mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-11 00:25:12 +00:00
feat: rehauled console (#3525)
* new console * move npm ci to angular build * rel path for assets * local grpc copy * login policy, rm clear views, features rel path * lock Co-authored-by: Livio Amstutz <[email protected]>
This commit is contained in:
co-authored by
Livio Amstutz
parent
00f7dbe875
commit
08ae39ae19
@@ -0,0 +1,59 @@
|
||||
<div *ngIf="type !== ActionKeysType.ORGSWITCHER && (isHandset$ | async) === false" class="action-keys-wrapper"
|
||||
[ngSwitch]="type" [ngClass]="{'without-margin': withoutMargin, 'no-contrast-mode': doNotUseContrast}">
|
||||
<div *ngSwitchCase="ActionKeysType.CLEAR" class="action-keys-row">
|
||||
<div class="action-key esc">
|
||||
<div class="key-overlay"></div>
|
||||
<span>ESC</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="ActionKeysType.ADD" class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>N</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="ActionKeysType.DELETE" class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span *ngIf="isMacLike || isIOS; else otherOS">⌘</span>
|
||||
</div>
|
||||
+
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>BS</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="ActionKeysType.DEACTIVATE" class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span *ngIf="isMacLike || isIOS; else otherOS">⌘</span>
|
||||
</div>
|
||||
+
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>↓</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="ActionKeysType.REACTIVATE" class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span *ngIf="isMacLike || isIOS; else otherOS">⌘</span>
|
||||
|
||||
</div>
|
||||
+
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>↑</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngSwitchCase="ActionKeysType.FILTER" class="action-keys-row">
|
||||
<div class="action-key">
|
||||
<div class="key-overlay"></div>
|
||||
<span>F</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #otherOS>
|
||||
<span>crtl</span>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,73 @@
|
||||
@use '@angular/material' as mat;
|
||||
|
||||
@mixin action-keys-theme($theme) {
|
||||
$primary: map-get($theme, primary);
|
||||
$background: map-get($theme, background);
|
||||
$foreground: map-get($theme, foreground);
|
||||
$accent: map-get($theme, accent);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$accent-color: mat.get-color-from-palette($primary, 500);
|
||||
$back: map-get($background, background);
|
||||
|
||||
.action-keys-wrapper {
|
||||
display: inline-block;
|
||||
padding-left: 0.5rem;
|
||||
margin-right: -0.5rem;
|
||||
|
||||
&.without-margin {
|
||||
padding: 0;
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
||||
.action-keys-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 -4px;
|
||||
|
||||
.action-key {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 11px;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
position: relative;
|
||||
margin: 0 4px;
|
||||
|
||||
&.esc {
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.key-overlay {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: mat.get-color-from-palette($primary, default-contrast);
|
||||
opacity: 0.2;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.span {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50% -50%);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.no-contrast-mode {
|
||||
.action-keys-row {
|
||||
.key-overlay {
|
||||
z-index: 0;
|
||||
background: if($is-dark-theme, #fff, #000);
|
||||
opacity: 0.15;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ActionKeysComponent } from './action-keys.component';
|
||||
|
||||
describe('ActionKeysComponent', () => {
|
||||
let component: ActionKeysComponent;
|
||||
let fixture: ComponentFixture<ActionKeysComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ActionKeysComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ActionKeysComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
|
||||
import { AfterViewInit, Component, EventEmitter, HostListener, Input, Output } from '@angular/core';
|
||||
import { map, Observable } from 'rxjs';
|
||||
|
||||
export enum ActionKeysType {
|
||||
ADD,
|
||||
DELETE,
|
||||
DEACTIVATE,
|
||||
REACTIVATE,
|
||||
FILTER,
|
||||
ORGSWITCHER,
|
||||
CLEAR,
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-action-keys',
|
||||
templateUrl: './action-keys.component.html',
|
||||
styleUrls: ['./action-keys.component.scss'],
|
||||
})
|
||||
export class ActionKeysComponent implements AfterViewInit {
|
||||
@Input() type: ActionKeysType = ActionKeysType.ADD;
|
||||
@Input() withoutMargin: boolean = false;
|
||||
@Input() doNotUseContrast: boolean = false;
|
||||
@Output() actionTriggered: EventEmitter<void> = new EventEmitter();
|
||||
@HostListener('document:keydown', ['$event'])
|
||||
handleKeyboardEvent(event: KeyboardEvent) {
|
||||
const tagname = (event.target as any)?.tagName;
|
||||
const exclude = ['input', 'textarea'];
|
||||
|
||||
if (exclude.indexOf(tagname.toLowerCase()) === -1) {
|
||||
switch (this.type) {
|
||||
case ActionKeysType.CLEAR:
|
||||
if (event.code === 'Escape') {
|
||||
event.preventDefault();
|
||||
this.actionTriggered.emit();
|
||||
}
|
||||
break;
|
||||
case ActionKeysType.ORGSWITCHER:
|
||||
if (event.key === '/') {
|
||||
this.actionTriggered.emit();
|
||||
}
|
||||
break;
|
||||
case ActionKeysType.ADD:
|
||||
if (event.code === 'KeyN') {
|
||||
this.actionTriggered.emit();
|
||||
}
|
||||
break;
|
||||
|
||||
case ActionKeysType.DELETE:
|
||||
if ((event.ctrlKey || event.metaKey) && event.code === 'Backspace') {
|
||||
this.actionTriggered.emit();
|
||||
}
|
||||
break;
|
||||
|
||||
case ActionKeysType.DEACTIVATE:
|
||||
if ((event.ctrlKey || event.metaKey) && event.code === 'ArrowDown') {
|
||||
event.preventDefault();
|
||||
this.actionTriggered.emit();
|
||||
}
|
||||
break;
|
||||
|
||||
case ActionKeysType.REACTIVATE:
|
||||
if ((event.ctrlKey || event.metaKey) && event.code === 'ArrowUp') {
|
||||
event.preventDefault();
|
||||
this.actionTriggered.emit();
|
||||
}
|
||||
break;
|
||||
|
||||
case ActionKeysType.FILTER:
|
||||
if (event.ctrlKey === false && event.code === 'KeyF') {
|
||||
this.actionTriggered.emit();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset).pipe(
|
||||
map((result) => {
|
||||
return result.matches;
|
||||
}),
|
||||
);
|
||||
|
||||
public ActionKeysType: any = ActionKeysType;
|
||||
|
||||
constructor(public breakpointObserver: BreakpointObserver) {}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
window.focus();
|
||||
if (document.activeElement) {
|
||||
(document.activeElement as any).blur();
|
||||
}
|
||||
}
|
||||
|
||||
public get isMacLike(): boolean {
|
||||
return /(Mac|iPhone|iPod|iPad)/i.test(navigator.userAgent);
|
||||
}
|
||||
|
||||
public get isIOS(): boolean {
|
||||
return /(iPhone|iPod|iPad)/i.test(navigator.userAgent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { ActionKeysComponent } from './action-keys.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [ActionKeysComponent],
|
||||
imports: [CommonModule],
|
||||
exports: [ActionKeysComponent],
|
||||
})
|
||||
export class ActionKeysModule {}
|
||||
Reference in New Issue
Block a user