mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 20:27:32 +00:00
fix(console): text color shades, ui fixes, state handle restore (#3698)
* common project grant dialog, info box, label policy * text styles, statehandler fix * dialog, btn alignment, i18n * search-user theme colors * filter formfield sizing * redirect uris * shortcut layout * settings grid type rest, shortcuts linking * login policy, reset button consistency, metadata * permission checks
This commit is contained in:
@@ -75,7 +75,7 @@ const routes: Routes = [
|
|||||||
loadChildren: () => import('./pages/actions/actions.module').then((m) => m.ActionsModule),
|
loadChildren: () => import('./pages/actions/actions.module').then((m) => m.ActionsModule),
|
||||||
canActivate: [AuthGuard, RoleGuard],
|
canActivate: [AuthGuard, RoleGuard],
|
||||||
data: {
|
data: {
|
||||||
roles: ['org.read'],
|
roles: ['org.action.read', 'org.flow.read'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -11,8 +11,6 @@
|
|||||||
$warn-color: mat.get-color-from-palette($warn, 500);
|
$warn-color: mat.get-color-from-palette($warn, 500);
|
||||||
$accent-color: mat.get-color-from-palette($accent, 500);
|
$accent-color: mat.get-color-from-palette($accent, 500);
|
||||||
$is-dark-theme: map-get($theme, is-dark);
|
$is-dark-theme: map-get($theme, is-dark);
|
||||||
$back: map-get($background, background);
|
|
||||||
$base: map-get($foreground, base);
|
|
||||||
|
|
||||||
.main-container {
|
.main-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { BreakpointObserver } from '@angular/cdk/layout';
|
import { BreakpointObserver } from '@angular/cdk/layout';
|
||||||
import { OverlayContainer } from '@angular/cdk/overlay';
|
import { OverlayContainer } from '@angular/cdk/overlay';
|
||||||
import { DOCUMENT, ViewportScroller } from '@angular/common';
|
import { DOCUMENT, ViewportScroller } from '@angular/common';
|
||||||
import { Component, HostBinding, HostListener, Inject, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
import { Component, HostBinding, HostListener, Inject, OnDestroy, ViewChild } from '@angular/core';
|
||||||
import { MatIconRegistry } from '@angular/material/icon';
|
import { MatIconRegistry } from '@angular/material/icon';
|
||||||
import { MatDrawer } from '@angular/material/sidenav';
|
import { MatDrawer } from '@angular/material/sidenav';
|
||||||
import { DomSanitizer } from '@angular/platform-browser';
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
@@ -19,8 +19,7 @@ import { KeyboardShortcutsService } from './services/keyboard-shortcuts/keyboard
|
|||||||
import { ManagementService } from './services/mgmt.service';
|
import { ManagementService } from './services/mgmt.service';
|
||||||
import { NavigationService } from './services/navigation.service';
|
import { NavigationService } from './services/navigation.service';
|
||||||
import { OverlayWorkflowService } from './services/overlay/overlay-workflow.service';
|
import { OverlayWorkflowService } from './services/overlay/overlay-workflow.service';
|
||||||
import { IntroWorkflowOverlays } from './services/overlay/workflows';
|
import { StorageService } from './services/storage.service';
|
||||||
import { StorageLocation, StorageService } from './services/storage.service';
|
|
||||||
import { ThemeService } from './services/theme.service';
|
import { ThemeService } from './services/theme.service';
|
||||||
import { UpdateService } from './services/update.service';
|
import { UpdateService } from './services/update.service';
|
||||||
|
|
||||||
@@ -30,7 +29,7 @@ import { UpdateService } from './services/update.service';
|
|||||||
styleUrls: ['./app.component.scss'],
|
styleUrls: ['./app.component.scss'],
|
||||||
animations: [toolbarAnimation, ...navAnimations, accountCard, routeAnimations, adminLineAnimation],
|
animations: [toolbarAnimation, ...navAnimations, accountCard, routeAnimations, adminLineAnimation],
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit, OnDestroy {
|
export class AppComponent implements OnDestroy {
|
||||||
@ViewChild('drawer') public drawer!: MatDrawer;
|
@ViewChild('drawer') public drawer!: MatDrawer;
|
||||||
public isHandset$: Observable<boolean> = this.breakpointObserver.observe('(max-width: 599px)').pipe(
|
public isHandset$: Observable<boolean> = this.breakpointObserver.observe('(max-width: 599px)').pipe(
|
||||||
map((result) => {
|
map((result) => {
|
||||||
@@ -218,7 +217,10 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
.then((org) => {
|
.then((org) => {
|
||||||
this.org = org;
|
this.org = org;
|
||||||
|
|
||||||
this.startIntroWorkflow();
|
this.loadPrivateLabelling();
|
||||||
|
|
||||||
|
// TODO add when console storage is implemented
|
||||||
|
// this.startIntroWorkflow();
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.router.navigate(['/users/me']);
|
this.router.navigate(['/users/me']);
|
||||||
@@ -235,21 +237,19 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private startIntroWorkflow(): void {
|
// TODO implement Console storage
|
||||||
setTimeout(() => {
|
|
||||||
const cb = () => {
|
|
||||||
this.storageService.setItem('intro-dismissed', true, StorageLocation.local);
|
|
||||||
};
|
|
||||||
const dismissed = this.storageService.getItem('intro-dismissed', StorageLocation.local);
|
|
||||||
if (!dismissed) {
|
|
||||||
this.workflowService.startWorkflow(IntroWorkflowOverlays, cb);
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ngOnInit(): void {
|
// private startIntroWorkflow(): void {
|
||||||
this.loadPrivateLabelling();
|
// setTimeout(() => {
|
||||||
}
|
// const cb = () => {
|
||||||
|
// this.storageService.setItem('intro-dismissed', true, StorageLocation.local);
|
||||||
|
// };
|
||||||
|
// const dismissed = this.storageService.getItem('intro-dismissed', StorageLocation.local);
|
||||||
|
// if (!dismissed) {
|
||||||
|
// this.workflowService.startWorkflow(IntroWorkflowOverlays, cb);
|
||||||
|
// }
|
||||||
|
// }, 1000);
|
||||||
|
// }
|
||||||
|
|
||||||
public ngOnDestroy(): void {
|
public ngOnDestroy(): void {
|
||||||
this.destroy$.next();
|
this.destroy$.next();
|
||||||
|
@@ -63,6 +63,11 @@
|
|||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter-select-method .mat-select {
|
||||||
|
height: 36px;
|
||||||
|
padding: 7px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.subquery {
|
.subquery {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -82,6 +87,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.filter-input-value {
|
.filter-input-value {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
height: 36px;
|
height: 36px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
@@ -96,7 +96,7 @@
|
|||||||
margin: 0.5rem 0;
|
margin: 0.5rem 0;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: map-get($foreground, base);
|
color: map-get($foreground, text);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@@ -57,7 +57,7 @@
|
|||||||
|
|
||||||
.org-link {
|
.org-link {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: map-get($foreground, base);
|
color: map-get($foreground, text);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 0.5rem 0.75rem 0.5rem 0.75rem;
|
padding: 0.5rem 0.75rem 0.5rem 0.75rem;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
.org-switch-button {
|
.org-switch-button {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border: none;
|
border: none;
|
||||||
color: map-get($foreground, base);
|
color: map-get($foreground, text);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
position: relative;
|
position: relative;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
|
|
||||||
svg {
|
svg {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
fill: map-get($foreground, base);
|
fill: map-get($foreground, text);
|
||||||
height: 1.25rem;
|
height: 1.25rem;
|
||||||
width: 1.25rem;
|
width: 1.25rem;
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
|
|
||||||
.breadcrumb-link {
|
.breadcrumb-link {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: map-get($foreground, base);
|
color: map-get($foreground, text);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 0.5rem 0.75rem 0.5rem 0.75rem;
|
padding: 0.5rem 0.75rem 0.5rem 0.75rem;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
|
@@ -44,7 +44,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: map-get($foreground, base);
|
color: map-get($foreground, text);
|
||||||
|
|
||||||
&.top-left {
|
&.top-left {
|
||||||
&::before {
|
&::before {
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin: 0.5rem 0;
|
margin: 0.5rem 0;
|
||||||
|
box-shadow: 0 2px 5px rgb(0 0 0 / 10%);
|
||||||
|
|
||||||
&.fit {
|
&.fit {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<h1 mat-dialog-title>
|
<h1 mat-dialog-title>
|
||||||
<span>{{data.titleKey | translate}} {{data?.number}}</span>
|
<span>{{ data.titleKey | translate }} {{ data?.number }}</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p class="desc cnsl-secondary-text">{{data.descKey | translate}}</p>
|
<p class="desc cnsl-secondary-text">{{ data.descKey | translate }}</p>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ data.labelKey | translate }}</cnsl-label>
|
<cnsl-label>{{ data.labelKey | translate }}</cnsl-label>
|
||||||
@@ -9,12 +9,11 @@
|
|||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
</div>
|
</div>
|
||||||
<div mat-dialog-actions class="action">
|
<div mat-dialog-actions class="action">
|
||||||
<button color="primary" mat-stroked-button class="ok-button" (click)="closeDialog()">
|
<button color="primary" mat-stroked-button (click)="closeDialog()">
|
||||||
{{'ACTIONS.CLOSE' | translate}}
|
{{ 'ACTIONS.CLOSE' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button [disabled]="!name" cdkFocusInitial color="primary" mat-raised-button class="ok-button"
|
<button [disabled]="!name" cdkFocusInitial color="primary" mat-raised-button (click)="closeDialog(name)">
|
||||||
(click)="closeDialog(name)">
|
{{ 'ACTIONS.RENAME' | translate }}
|
||||||
{{'ACTIONS.RENAME' | translate}}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -15,10 +15,6 @@ h1 {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
.ok-button {
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
}
|
}
|
||||||
|
@@ -1,25 +1,29 @@
|
|||||||
<div class="paginator-wrapper">
|
<div class="paginator-wrapper">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<p class="length"><span>{{length}} </span>{{'PAGINATOR.COUNT' | translate}}</p>
|
<p class="length">
|
||||||
|
<span>{{ length }} </span>{{ 'PAGINATOR.COUNT' | translate }}
|
||||||
|
</p>
|
||||||
<p class="ts cnsl-secondary-text" *ngIf="timestamp">
|
<p class="ts cnsl-secondary-text" *ngIf="timestamp">
|
||||||
{{(timestamp | timestampToDate)| localizedDate: 'EEEE dd. MMM YYYY, HH:mm'}}
|
{{ timestamp | timestampToDate | localizedDate: 'EEEE dd. MMM YYYY, HH:mm' }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<span class="fill-space"></span>
|
<span class="fill-space"></span>
|
||||||
<span class="pos cnsl-secondary-text" *ngIf="!hidePagination">{{pageIndex * pageSize}} - {{pageIndex * pageSize +
|
<span class="pos cnsl-secondary-text" *ngIf="!hidePagination"
|
||||||
pageSize}} </span>
|
>{{ pageIndex * pageSize }} - {{ pageIndex * pageSize + pageSize }}
|
||||||
|
</span>
|
||||||
<div class="row" *ngIf="!hidePagination">
|
<div class="row" *ngIf="!hidePagination">
|
||||||
<cnsl-form-field class="size" appearance="outline">
|
<cnsl-form-field class="size" appearance="outline">
|
||||||
<mat-select [(ngModel)]="pageSize" (selectionChange)="emitChange()">
|
<mat-select class="paginator-select" [(ngModel)]="pageSize" (selectionChange)="emitChange()">
|
||||||
<mat-option *ngFor="let sizeOption of pageSizeOptions" [value]="sizeOption">
|
<mat-option *ngFor="let sizeOption of pageSizeOptions" [value]="sizeOption">
|
||||||
{{sizeOption}}
|
{{ sizeOption }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<button *ngIf="previousPossible" (click)="previous()" [disabled]="!previousPossible"
|
<button *ngIf="previousPossible" (click)="previous()" [disabled]="!previousPossible" mat-stroked-button>
|
||||||
mat-stroked-button>{{'PAGINATOR.PREVIOUS' |
|
{{ 'PAGINATOR.PREVIOUS' | translate }}
|
||||||
translate}}</button>
|
</button>
|
||||||
<button *ngIf="nextPossible" (click)="next()" [disabled]="!nextPossible" mat-stroked-button>{{'PAGINATOR.NEXT' |
|
<button *ngIf="nextPossible" (click)="next()" [disabled]="!nextPossible" mat-stroked-button>
|
||||||
translate}}</button>
|
{{ 'PAGINATOR.NEXT' | translate }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -50,7 +50,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* stylelint-disable */
|
/* stylelint-disable */
|
||||||
::ng-deep .mat-select {
|
::ng-deep .paginator-select.mat-select {
|
||||||
min-width: 60px;
|
min-width: 60px;
|
||||||
height: 36px !important;
|
height: 36px !important;
|
||||||
padding-top: 8px !important;
|
padding-top: 8px !important;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<h1 mat-dialog-title class="title">
|
<h1 class="title">
|
||||||
<span>{{ data.title | translate }}</span>
|
<span>{{ data.title | translate }}</span>
|
||||||
</h1>
|
</h1>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
.title {
|
.title {
|
||||||
font-size: 1.5rem;
|
font-size: 1.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.desc {
|
.desc {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-field {
|
.form-field {
|
||||||
|
@@ -19,6 +19,7 @@ export class DialogAddTypeComponent {
|
|||||||
|
|
||||||
constructor(public dialogRef: MatDialogRef<DialogAddTypeComponent>, @Inject(MAT_DIALOG_DATA) public data: any) {
|
constructor(public dialogRef: MatDialogRef<DialogAddTypeComponent>, @Inject(MAT_DIALOG_DATA) public data: any) {
|
||||||
this.availableMfaTypes = data.types;
|
this.availableMfaTypes = data.types;
|
||||||
|
this.newMfaType = data.types && data.types[0] ? data.types[0] : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeDialog(): void {
|
public closeDialog(): void {
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
<button
|
<button
|
||||||
mat-stroked-button
|
mat-stroked-button
|
||||||
class="new-mfa cnsl-action-button"
|
class="new-mfa cnsl-action-button"
|
||||||
[disabled]="disabled"
|
[disabled]="disabled || availableSelection.length === 0"
|
||||||
(click)="!disabled ? addMfa() : null"
|
(click)="!disabled ? addMfa() : null"
|
||||||
>
|
>
|
||||||
<mat-icon class="icon">add</mat-icon>
|
<mat-icon class="icon">add</mat-icon>
|
||||||
|
@@ -35,7 +35,7 @@
|
|||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
&:not(:hover) {
|
&:not(:hover) {
|
||||||
color: var(--grey);
|
color: map-get($foreground, secondary-text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -105,27 +105,12 @@ export class FactorTableComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public addMfa(): void {
|
public addMfa(): void {
|
||||||
let selection: any[] = [];
|
|
||||||
|
|
||||||
if (this.componentType === LoginMethodComponentType.MultiFactor) {
|
|
||||||
selection = [MultiFactorType.MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION];
|
|
||||||
} else if (this.componentType === LoginMethodComponentType.SecondFactor) {
|
|
||||||
selection = [SecondFactorType.SECOND_FACTOR_TYPE_U2F, SecondFactorType.SECOND_FACTOR_TYPE_OTP];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.mfas.forEach((mfa) => {
|
|
||||||
const index = selection.findIndex((sel) => sel === mfa);
|
|
||||||
if (index > -1) {
|
|
||||||
selection.splice(index, 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const dialogRef = this.dialog.open(DialogAddTypeComponent, {
|
const dialogRef = this.dialog.open(DialogAddTypeComponent, {
|
||||||
data: {
|
data: {
|
||||||
title: 'MFA.CREATE.TITLE',
|
title: 'MFA.CREATE.TITLE',
|
||||||
desc: 'MFA.CREATE.DESCRIPTION',
|
desc: 'MFA.CREATE.DESCRIPTION',
|
||||||
componentType: this.componentType,
|
componentType: this.componentType,
|
||||||
types: selection,
|
types: this.availableSelection,
|
||||||
},
|
},
|
||||||
width: '400px',
|
width: '400px',
|
||||||
});
|
});
|
||||||
@@ -244,4 +229,17 @@ export class FactorTableComponent implements OnInit {
|
|||||||
this.getData();
|
this.getData();
|
||||||
}, to);
|
}, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get availableSelection(): Array<MultiFactorType | SecondFactorType> {
|
||||||
|
const allTypes: MultiFactorType[] | SecondFactorType[] =
|
||||||
|
this.componentType === LoginMethodComponentType.MultiFactor
|
||||||
|
? [MultiFactorType.MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION]
|
||||||
|
: this.componentType === LoginMethodComponentType.SecondFactor
|
||||||
|
? [SecondFactorType.SECOND_FACTOR_TYPE_U2F, SecondFactorType.SECOND_FACTOR_TYPE_OTP]
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const filtered = (allTypes as Array<MultiFactorType | SecondFactorType>).filter((type) => !this.mfas.includes(type));
|
||||||
|
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -122,7 +122,6 @@ export class LoginPolicyComponent implements OnInit {
|
|||||||
)
|
)
|
||||||
.pipe(take(1))
|
.pipe(take(1))
|
||||||
.subscribe((allowed) => {
|
.subscribe((allowed) => {
|
||||||
console.log(allowed);
|
|
||||||
if (allowed) {
|
if (allowed) {
|
||||||
this.lifetimeForm.enable();
|
this.lifetimeForm.enable();
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,7 @@
|
|||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content">
|
<div class="message-text-content">
|
||||||
<cnsl-edit-text
|
<cnsl-edit-text
|
||||||
[chips]="chips[currentType]"
|
[chips]="chips[currentType]"
|
||||||
[disabled]="(canWrite$ | async) === false"
|
[disabled]="(canWrite$ | async) === false"
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
></cnsl-edit-text>
|
></cnsl-edit-text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="actions">
|
<div class="message-text-actions">
|
||||||
<button
|
<button
|
||||||
class="reset-button"
|
class="reset-button"
|
||||||
*ngIf="(getCustomInitMessageTextMap$ | async) && (getCustomInitMessageTextMap$ | async)?.isDefault === false"
|
*ngIf="(getCustomInitMessageTextMap$ | async) && (getCustomInitMessageTextMap$ | async)?.isDefault === false"
|
||||||
|
@@ -40,11 +40,11 @@
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.message-text-content {
|
||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions {
|
.message-text-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
|
@@ -1,11 +1,19 @@
|
|||||||
<!-- <cnsl-card
|
|
||||||
title="{{ 'POLICY.PWD_LOCKOUT.TITLE' | translate }}"
|
|
||||||
description="{{ 'POLICY.PWD_LOCKOUT.DESCRIPTION' | translate }}"
|
|
||||||
> -->
|
|
||||||
<h2>{{ 'POLICY.PWD_LOCKOUT.TITLE' | translate }}</h2>
|
<h2>{{ 'POLICY.PWD_LOCKOUT.TITLE' | translate }}</h2>
|
||||||
<p class="cnsl-secondary-text">{{ 'POLICY.PWD_LOCKOUT.DESCRIPTION' | translate }}</p>
|
<p class="cnsl-secondary-text">{{ 'POLICY.PWD_LOCKOUT.DESCRIPTION' | translate }}</p>
|
||||||
|
|
||||||
<cnsl-info-section class="default" *ngIf="isDefault"> {{ 'POLICY.DEFAULTLABEL' | translate }}</cnsl-info-section>
|
<ng-template cnslHasRole [hasRole]="['policy.delete']">
|
||||||
|
<button
|
||||||
|
*ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
|
||||||
|
matTooltip="{{ 'POLICY.RESET' | translate }}"
|
||||||
|
color="warn"
|
||||||
|
(click)="resetPolicy()"
|
||||||
|
mat-stroked-button
|
||||||
|
>
|
||||||
|
{{ 'POLICY.RESET' | translate }}
|
||||||
|
</button>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<!-- <cnsl-info-section class="default" *ngIf="isDefault"> {{ 'POLICY.DEFAULTLABEL' | translate }}</cnsl-info-section> -->
|
||||||
|
|
||||||
<cnsl-card *ngIf="lockoutData">
|
<cnsl-card *ngIf="lockoutData">
|
||||||
<div class="lockout-content">
|
<div class="lockout-content">
|
||||||
@@ -38,17 +46,4 @@
|
|||||||
>
|
>
|
||||||
{{ 'ACTIONS.SAVE' | translate }}
|
{{ 'ACTIONS.SAVE' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<ng-template cnslHasRole [hasRole]="['policy.delete']">
|
|
||||||
<button
|
|
||||||
*ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
|
|
||||||
matTooltip="{{ 'POLICY.RESET' | translate }}"
|
|
||||||
color="warn"
|
|
||||||
(click)="resetPolicy()"
|
|
||||||
mat-stroked-button
|
|
||||||
>
|
|
||||||
{{ 'POLICY.RESET' | translate }}
|
|
||||||
</button>
|
|
||||||
</ng-template>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- </cnsl-card> -->
|
|
||||||
|
@@ -1,7 +1,21 @@
|
|||||||
<h2>{{ 'POLICY.PRIVACY_POLICY.TITLE' | translate }}</h2>
|
<h2>{{ 'POLICY.PRIVACY_POLICY.TITLE' | translate }}</h2>
|
||||||
<p class="cnsl-secondary-text">{{ 'POLICY.PRIVACY_POLICY.DESCRIPTION' | translate }}</p>
|
<p class="cnsl-secondary-text">{{ 'POLICY.PRIVACY_POLICY.DESCRIPTION' | translate }}</p>
|
||||||
|
|
||||||
<cnsl-info-section *ngIf="isDefault"> {{ 'POLICY.DEFAULTLABEL' | translate }}</cnsl-info-section>
|
<ng-container *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault">
|
||||||
|
<ng-template cnslHasRole [hasRole]="['policy.delete']">
|
||||||
|
<button
|
||||||
|
color="primary"
|
||||||
|
matTooltip="{{ 'POLICY.RESET' | translate }}"
|
||||||
|
color="warn"
|
||||||
|
(click)="resetDefault()"
|
||||||
|
mat-stroked-button
|
||||||
|
>
|
||||||
|
{{ 'POLICY.RESET' | translate }}
|
||||||
|
</button>
|
||||||
|
</ng-template>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- <cnsl-info-section *ngIf="isDefault"> {{ 'POLICY.DEFAULTLABEL' | translate }}</cnsl-info-section> -->
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<form *ngIf="form" [formGroup]="form" class="policy-content">
|
<form *ngIf="form" [formGroup]="form" class="policy-content">
|
||||||
@@ -26,17 +40,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="policy-actions">
|
<div class="policy-actions">
|
||||||
<button
|
|
||||||
*ngIf="privacyPolicy && privacyPolicy.isDefault === false"
|
|
||||||
class="reset-button"
|
|
||||||
[disabled]="(canWrite$ | async) === false"
|
|
||||||
(click)="resetDefault()"
|
|
||||||
color="warn"
|
|
||||||
type="submit"
|
|
||||||
mat-stroked-button
|
|
||||||
>
|
|
||||||
<i class="las la-history"></i> {{ 'ACTIONS.RESETDEFAULT' | translate }}
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
class="save-button"
|
class="save-button"
|
||||||
[disabled]="(canWrite$ | async) === false"
|
[disabled]="(canWrite$ | async) === false"
|
||||||
|
@@ -61,18 +61,8 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
|
||||||
.save-button,
|
.save-button {
|
||||||
.reset-button {
|
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0 1rem 0 0;
|
margin: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.reset-button {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
i {
|
|
||||||
margin-bottom: 3px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
transform: scale(0.9);
|
transform: scale(0.9);
|
||||||
color: map-get($foreground, base);
|
color: map-get($foreground, text);
|
||||||
|
|
||||||
* {
|
* {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@@ -54,7 +54,7 @@
|
|||||||
<ng-template cnslHasRole [hasRole]="['policy.delete']">
|
<ng-template cnslHasRole [hasRole]="['policy.delete']">
|
||||||
<button
|
<button
|
||||||
class="pl-action-button"
|
class="pl-action-button"
|
||||||
*ngIf="view === View.CURRENT && serviceType === PolicyComponentServiceType.MGMT && !isDefault"
|
*ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
|
||||||
matTooltip="{{ 'POLICY.RESET' | translate }}"
|
matTooltip="{{ 'POLICY.RESET' | translate }}"
|
||||||
color="warn"
|
color="warn"
|
||||||
(click)="removePolicy()"
|
(click)="removePolicy()"
|
||||||
|
@@ -93,6 +93,11 @@
|
|||||||
.pl-action-button {
|
.pl-action-button {
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,20 +1,25 @@
|
|||||||
<h1 class="title">{{'PROJECT.PAGES.PRIVATELABEL.DIALOG.TITLE' | translate}} {{data?.number}}</h1>
|
<h1 class="title">{{ 'PROJECT.PAGES.PRIVATELABEL.DIALOG.TITLE' | translate }} {{ data?.number }}</h1>
|
||||||
<p class="desc cnsl-secondary-text">{{'PROJECT.PAGES.PRIVATELABEL.DIALOG.DESCRIPTION' | translate}}</p>
|
<p class="desc cnsl-secondary-text">{{ 'PROJECT.PAGES.PRIVATELABEL.DIALOG.DESCRIPTION' | translate }}</p>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
<mat-radio-group class="example-radio-group" [(ngModel)]="setting">
|
<mat-radio-group class="project-radio-group" [(ngModel)]="setting">
|
||||||
<mat-radio-button class="radio-button" *ngFor="let selection of settings" [value]="selection">
|
<mat-radio-button class="radio-button" *ngFor="let selection of settings" [value]="selection">
|
||||||
<span class="label">{{'PROJECT.PAGES.PRIVATELABEL.'+selection+'.TITLE' | translate}}</span>
|
<span class="label">{{ 'PROJECT.PAGES.PRIVATELABEL.' + selection + '.TITLE' | translate }}</span>
|
||||||
</mat-radio-button>
|
</mat-radio-button>
|
||||||
</mat-radio-group>
|
</mat-radio-group>
|
||||||
<cnsl-info-section class="info">{{'PROJECT.PAGES.PRIVATELABEL.'+setting+'.DESC' | translate}}</cnsl-info-section>
|
<cnsl-info-section class="info">{{ 'PROJECT.PAGES.PRIVATELABEL.' + setting + '.DESC' | translate }}</cnsl-info-section>
|
||||||
</div>
|
</div>
|
||||||
<div mat-dialog-actions class="action">
|
<div mat-dialog-actions class="action">
|
||||||
<button cdkFocusInitial mat-stroked-button class="ok-button" (click)="closeDialog()">
|
<button cdkFocusInitial mat-stroked-button (click)="closeDialog()">
|
||||||
{{'ACTIONS.CLOSE' | translate}}
|
{{ 'ACTIONS.CLOSE' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button [disabled]="setting === undefined" cdkFocusInitial color="primary" mat-raised-button class="ok-button"
|
<button
|
||||||
(click)="closeDialog(setting)">
|
[disabled]="setting === undefined"
|
||||||
{{'ACTIONS.OK' | translate}}
|
cdkFocusInitial
|
||||||
|
color="primary"
|
||||||
|
mat-raised-button
|
||||||
|
(click)="closeDialog(setting)"
|
||||||
|
>
|
||||||
|
{{ 'ACTIONS.OK' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -7,11 +7,16 @@
|
|||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-button {
|
.project-radio-group {
|
||||||
margin: 0.5rem 0;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
.label {
|
.radio-button {
|
||||||
white-space: normal;
|
margin: 0.5rem 0;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,10 +29,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
.ok-button {
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
<div class="found" *ngIf="users.length > 0">
|
<div class="user-autocomplete-found" *ngIf="users.length > 0">
|
||||||
<!-- <span class="found-label cnsl-secondary-text">{{'USER.SEARCH.FOUND' | translate}}:</span> -->
|
|
||||||
<div class="found-user-row" *ngFor="let user of users; index as i">
|
<div class="found-user-row" *ngFor="let user of users; index as i">
|
||||||
<div class="circle">
|
<div class="circle">
|
||||||
<cnsl-avatar
|
<cnsl-avatar
|
||||||
@@ -109,9 +108,11 @@
|
|||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-autocomplete>
|
</mat-autocomplete>
|
||||||
|
|
||||||
<span class="target-desc">
|
<span class="user-autocomplete-target-desc">
|
||||||
{{ 'USER.TARGET.SELF' | translate }}
|
{{ 'USER.TARGET.SELF' | translate }}
|
||||||
<a (click)="changeTarget()">{{ 'USER.TARGET.CLICKHERE' | translate }}</a>
|
<a (click)="changeTarget()"
|
||||||
|
><strong>{{ 'USER.TARGET.CLICKHERE' | translate }}</strong></a
|
||||||
|
>
|
||||||
</span>
|
</span>
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
</div>
|
</div>
|
||||||
@@ -122,9 +123,11 @@
|
|||||||
<cnsl-form-field class="user-create-form-field more-space">
|
<cnsl-form-field class="user-create-form-field more-space">
|
||||||
<cnsl-label>{{ 'USER.SEARCH.ADDITIONAL-EXTERNAL' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.SEARCH.ADDITIONAL-EXTERNAL' | translate }}</cnsl-label>
|
||||||
<input cnslInput type="text" [formControl]="globalLoginNameControl" placeholder="example@externaldomain.com" />
|
<input cnslInput type="text" [formControl]="globalLoginNameControl" placeholder="example@externaldomain.com" />
|
||||||
<span class="target-desc">
|
<span class="user-autocomplete-target-desc">
|
||||||
{{ (target === UserTarget.SELF ? 'USER.TARGET.SELF' : 'USER.TARGET.EXTERNAL') | translate }}
|
{{ (target === UserTarget.SELF ? 'USER.TARGET.SELF' : 'USER.TARGET.EXTERNAL') | translate }}
|
||||||
<a (click)="changeTarget()">{{ 'USER.TARGET.CLICKHERE' | translate }}</a>
|
<a (click)="changeTarget()"
|
||||||
|
><strong>{{ 'USER.TARGET.CLICKHERE' | translate }}</strong></a
|
||||||
|
>
|
||||||
</span>
|
</span>
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
|
@@ -1,15 +1,79 @@
|
|||||||
.target-desc {
|
@use '@angular/material' as mat;
|
||||||
font-size: 14px;
|
|
||||||
display: block;
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
|
|
||||||
a {
|
@mixin search-user-autocomplete-theme($theme) {
|
||||||
color: #4072b4;
|
$primary: map-get($theme, primary);
|
||||||
|
$primary-color: mat.get-color-from-palette($primary, 500);
|
||||||
|
$background: map-get($theme, background);
|
||||||
|
$foreground: map-get($theme, foreground);
|
||||||
|
$secondary-text: map-get($foreground, secondary-text);
|
||||||
|
|
||||||
&:hover {
|
.user-autocomplete-found {
|
||||||
cursor: pointer;
|
margin: 0.5rem 0;
|
||||||
color: #6992c9;
|
border-radius: 0.5rem;
|
||||||
text-decoration: underline;
|
padding: 0.5rem 0;
|
||||||
|
max-width: 500px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.add-user-row {
|
||||||
|
margin-left: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.found-user-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.25rem 0;
|
||||||
|
|
||||||
|
button {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
button {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.found-label {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-name-column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.smaller {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fill-space {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-user-dl-btn {
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
|
||||||
|
&:not(:hover) {
|
||||||
|
color: $secondary-text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-autocomplete-target-desc {
|
||||||
|
font-size: 14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $primary-color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
color: mat.get-color-from-palette($primary, 400);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,60 +100,6 @@
|
|||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.found {
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
max-width: 500px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
.add-user-row {
|
|
||||||
margin-left: -4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.found-user-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0.25rem 0;
|
|
||||||
|
|
||||||
button {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
button {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.found-label {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-name-column {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
.smaller {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fill-space {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-user-dl-btn {
|
|
||||||
transition: color 0.2s ease;
|
|
||||||
|
|
||||||
&:not(:hover) {
|
|
||||||
color: var(--grey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.circle {
|
.circle {
|
||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
|
@@ -2,10 +2,10 @@ export interface SettingLinks {
|
|||||||
i18nTitle: string;
|
i18nTitle: string;
|
||||||
i18nDesc: string;
|
i18nDesc: string;
|
||||||
iamRouterLink: any;
|
iamRouterLink: any;
|
||||||
orgRouterLink: any;
|
orgRouterLink?: any;
|
||||||
queryParams: any;
|
queryParams: any;
|
||||||
iamWithRole: string[];
|
iamWithRole?: string[];
|
||||||
orgWithRole: string[];
|
orgWithRole?: string[];
|
||||||
icon?: string;
|
icon?: string;
|
||||||
svgIcon?: string;
|
svgIcon?: string;
|
||||||
color: string;
|
color: string;
|
||||||
@@ -49,12 +49,10 @@ export const PRIVACY_POLICY: SettingLinks = {
|
|||||||
|
|
||||||
export const NOTIFICATION_GROUP: SettingLinks = {
|
export const NOTIFICATION_GROUP: SettingLinks = {
|
||||||
i18nTitle: 'SETTINGS.GROUPS.NOTIFICATIONS',
|
i18nTitle: 'SETTINGS.GROUPS.NOTIFICATIONS',
|
||||||
i18nDesc: '',
|
i18nDesc: 'SETTINGS.LIST.NOTIFICATIONS_DESC',
|
||||||
iamRouterLink: ['/settings'],
|
iamRouterLink: ['/settings'],
|
||||||
orgRouterLink: ['/org-settings'],
|
|
||||||
queryParams: { id: 'notifications' },
|
queryParams: { id: 'notifications' },
|
||||||
iamWithRole: ['iam.policy.read'],
|
iamWithRole: ['iam.policy.read'],
|
||||||
orgWithRole: ['policy.read'],
|
|
||||||
icon: 'las la-bell',
|
icon: 'las la-bell',
|
||||||
color: 'red',
|
color: 'red',
|
||||||
};
|
};
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { animate, style, transition, trigger } from '@angular/animations';
|
import { animate, style, transition, trigger } from '@angular/animations';
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { PolicyComponentServiceType } from 'src/app/modules/policies/policy-component-types.enum';
|
import { PolicyComponentServiceType } from 'src/app/modules/policies/policy-component-types.enum';
|
||||||
|
|
||||||
import { SETTINGLINKS, SettingLinks } from './settinglinks';
|
import { SETTINGLINKS, SettingLinks } from './settinglinks';
|
||||||
@@ -35,9 +35,15 @@ import { SETTINGLINKS, SettingLinks } from './settinglinks';
|
|||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class SettingsGridComponent {
|
export class SettingsGridComponent implements OnInit {
|
||||||
@Input() public type!: PolicyComponentServiceType;
|
@Input() public type!: PolicyComponentServiceType;
|
||||||
@Input() public tag: string = '';
|
@Input() public tag: string = '';
|
||||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||||
public SETTINGS: SettingLinks[] = SETTINGLINKS;
|
public SETTINGS: SettingLinks[] = SETTINGLINKS;
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.SETTINGS = this.SETTINGS.filter((setting) =>
|
||||||
|
this.type === PolicyComponentServiceType.MGMT ? !!setting.orgRouterLink : !!setting.iamRouterLink,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,99 +1,132 @@
|
|||||||
<div cdkDropListGroup>
|
<div cdkDropListGroup>
|
||||||
<div class="shortcut-container">
|
<div class="shortcut-container">
|
||||||
<div class="shortcut-title-container">
|
<div class="shortcut-title-container">
|
||||||
<h2>{{'HOME.SHORTCUTS.SHORTCUTS' | translate}}</h2>
|
<h2>{{ 'HOME.SHORTCUTS.SHORTCUTS' | translate }}</h2>
|
||||||
<button [matTooltip]="(editState ? 'ACTIONS.CLOSE' : 'ACTIONS.EDIT') | translate" class="shortcut-btn"
|
<button
|
||||||
(click)="editState = !editState" mat-icon-button>
|
[matTooltip]="(editState ? 'ACTIONS.SAVE' : 'ACTIONS.EDIT') | translate"
|
||||||
<i *ngIf="!editState" class=" las la-pen"></i>
|
class="shortcut-btn"
|
||||||
<mat-icon *ngIf="editState">close</mat-icon>
|
(click)="editState = !editState"
|
||||||
|
mat-icon-button
|
||||||
|
>
|
||||||
|
<i *ngIf="!editState" class="las la-pen"></i>
|
||||||
|
<i *ngIf="editState" class="las la-check"></i>
|
||||||
</button>
|
</button>
|
||||||
<button matTooltip="{{'ACTIONS.RESETDEFAULT' | translate}}" (click)="reset()" *ngIf="editState" mat-icon-button>
|
<button matTooltip="{{ 'ACTIONS.RESETDEFAULT' | translate }}" (click)="reset()" *ngIf="editState" mat-icon-button>
|
||||||
<i *ngIf="editState" class="las la-undo-alt"></i>
|
<i *ngIf="editState" class="las la-undo-alt"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="shortcut-list-row">
|
<div class="shortcut-list-row">
|
||||||
<div cdkDropList [cdkDropListData]="main" class="shortcut-list" (cdkDropListDropped)="drop($event, 'main')">
|
<div cdkDropList [cdkDropListData]="main" class="shortcut-list" (cdkDropListDropped)="drop($event, 'main')">
|
||||||
<p *ngIf="editState" class="shortcut-desc">{{'HOME.SHORTCUTS.REORDER' | translate}}</p>
|
<p *ngIf="editState" class="shortcut-desc cnsl-secondary-text">{{ 'HOME.SHORTCUTS.REORDER' | translate }}</p>
|
||||||
<ng-container *ngFor="let shortcut of main">
|
<ng-container *ngFor="let shortcut of main">
|
||||||
<ng-template cnslHasRole [hasRole]="shortcut.withRole">
|
<ng-template cnslHasRole [hasRole]="shortcut.withRole">
|
||||||
<a [routerLink]="!editState ? shortcut.routerLink : null" class="shortcut-box"
|
<a
|
||||||
[ngClass]="{'edit-state': editState && !shortcut.disabled, 'disabled': editState && shortcut.disabled}"
|
[routerLink]="!editState ? shortcut.routerLink : null"
|
||||||
cdkDrag [cdkDragDisabled]="shortcut.disabled || !editState">
|
[queryParams]="shortcut.queryParams ? shortcut.queryParams : null"
|
||||||
<div class="shortcuts-avatar {{shortcut.color}}">
|
class="shortcut-box"
|
||||||
|
[ngClass]="{ 'edit-state': editState && !shortcut.disabled, disabled: editState && shortcut.disabled }"
|
||||||
|
cdkDrag
|
||||||
|
[cdkDragDisabled]="shortcut.disabled || !editState"
|
||||||
|
>
|
||||||
|
<div class="shortcuts-avatar {{ shortcut.color }}">
|
||||||
<mat-icon *ngIf="shortcut.svgIcon" class="icon" [svgIcon]="shortcut.svgIcon"></mat-icon>
|
<mat-icon *ngIf="shortcut.svgIcon" class="icon" [svgIcon]="shortcut.svgIcon"></mat-icon>
|
||||||
<i *ngIf="shortcut.icon" class="icon {{shortcut.icon}}"></i>
|
<i *ngIf="shortcut.icon" class="icon {{ shortcut.icon }}"></i>
|
||||||
<span *ngIf="shortcut.label" class="shortcuts-avatar-label">{{shortcut.label}}</span>
|
<span *ngIf="shortcut.label" class="shortcuts-avatar-label">{{ shortcut.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="shortcut-col">
|
<div class="shortcut-col">
|
||||||
<span *ngIf="shortcut.i18nTitle">{{shortcut.i18nTitle | translate}}</span>
|
<span *ngIf="shortcut.i18nTitle">{{ shortcut.i18nTitle | translate }}</span>
|
||||||
<span *ngIf="shortcut.title">{{shortcut.title}}</span>
|
<span *ngIf="shortcut.title">{{ shortcut.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="fill-space"></span>
|
<span class="fill-space"></span>
|
||||||
|
|
||||||
<div class="shortcut-state-dot" *ngIf="shortcut && shortcut.state !== undefined"
|
<div
|
||||||
matTooltip="{{'PROJECT.STATE.'+shortcut.state | translate}}"
|
class="shortcut-state-dot"
|
||||||
[ngClass]="{'active': shortcut.state === ProjectState.PROJECT_STATE_ACTIVE, 'inactive': shortcut.state === ProjectState.PROJECT_STATE_INACTIVE }">
|
*ngIf="shortcut && shortcut.state !== undefined"
|
||||||
</div>
|
matTooltip="{{ 'PROJECT.STATE.' + shortcut.state | translate }}"
|
||||||
|
[ngClass]="{
|
||||||
|
active: shortcut.state === ProjectState.PROJECT_STATE_ACTIVE,
|
||||||
|
inactive: shortcut.state === ProjectState.PROJECT_STATE_INACTIVE
|
||||||
|
}"
|
||||||
|
></div>
|
||||||
</a>
|
</a>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div cdkDropList [cdkDropListData]="secondary" class="shortcut-list"
|
<div cdkDropList [cdkDropListData]="secondary" class="shortcut-list" (cdkDropListDropped)="drop($event, 'secondary')">
|
||||||
(cdkDropListDropped)="drop($event, 'secondary')">
|
<p *ngIf="editState" class="shortcut-desc cnsl-secondary-text">{{ 'HOME.SHORTCUTS.REORDER' | translate }}</p>
|
||||||
<p *ngIf="editState" class="shortcut-desc">{{'HOME.SHORTCUTS.REORDER' | translate}}</p>
|
|
||||||
<ng-container *ngFor="let shortcut of secondary">
|
<ng-container *ngFor="let shortcut of secondary">
|
||||||
<ng-template cnslHasRole [hasRole]="shortcut.withRole">
|
<ng-template cnslHasRole [hasRole]="shortcut.withRole">
|
||||||
<a [routerLink]="!editState ? shortcut.routerLink : null" class="shortcut-box"
|
<a
|
||||||
[ngClass]="{'edit-state': editState && !shortcut.disabled}" cdkDrag
|
[routerLink]="!editState ? shortcut.routerLink : null"
|
||||||
[cdkDragDisabled]="shortcut.disabled || !editState">
|
[queryParams]="shortcut.queryParams ? shortcut.queryParams : null"
|
||||||
<div class="shortcuts-avatar {{shortcut.color}}">
|
class="shortcut-box"
|
||||||
|
[ngClass]="{ 'edit-state': editState && !shortcut.disabled }"
|
||||||
|
cdkDrag
|
||||||
|
[cdkDragDisabled]="shortcut.disabled || !editState"
|
||||||
|
>
|
||||||
|
<div class="shortcuts-avatar {{ shortcut.color }}">
|
||||||
<mat-icon *ngIf="shortcut.svgIcon" class="icon" [svgIcon]="shortcut.svgIcon"></mat-icon>
|
<mat-icon *ngIf="shortcut.svgIcon" class="icon" [svgIcon]="shortcut.svgIcon"></mat-icon>
|
||||||
<i *ngIf="shortcut.icon" class="icon {{shortcut.icon}}"></i>
|
<i *ngIf="shortcut.icon" class="icon {{ shortcut.icon }}"></i>
|
||||||
<span *ngIf="shortcut.label" class="shortcuts-avatar-label">{{shortcut.label}}</span>
|
<span *ngIf="shortcut.label" class="shortcuts-avatar-label">{{ shortcut.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="shortcut-col">
|
<div class="shortcut-col">
|
||||||
<span *ngIf="shortcut.i18nTitle">{{shortcut.i18nTitle | translate}}</span>
|
<span *ngIf="shortcut.i18nTitle">{{ shortcut.i18nTitle | translate }}</span>
|
||||||
<span *ngIf="shortcut.title">{{shortcut.title}}</span>
|
<span *ngIf="shortcut.title">{{ shortcut.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="fill-space"></span>
|
<span class="fill-space"></span>
|
||||||
|
|
||||||
<div class="shortcut-state-dot" *ngIf="shortcut && shortcut.state !== undefined"
|
<div
|
||||||
matTooltip="{{'PROJECT.STATE.'+shortcut.state | translate}}"
|
class="shortcut-state-dot"
|
||||||
[ngClass]="{'active': shortcut.state === ProjectState.PROJECT_STATE_ACTIVE, 'inactive': shortcut.state === ProjectState.PROJECT_STATE_INACTIVE }">
|
*ngIf="shortcut && shortcut.state !== undefined"
|
||||||
</div>
|
matTooltip="{{ 'PROJECT.STATE.' + shortcut.state | translate }}"
|
||||||
|
[ngClass]="{
|
||||||
|
active: shortcut.state === ProjectState.PROJECT_STATE_ACTIVE,
|
||||||
|
inactive: shortcut.state === ProjectState.PROJECT_STATE_INACTIVE
|
||||||
|
}"
|
||||||
|
></div>
|
||||||
</a>
|
</a>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div cdkDropList [cdkDropListData]="third" class="shortcut-list" (cdkDropListDropped)="drop($event, 'third')">
|
<div cdkDropList [cdkDropListData]="third" class="shortcut-list" (cdkDropListDropped)="drop($event, 'third')">
|
||||||
<p *ngIf="editState" class="shortcut-desc">{{'HOME.SHORTCUTS.REORDER' | translate}}</p>
|
<p *ngIf="editState" class="shortcut-desc cnsl-secondary-text">{{ 'HOME.SHORTCUTS.REORDER' | translate }}</p>
|
||||||
<ng-container *ngFor="let shortcut of third">
|
<ng-container *ngFor="let shortcut of third">
|
||||||
<ng-template cnslHasRole [hasRole]="shortcut.withRole">
|
<ng-template cnslHasRole [hasRole]="shortcut.withRole">
|
||||||
<a [routerLink]="!editState ? shortcut.routerLink : null" class="shortcut-box"
|
<a
|
||||||
[ngClass]="{'edit-state': editState && !shortcut.disabled}" cdkDrag
|
[routerLink]="!editState ? shortcut.routerLink : null"
|
||||||
[cdkDragDisabled]="shortcut.disabled || !editState">
|
[queryParams]="shortcut.queryParams ? shortcut.queryParams : null"
|
||||||
<div class="shortcuts-avatar {{shortcut.color}}">
|
class="shortcut-box"
|
||||||
|
[ngClass]="{ 'edit-state': editState && !shortcut.disabled }"
|
||||||
|
cdkDrag
|
||||||
|
[cdkDragDisabled]="shortcut.disabled || !editState"
|
||||||
|
>
|
||||||
|
<div class="shortcuts-avatar {{ shortcut.color }}">
|
||||||
<mat-icon *ngIf="shortcut.svgIcon" class="icon" [svgIcon]="shortcut.svgIcon"></mat-icon>
|
<mat-icon *ngIf="shortcut.svgIcon" class="icon" [svgIcon]="shortcut.svgIcon"></mat-icon>
|
||||||
<i *ngIf="shortcut.icon" class="icon {{shortcut.icon}}"></i>
|
<i *ngIf="shortcut.icon" class="icon {{ shortcut.icon }}"></i>
|
||||||
<span *ngIf="shortcut.label" class="shortcuts-avatar-label">{{shortcut.label}}</span>
|
<span *ngIf="shortcut.label" class="shortcuts-avatar-label">{{ shortcut.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="shortcut-col">
|
<div class="shortcut-col">
|
||||||
<span *ngIf="shortcut.i18nTitle">{{shortcut.i18nTitle | translate}}</span>
|
<span *ngIf="shortcut.i18nTitle">{{ shortcut.i18nTitle | translate }}</span>
|
||||||
<span *ngIf="shortcut.title">{{shortcut.title}}</span>
|
<span *ngIf="shortcut.title">{{ shortcut.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span class="fill-space"></span>
|
<span class="fill-space"></span>
|
||||||
|
|
||||||
<div class="shortcut-state-dot" *ngIf="shortcut && shortcut.state !== undefined"
|
<div
|
||||||
matTooltip="{{'PROJECT.STATE.'+shortcut.state | translate}}"
|
class="shortcut-state-dot"
|
||||||
[ngClass]="{'active': shortcut.state === ProjectState.PROJECT_STATE_ACTIVE, 'inactive': shortcut.state === ProjectState.PROJECT_STATE_INACTIVE }">
|
*ngIf="shortcut && shortcut.state !== undefined"
|
||||||
</div>
|
matTooltip="{{ 'PROJECT.STATE.' + shortcut.state | translate }}"
|
||||||
|
[ngClass]="{
|
||||||
|
active: shortcut.state === ProjectState.PROJECT_STATE_ACTIVE,
|
||||||
|
inactive: shortcut.state === ProjectState.PROJECT_STATE_INACTIVE
|
||||||
|
}"
|
||||||
|
></div>
|
||||||
</a>
|
</a>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
@@ -102,92 +135,48 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="shortcut-container" *ngIf="editState">
|
<div class="shortcut-container" *ngIf="editState">
|
||||||
<h2>{{'HOME.SHORTCUTS.SETTINGS' | translate}}</h2>
|
<h2>{{ 'HOME.SHORTCUTS.SETTINGS' | translate }}</h2>
|
||||||
|
|
||||||
<div class="shortcut-list-row">
|
<div class="available-shortcut-wrapper">
|
||||||
|
<p *ngIf="editState" class="shortcut-desc cnsl-secondary-text">{{ 'HOME.SHORTCUTS.REORDER' | translate }}</p>
|
||||||
|
|
||||||
<div cdkDropList [cdkDropListData]="allRoutes" class="shortcut-list" (cdkDropListDropped)="drop($event, 'main')">
|
<div
|
||||||
<p *ngIf="editState" class="shortcut-desc">{{'HOME.SHORTCUTS.REORDER' | translate}}</p>
|
cdkDropList
|
||||||
<ng-container *ngFor="let shortcut of allRoutes">
|
[cdkDropListData]="allAvailableShortcuts"
|
||||||
|
class="available-shortcut-list"
|
||||||
|
(cdkDropListDropped)="drop($event, 'main')"
|
||||||
|
>
|
||||||
|
<ng-container *ngFor="let shortcut of allAvailableShortcuts">
|
||||||
<ng-template cnslHasRole [hasRole]="shortcut.withRole">
|
<ng-template cnslHasRole [hasRole]="shortcut.withRole">
|
||||||
<div class="shortcut-box"
|
<div
|
||||||
[ngClass]="{'edit-state': editState && !shortcut.disabled, 'disabled': editState && shortcut.disabled}"
|
class="shortcut-box"
|
||||||
cdkDrag [cdkDragDisabled]="shortcut.disabled">
|
[ngClass]="{ 'edit-state': editState && !shortcut.disabled, disabled: editState && shortcut.disabled }"
|
||||||
<div class="shortcuts-avatar {{shortcut.color}}">
|
cdkDrag
|
||||||
|
[cdkDragDisabled]="shortcut.disabled"
|
||||||
|
>
|
||||||
|
<div class="shortcuts-avatar {{ shortcut.color }}">
|
||||||
<mat-icon *ngIf="shortcut.svgIcon" class="icon" [svgIcon]="shortcut.svgIcon"></mat-icon>
|
<mat-icon *ngIf="shortcut.svgIcon" class="icon" [svgIcon]="shortcut.svgIcon"></mat-icon>
|
||||||
<i *ngIf="shortcut.icon" class="icon {{shortcut.icon}}"></i>
|
<i *ngIf="shortcut.icon" class="icon {{ shortcut.icon }}"></i>
|
||||||
<span *ngIf="shortcut.label" class="shortcuts-avatar-label">{{shortcut.label}}</span>
|
<span *ngIf="shortcut.label" class="shortcuts-avatar-label">{{ shortcut.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="shortcut-col">
|
<div class="shortcut-col">
|
||||||
<span *ngIf="shortcut.i18nTitle">{{shortcut.i18nTitle | translate}}</span>
|
<span *ngIf="shortcut.i18nTitle">{{ shortcut.i18nTitle | translate }}</span>
|
||||||
<span *ngIf="shortcut.title">{{shortcut.title}}</span>
|
<span *ngIf="shortcut.title">{{ shortcut.title }}</span>
|
||||||
<span class="shortcut-item-desc cnsl-secondary-text" *ngIf="shortcut.i18nDesc">{{shortcut.i18nDesc |
|
<span class="shortcut-item-desc cnsl-secondary-text" *ngIf="shortcut.i18nDesc">{{
|
||||||
translate}}</span>
|
shortcut.i18nDesc | translate
|
||||||
<span class="shortcut-item-desc cnsl-secondary-text" *ngIf="shortcut.desc">{{shortcut.desc}}</span>
|
}}</span>
|
||||||
|
<span class="shortcut-item-desc cnsl-secondary-text" *ngIf="shortcut.desc">{{ shortcut.desc }}</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="fill-space"></span>
|
<span class="fill-space"></span>
|
||||||
<div class="shortcut-state-dot" *ngIf="shortcut && shortcut.state !== undefined"
|
<div
|
||||||
matTooltip="{{'PROJECT.STATE.'+shortcut.state | translate}}"
|
class="shortcut-state-dot"
|
||||||
[ngClass]="{'active': shortcut.state === ProjectState.PROJECT_STATE_ACTIVE, 'inactive': shortcut.state === ProjectState.PROJECT_STATE_INACTIVE }">
|
*ngIf="shortcut && shortcut.state !== undefined"
|
||||||
</div>
|
matTooltip="{{ 'PROJECT.STATE.' + shortcut.state | translate }}"
|
||||||
</div>
|
[ngClass]="{
|
||||||
</ng-template>
|
active: shortcut.state === ProjectState.PROJECT_STATE_ACTIVE,
|
||||||
</ng-container>
|
inactive: shortcut.state === ProjectState.PROJECT_STATE_INACTIVE
|
||||||
</div>
|
}"
|
||||||
|
></div>
|
||||||
<div cdkDropList [cdkDropListData]="allPolicies" class="shortcut-list"
|
|
||||||
(cdkDropListDropped)="drop($event, 'secondary')">
|
|
||||||
<p *ngIf="editState" class="shortcut-desc">{{'HOME.SHORTCUTS.REORDER' | translate}}</p>
|
|
||||||
<ng-container *ngFor="let shortcut of allPolicies">
|
|
||||||
<ng-template cnslHasRole [hasRole]="shortcut.withRole">
|
|
||||||
<div class="shortcut-box" [ngClass]="{'edit-state': editState && !shortcut.disabled}" cdkDrag
|
|
||||||
[cdkDragDisabled]="shortcut.disabled">
|
|
||||||
<div class="shortcuts-avatar {{shortcut.color}}">
|
|
||||||
<mat-icon *ngIf="shortcut.svgIcon" class="icon" [svgIcon]="shortcut.svgIcon"></mat-icon>
|
|
||||||
<i *ngIf="shortcut.icon" class="icon {{shortcut.icon}}"></i>
|
|
||||||
<span *ngIf="shortcut.label" class="shortcuts-avatar-label">{{shortcut.label}}</span>
|
|
||||||
</div>
|
|
||||||
<div class="shortcut-col">
|
|
||||||
<span *ngIf="shortcut.i18nTitle">{{shortcut.i18nTitle | translate}}</span>
|
|
||||||
<span *ngIf="shortcut.title">{{shortcut.title}}</span>
|
|
||||||
<span class="shortcut-item-desc cnsl-secondary-text" *ngIf="shortcut.i18nDesc">{{shortcut.i18nDesc |
|
|
||||||
translate}}</span>
|
|
||||||
<span class="shortcut-item-desc cnsl-secondary-text" *ngIf="shortcut.desc">{{shortcut.desc}}</span>
|
|
||||||
</div>
|
|
||||||
<span class="fill-space"></span>
|
|
||||||
<div class="shortcut-state-dot" *ngIf="shortcut && shortcut.state !== undefined"
|
|
||||||
matTooltip="{{'PROJECT.STATE.'+shortcut.state | translate}}"
|
|
||||||
[ngClass]="{'active': shortcut.state === ProjectState.PROJECT_STATE_ACTIVE, 'inactive': shortcut.state === ProjectState.PROJECT_STATE_INACTIVE }">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ng-template>
|
|
||||||
</ng-container>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div cdkDropList [cdkDropListData]="allProjects" class="shortcut-list"
|
|
||||||
(cdkDropListDropped)="drop($event, 'third')">
|
|
||||||
<p *ngIf="editState" class="shortcut-desc">{{'HOME.SHORTCUTS.REORDER' | translate}}</p>
|
|
||||||
<ng-container *ngFor="let shortcut of allProjects">
|
|
||||||
<ng-template cnslHasRole [hasRole]="shortcut.withRole">
|
|
||||||
<div class="shortcut-box" [ngClass]="{'edit-state': editState && !shortcut.disabled}" cdkDrag
|
|
||||||
[cdkDragDisabled]="shortcut.disabled">
|
|
||||||
<div class="shortcuts-avatar {{shortcut.color}}">
|
|
||||||
<mat-icon *ngIf="shortcut.svgIcon" class="icon" [svgIcon]="shortcut.svgIcon"></mat-icon>
|
|
||||||
<i *ngIf="shortcut.icon" class="icon {{shortcut.icon}}"></i>
|
|
||||||
<span *ngIf="shortcut.label" class="shortcuts-avatar-label">{{shortcut.label}}</span>
|
|
||||||
</div>
|
|
||||||
<div class="shortcut-col">
|
|
||||||
<span *ngIf="shortcut.i18nTitle">{{shortcut.i18nTitle | translate}}</span>
|
|
||||||
<span *ngIf="shortcut.title">{{shortcut.title}}</span>
|
|
||||||
<span class="shortcut-item-desc cnsl-secondary-text" *ngIf="shortcut.i18nDesc">{{shortcut.i18nDesc |
|
|
||||||
translate}}</span>
|
|
||||||
<span class="shortcut-item-desc cnsl-secondary-text" *ngIf="shortcut.desc">{{shortcut.desc}}</span>
|
|
||||||
</div>
|
|
||||||
<span class="fill-space"></span>
|
|
||||||
<div class="shortcut-state-dot" *ngIf="shortcut && shortcut.state !== undefined"
|
|
||||||
matTooltip="{{'PROJECT.STATE.'+shortcut.state | translate}}"
|
|
||||||
[ngClass]="{'active': shortcut.state === ProjectState.PROJECT_STATE_ACTIVE, 'inactive': shortcut.state === ProjectState.PROJECT_STATE_INACTIVE }">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
@@ -207,4 +196,4 @@
|
|||||||
<span *ngIf="shortcut.title">{{shortcut.title}}</span>
|
<span *ngIf="shortcut.title">{{shortcut.title}}</span>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-template> -->
|
</ng-template> -->
|
||||||
|
@@ -62,7 +62,6 @@
|
|||||||
.shortcut-desc {
|
.shortcut-desc {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--grey);
|
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
@@ -89,7 +88,6 @@
|
|||||||
.shortcut-desc {
|
.shortcut-desc {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--grey);
|
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
@@ -209,6 +207,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.available-shortcut-wrapper {
|
||||||
|
border: 1px solid $border-color;
|
||||||
|
border-radius: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
.available-shortcut-list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-gap: 1rem;
|
||||||
|
|
||||||
|
@media only screen and (min-width: 800px) {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (min-width: 1200px) {
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shortcut-box {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.cdk-drag-preview {
|
.cdk-drag-preview {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
|
@@ -17,7 +17,8 @@ export interface ShortcutItem {
|
|||||||
i18nTitle?: string;
|
i18nTitle?: string;
|
||||||
i18nDesc?: string;
|
i18nDesc?: string;
|
||||||
routerLink: any;
|
routerLink: any;
|
||||||
withRole: string[];
|
queryParams?: any;
|
||||||
|
withRole?: string[];
|
||||||
icon?: string;
|
icon?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
svgIcon?: string;
|
svgIcon?: string;
|
||||||
@@ -138,8 +139,9 @@ export class ShortcutsComponent implements OnDestroy {
|
|||||||
type: ShortcutType.POLICY,
|
type: ShortcutType.POLICY,
|
||||||
i18nTitle: p.i18nTitle,
|
i18nTitle: p.i18nTitle,
|
||||||
i18nDesc: p.i18nDesc,
|
i18nDesc: p.i18nDesc,
|
||||||
routerLink: p.orgRouterLink,
|
routerLink: p.orgRouterLink ?? p.iamRouterLink,
|
||||||
withRole: p.orgWithRole,
|
queryParams: p.queryParams,
|
||||||
|
withRole: p.orgWithRole ?? p.iamWithRole,
|
||||||
icon: p.icon ?? '',
|
icon: p.icon ?? '',
|
||||||
svgIcon: p.svgIcon ?? '',
|
svgIcon: p.svgIcon ?? '',
|
||||||
color: p.color ?? '',
|
color: p.color ?? '',
|
||||||
@@ -176,10 +178,10 @@ export class ShortcutsComponent implements OnDestroy {
|
|||||||
} else {
|
} else {
|
||||||
switch (listName) {
|
switch (listName) {
|
||||||
case 'main':
|
case 'main':
|
||||||
this.main = [PROFILE_SHORTCUT, CREATE_ORG, CREATE_PROJECT, CREATE_USER];
|
this.main = [PROFILE_SHORTCUT /* CREATE_ORG, CREATE_PROJECT, CREATE_USER */];
|
||||||
break;
|
break;
|
||||||
case 'secondary':
|
case 'secondary':
|
||||||
this.secondary = [];
|
this.secondary = [CREATE_ORG, CREATE_PROJECT, CREATE_USER];
|
||||||
// [LOGIN_POLICY, PRIVATELABEL_POLICY].map((p) => {
|
// [LOGIN_POLICY, PRIVATELABEL_POLICY].map((p) => {
|
||||||
// const policy: string = {
|
// const policy: string = {
|
||||||
// i18nTitle: p.i18nTitle,
|
// i18nTitle: p.i18nTitle,
|
||||||
@@ -194,7 +196,7 @@ export class ShortcutsComponent implements OnDestroy {
|
|||||||
// });
|
// });
|
||||||
break;
|
break;
|
||||||
case 'third':
|
case 'third':
|
||||||
this.third = [];
|
this.third = this.ALL_SHORTCUTS.filter((item) => item.i18nTitle === 'SETTINGS.GROUPS.APPEARANCE');
|
||||||
// [LOGIN_TEXTS_POLICY, MESSAGE_TEXTS_POLICY].map((p) => {
|
// [LOGIN_TEXTS_POLICY, MESSAGE_TEXTS_POLICY].map((p) => {
|
||||||
// const policy: ShortcutItem = {
|
// const policy: ShortcutItem = {
|
||||||
// i18nTitle: p.i18nTitle,
|
// i18nTitle: p.i18nTitle,
|
||||||
@@ -276,4 +278,8 @@ export class ShortcutsComponent implements OnDestroy {
|
|||||||
public get allProjects(): ShortcutItem[] {
|
public get allProjects(): ShortcutItem[] {
|
||||||
return this.all.filter((s) => s.type === ShortcutType.PROJECT);
|
return this.all.filter((s) => s.type === ShortcutType.PROJECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get allAvailableShortcuts(): ShortcutItem[] {
|
||||||
|
return [...this.allRoutes, ...this.allPolicies, ...this.allProjects];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,30 +1,37 @@
|
|||||||
<span class="title" mat-dialog-title>{{'USER.PERSONALACCESSTOKEN.ADDED.TITLE' | translate}}</span>
|
<span class="title" mat-dialog-title>{{ 'USER.PERSONALACCESSTOKEN.ADDED.TITLE' | translate }}</span>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
<cnsl-info-section [type]="InfoSectionType.WARN"> {{'USER.PERSONALACCESSTOKEN.ADDED.DESCRIPTION' | translate}}
|
<cnsl-info-section [type]="InfoSectionType.WARN">
|
||||||
|
{{ 'USER.PERSONALACCESSTOKEN.ADDED.DESCRIPTION' | translate }}
|
||||||
</cnsl-info-section>
|
</cnsl-info-section>
|
||||||
|
|
||||||
<ng-container *ngIf="tokenResponse">
|
<ng-container *ngIf="tokenResponse">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<p class="left">{{'USER.PERSONALACCESSTOKEN.ID' | translate}}</p>
|
<p class="left cnsl-secondary-text">{{ 'USER.PERSONALACCESSTOKEN.ID' | translate }}</p>
|
||||||
<p class="right">{{tokenResponse.tokenId}}</p>
|
<p class="right">{{ tokenResponse.tokenId }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row" *ngIf="tokenResponse.token">
|
<div class="row" *ngIf="tokenResponse.token">
|
||||||
<p class="left">{{'USER.PERSONALACCESSTOKEN.TOKEN' | translate}}</p>
|
<p class="left cnsl-secondary-text">{{ 'USER.PERSONALACCESSTOKEN.TOKEN' | translate }}</p>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<button class="ctc" [disabled]="copied === tokenResponse.token"
|
<button
|
||||||
[matTooltip]="(copied !== tokenResponse.token ? 'ACTIONS.COPY' : 'ACTIONS.COPIED' ) | translate"
|
class="ctc"
|
||||||
cnslCopyToClipboard [valueToCopy]="tokenResponse.token" (copiedValue)="copied = $event" mat-icon-button>
|
[disabled]="copied === tokenResponse.token"
|
||||||
|
[matTooltip]="(copied !== tokenResponse.token ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||||
|
cnslCopyToClipboard
|
||||||
|
[valueToCopy]="tokenResponse.token"
|
||||||
|
(copiedValue)="copied = $event"
|
||||||
|
mat-icon-button
|
||||||
|
>
|
||||||
<i *ngIf="copied !== tokenResponse.token" class="las la-clipboard"></i>
|
<i *ngIf="copied !== tokenResponse.token" class="las la-clipboard"></i>
|
||||||
<i *ngIf="copied === tokenResponse.token" class="las la-clipboard-check"></i>
|
<i *ngIf="copied === tokenResponse.token" class="las la-clipboard-check"></i>
|
||||||
</button>
|
</button>
|
||||||
<span>{{tokenResponse.token}}</span>
|
<span>{{ tokenResponse.token }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
<div mat-dialog-actions class="action">
|
<div mat-dialog-actions class="action">
|
||||||
<button color="primary" mat-raised-button class="ok-button" (click)="closeDialog()">
|
<button color="primary" mat-raised-button class="ok-button" (click)="closeDialog()">
|
||||||
{{'ACTIONS.CLOSE' | translate}}
|
{{ 'ACTIONS.CLOSE' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -28,7 +28,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
color: var(--grey);
|
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
|
@@ -69,7 +69,7 @@
|
|||||||
padding: 0.75rem 0;
|
padding: 0.75rem 0;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: map-get($foreground, base);
|
color: map-get($foreground, text);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: map-get($foreground, base);
|
color: map-get($foreground, text);
|
||||||
|
|
||||||
&:not(:last-child) {
|
&:not(:last-child) {
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<span class="title" mat-dialog-title>{{'ORG.DOMAINS.ADD.TITLE' | translate}}</span>
|
<span class="title" mat-dialog-title>{{ 'ORG.DOMAINS.ADD.TITLE' | translate }}</span>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
<p class="desc"> {{'ORG.DOMAINS.ADD.DESCRIPTION' | translate}}</p>
|
<p class="desc cnsl-secondary-text">{{ 'ORG.DOMAINS.ADD.DESCRIPTION' | translate }}</p>
|
||||||
|
|
||||||
<cnsl-form-field label="Domain" required="true" class="form-field" appearance="outline">
|
<cnsl-form-field label="Domain" required="true" class="form-field" appearance="outline">
|
||||||
<cnsl-label>Domain</cnsl-label>
|
<cnsl-label>Domain</cnsl-label>
|
||||||
@@ -9,11 +9,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div mat-dialog-actions class="action">
|
<div mat-dialog-actions class="action">
|
||||||
<button mat-stroked-button (click)="closeDialog()">
|
<button mat-stroked-button (click)="closeDialog()">
|
||||||
{{'ACTIONS.CANCEL' | translate}}
|
{{ 'ACTIONS.CANCEL' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button color="primary" mat-raised-button class="ok-button" [disabled]="!newdomain"
|
<button color="primary" mat-raised-button class="ok-button" [disabled]="!newdomain" (click)="closeDialogWithSuccess()">
|
||||||
(click)="closeDialogWithSuccess()">
|
{{ 'ACTIONS.ADD' | translate }}
|
||||||
{{'ACTIONS.ADD' | translate}}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.desc {
|
.desc {
|
||||||
color: var(--grey);
|
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,18 +1,34 @@
|
|||||||
<div class="max-width-container">
|
<div class="max-width-container">
|
||||||
<div class="enlarged-container">
|
<div class="enlarged-container">
|
||||||
<h1>{{ 'GRANTS.TITLE' | translate }}</h1>
|
<h1>{{ 'GRANTS.TITLE' | translate }}</h1>
|
||||||
<p class="desc cnsl-secondary-text">{{'GRANTS.DESC' | translate }}</p>
|
<p class="grants-desc cnsl-secondary-text">{{ 'GRANTS.DESC' | translate }}</p>
|
||||||
<cnsl-user-grants *ngIf="grantContext === UserGrantContext.NONE"
|
<cnsl-user-grants
|
||||||
[displayedColumns]="['select', 'user', 'org', 'projectId','type', 'creationDate','changeDate', 'roleNamesList', 'actions']"
|
*ngIf="grantContext === UserGrantContext.NONE"
|
||||||
[disableWrite]="((['user.grant.write$'] | hasRole) | async) === false"
|
[displayedColumns]="[
|
||||||
[disableDelete]="((['user.grant.delete$'] | hasRole) | async) === false"
|
'select',
|
||||||
[refreshOnPreviousRoutes]="['/grant-create']">
|
'user',
|
||||||
|
'org',
|
||||||
|
'projectId',
|
||||||
|
'type',
|
||||||
|
'creationDate',
|
||||||
|
'changeDate',
|
||||||
|
'roleNamesList',
|
||||||
|
'actions'
|
||||||
|
]"
|
||||||
|
[disableWrite]="(['user.grant.write$'] | hasRole | async) === false"
|
||||||
|
[disableDelete]="(['user.grant.delete$'] | hasRole | async) === false"
|
||||||
|
[refreshOnPreviousRoutes]="['/grant-create']"
|
||||||
|
>
|
||||||
</cnsl-user-grants>
|
</cnsl-user-grants>
|
||||||
|
|
||||||
<cnsl-user-grants *ngIf="grantContext === UserGrantContext.OWNED_PROJECT" [context]="UserGrantContext.OWNED_PROJECT"
|
<cnsl-user-grants
|
||||||
[projectId]="projectId" [refreshOnPreviousRoutes]="['/grant-create/project/'+projectId]"
|
*ngIf="grantContext === UserGrantContext.OWNED_PROJECT"
|
||||||
[disableWrite]="((['user.grant.write$', 'user.grant.write:'+projectId] | hasRole) | async) === false"
|
[context]="UserGrantContext.OWNED_PROJECT"
|
||||||
[disableDelete]="((['user.grant.delete$','user.grant.delete:'+projectId] | hasRole) | async) === false">
|
[projectId]="projectId"
|
||||||
|
[refreshOnPreviousRoutes]="['/grant-create/project/' + projectId]"
|
||||||
|
[disableWrite]="(['user.grant.write$', 'user.grant.write:' + projectId] | hasRole | async) === false"
|
||||||
|
[disableDelete]="(['user.grant.delete$', 'user.grant.delete:' + projectId] | hasRole | async) === false"
|
||||||
|
>
|
||||||
</cnsl-user-grants>
|
</cnsl-user-grants>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,7 +2,7 @@ h1 {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.desc {
|
.grants-desc {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 1rem;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<cnsl-top-view
|
<cnsl-top-view
|
||||||
title="{{ app?.name }}"
|
title="{{ app?.name }}"
|
||||||
[hasActions]="isZitadel === false && (['project.app.write:' + projectId, 'project.app.write'] | hasRole | async)"
|
[hasActions]="isZitadel === false && (['project.app.write:' + projectId, 'project.app.write'] | hasRole | async)"
|
||||||
docLink="https://docs.zitadel.ch/docs/guides/basics/projects"
|
docLink="https://docs.zitadel.com/docs/guides/basics/projects"
|
||||||
[sub]="app?.oidcConfig ? ('APP.OIDC.APPTYPE.' + app?.oidcConfig?.appType | translate) : 'API'"
|
[sub]="app?.oidcConfig ? ('APP.OIDC.APPTYPE.' + app?.oidcConfig?.appType | translate) : 'API'"
|
||||||
[isActive]="app?.state === AppState.APP_STATE_ACTIVE"
|
[isActive]="app?.state === AppState.APP_STATE_ACTIVE"
|
||||||
[isInactive]="app?.state === AppState.APP_STATE_INACTIVE"
|
[isInactive]="app?.state === AppState.APP_STATE_INACTIVE"
|
||||||
|
@@ -30,6 +30,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.redirect-section {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.app-desc {
|
.app-desc {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -131,6 +136,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border: 1px solid if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
border: 1px solid if($is-dark-theme, rgba(#8795a1, 0.2), rgba(#8795a1, 0.2));
|
||||||
|
color: white;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
@@ -14,18 +14,11 @@
|
|||||||
</cnsl-auth-method-radio>
|
</cnsl-auth-method-radio>
|
||||||
</div>
|
</div>
|
||||||
<div mat-dialog-actions class="action">
|
<div mat-dialog-actions class="action">
|
||||||
<button color="primary" mat-stroked-button class="ok-button" (click)="closeDialog()">
|
<button color="primary" mat-stroked-button (click)="closeDialog()">
|
||||||
{{ 'ACTIONS.CLOSE' | translate }}
|
{{ 'ACTIONS.CLOSE' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button [disabled]="!authmethod" cdkFocusInitial color="primary" mat-raised-button (click)="closeDialogWithMethod()">
|
||||||
[disabled]="!authmethod"
|
|
||||||
cdkFocusInitial
|
|
||||||
color="primary"
|
|
||||||
mat-raised-button
|
|
||||||
class="ok-button"
|
|
||||||
(click)="closeDialogWithMethod()"
|
|
||||||
>
|
|
||||||
{{ 'ACTIONS.SELECT' | translate }}
|
{{ 'ACTIONS.SELECT' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -13,11 +13,7 @@ h1 {
|
|||||||
|
|
||||||
.action {
|
.action {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: space-between;
|
||||||
|
|
||||||
.ok-button {
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
@@ -1,27 +1,40 @@
|
|||||||
<form class="form" (ngSubmit)="add(redInput)" [attr.data-e2e]="'redirect-uris'">
|
<form class="redirect-uris-form" (ngSubmit)="add(redInput)" [attr.data-e2e]="'redirect-uris'">
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ title }}</cnsl-label>
|
<cnsl-label>{{ title }}</cnsl-label>
|
||||||
|
|
||||||
<input #redInput cnslInput placeholder="ex. https://" [formControl]="redirectControl">
|
<input #redInput cnslInput placeholder="ex. https://" [formControl]="redirectControl" />
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<button matTooltip="{{'ACTIONS.ADD' | translate}}" type="submit" mat-icon-button
|
<button
|
||||||
[disabled]="redirectControl.invalid || !canWrite">
|
matTooltip="{{ 'ACTIONS.ADD' | translate }}"
|
||||||
<mat-icon>add</mat-icon>
|
type="submit"
|
||||||
</button>
|
mat-icon-button
|
||||||
|
[disabled]="redirectControl.invalid || !canWrite"
|
||||||
|
>
|
||||||
|
<mat-icon>add</mat-icon>
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="uri-list">
|
<div class="redirect-uris-list">
|
||||||
<div *ngFor="let uri of urisList" class="uri-line">
|
<div *ngFor="let uri of urisList" class="uri-line" [ngClass]="{ alert: !devMode && !(uri | redirect: isNative) }">
|
||||||
<span class="uri"
|
<span
|
||||||
[ngClass]="{'green': !devMode && uri?.startsWith('https://'), 'red': !devMode && !uri?.startsWith('https://')}">{{uri}}</span>
|
class="uri"
|
||||||
<span class="fill-space"></span>
|
[ngClass]="{ green: !devMode && uri?.startsWith('https://'), red: !devMode && !uri?.startsWith('https://') }"
|
||||||
<i *ngIf="!devMode && !(uri | redirect : isNative)" class="las la-exclamation red" [matTooltip]="isNative ? ('APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate) : ('APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate)"></i>
|
>{{ uri }}</span
|
||||||
|
>
|
||||||
|
<span class="fill-space"></span>
|
||||||
|
<i
|
||||||
|
class="alerticon las la-exclamation red"
|
||||||
|
[matTooltip]="
|
||||||
|
isNative ? ('APP.OIDC.REDIRECTDESCRIPTIONNATIVE' | translate) : ('APP.OIDC.REDIRECTDESCRIPTIONWEB' | translate)
|
||||||
|
"
|
||||||
|
></i>
|
||||||
|
|
||||||
<button matTooltip="{{'ACTIONS.DELETE' | translate}}" mat-icon-button (click)="remove(uri)" class="icon-button">
|
<button matTooltip="{{ 'ACTIONS.DELETE' | translate }}" mat-icon-button (click)="remove(uri)" class="icon-button">
|
||||||
<mat-icon class="icon">cancel</mat-icon>
|
<mat-icon class="icon">cancel</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p *ngIf="redirectControl.value && redirectControl.invalid" class="error">
|
<p *ngIf="redirectControl.value && redirectControl.invalid" class="redirect-uris-error">
|
||||||
{{'APP.OIDC.REDIRECTNOTVALID' | translate}}</p>
|
{{ 'APP.OIDC.REDIRECTNOTVALID' | translate }}
|
||||||
|
</p>
|
||||||
|
@@ -1,4 +1,80 @@
|
|||||||
.form {
|
@use '@angular/material' as mat;
|
||||||
|
|
||||||
|
@mixin redirect-uris-theme($theme) {
|
||||||
|
$foreground: map-get($theme, foreground);
|
||||||
|
$background: map-get($theme, background);
|
||||||
|
$is-dark-theme: map-get($theme, is-dark);
|
||||||
|
$warn: map-get($theme, warn);
|
||||||
|
$warn-color: map-get($warn, 500);
|
||||||
|
$button-text-color: map-get($foreground, text);
|
||||||
|
$button-disabled-text-color: map-get($foreground, disabled-button);
|
||||||
|
$divider-color: map-get($foreground, dividers);
|
||||||
|
$secondary-text: map-get($foreground, secondary-text);
|
||||||
|
|
||||||
|
.redirect-uris-list {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.uri-line {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
padding: 0 0 0 0.75rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: map-get($background, infosection);
|
||||||
|
|
||||||
|
.uri {
|
||||||
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fill-space {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i.green {
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 35px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-button {
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:hover) {
|
||||||
|
color: $secondary-text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.alerticon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.alert {
|
||||||
|
background-color: map-get($background, alertinfosection);
|
||||||
|
color: map-get($foreground, alertinfosection);
|
||||||
|
|
||||||
|
.alerticon {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.redirect-uris-error {
|
||||||
|
font-size: 13px;
|
||||||
|
color: $warn-color;
|
||||||
|
margin: 0 0.5rem 1.5rem 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.redirect-uris-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
min-width: 320px;
|
min-width: 320px;
|
||||||
@@ -12,52 +88,3 @@
|
|||||||
margin-right: -0.5rem;
|
margin-right: -0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.uri-list {
|
|
||||||
margin: 0 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.uri-line {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.uri {
|
|
||||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
|
||||||
font-size: 14px;
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fill-space {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
i.green {
|
|
||||||
font-size: 1rem;
|
|
||||||
line-height: 35px;
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
i.red {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-button {
|
|
||||||
height: 30px;
|
|
||||||
line-height: 30px;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
font-size: 1rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:hover) {
|
|
||||||
color: var(--grey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.error {
|
|
||||||
font-size: 13px;
|
|
||||||
color: var(--warn);
|
|
||||||
margin: 0 0.5rem 1.5rem 0.5rem;
|
|
||||||
}
|
|
||||||
|
@@ -11,7 +11,7 @@ import { ManagementService } from 'src/app/services/mgmt.service';
|
|||||||
})
|
})
|
||||||
export class ApplicationGridComponent implements OnInit {
|
export class ApplicationGridComponent implements OnInit {
|
||||||
@Input() public projectId: string = '';
|
@Input() public projectId: string = '';
|
||||||
@Input() public disabled: boolean = false;
|
@Input() public disabled: boolean = true;
|
||||||
@Output() public changeView: EventEmitter<void> = new EventEmitter();
|
@Output() public changeView: EventEmitter<void> = new EventEmitter();
|
||||||
public appsSubject: BehaviorSubject<App.AsObject[]> = new BehaviorSubject<App.AsObject[]>([]);
|
public appsSubject: BehaviorSubject<App.AsObject[]> = new BehaviorSubject<App.AsObject[]>([]);
|
||||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
|
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
[isInactive]="project?.state === ProjectState.PROJECT_STATE_INACTIVE"
|
[isInactive]="project?.state === ProjectState.PROJECT_STATE_INACTIVE"
|
||||||
[hasContributors]="true"
|
[hasContributors]="true"
|
||||||
stateTooltip="{{ 'PROJECT.STATE.' + project?.state | translate }}"
|
stateTooltip="{{ 'PROJECT.STATE.' + project?.state | translate }}"
|
||||||
[hasActions]="true"
|
[hasActions]="['project.app.write:' + project?.id, 'project.app.write$'] | hasRole | async"
|
||||||
>
|
>
|
||||||
<ng-template topActions cnslHasRole [hasRole]="['project.write:' + projectId, 'project.write']">
|
<ng-template topActions cnslHasRole [hasRole]="['project.write:' + projectId, 'project.write']">
|
||||||
<button mat-menu-item (click)="openNameDialog()" aria-label="Edit project name" *ngIf="isZitadel === false">
|
<button mat-menu-item (click)="openNameDialog()" aria-label="Edit project name" *ngIf="isZitadel === false">
|
||||||
@@ -68,8 +68,13 @@
|
|||||||
<cnsl-meta-layout>
|
<cnsl-meta-layout>
|
||||||
<cnsl-sidenav [(ngModel)]="currentSetting" [settingsList]="settingsList" [queryParam]="'id'">
|
<cnsl-sidenav [(ngModel)]="currentSetting" [settingsList]="settingsList" [queryParam]="'id'">
|
||||||
<ng-container *ngIf="currentSetting === 'general' && project">
|
<ng-container *ngIf="currentSetting === 'general' && project">
|
||||||
<ng-template cnslHasRole [hasRole]="['project.app.read:' + project.id, 'project.app.read']">
|
<ng-template cnslHasRole [hasRole]="['project.app.read:' + project.id, 'project.app.read$']">
|
||||||
<cnsl-application-grid *ngIf="grid" [disabled]="isZitadel" (changeView)="grid = false" [projectId]="projectId">
|
<cnsl-application-grid
|
||||||
|
*ngIf="grid"
|
||||||
|
[disabled]="isZitadel || (['project.app.write:' + project.id, 'project.app.write$'] | hasRole | async) === false"
|
||||||
|
(changeView)="grid = false"
|
||||||
|
[projectId]="projectId"
|
||||||
|
>
|
||||||
</cnsl-application-grid>
|
</cnsl-application-grid>
|
||||||
<cnsl-card *ngIf="!grid" title="{{ 'PROJECT.APP.TITLE' | translate }}">
|
<cnsl-card *ngIf="!grid" title="{{ 'PROJECT.APP.TITLE' | translate }}">
|
||||||
<div class="card-actions" card-actions>
|
<div class="card-actions" card-actions>
|
||||||
@@ -77,7 +82,12 @@
|
|||||||
<i matTooltip="show grid view" class="las la-th-large"></i>
|
<i matTooltip="show grid view" class="las la-th-large"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<cnsl-applications [disabled]="isZitadel" [projectId]="projectId"></cnsl-applications>
|
<cnsl-applications
|
||||||
|
[disabled]="
|
||||||
|
isZitadel || (['project.app.write:' + project.id, 'project.app.write$'] | hasRole | async) === false
|
||||||
|
"
|
||||||
|
[projectId]="projectId"
|
||||||
|
></cnsl-applications>
|
||||||
</cnsl-card>
|
</cnsl-card>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
@@ -111,7 +121,9 @@
|
|||||||
>
|
>
|
||||||
{{ 'PROJECT.ROLE.ASSERTION' | translate }}</mat-checkbox
|
{{ 'PROJECT.ROLE.ASSERTION' | translate }}</mat-checkbox
|
||||||
>
|
>
|
||||||
<p class="desc cnsl-secondary-text">{{ 'PROJECT.ROLE.ASSERTION_DESCRIPTION' | translate }}</p>
|
<cnsl-info-section class="desc cnsl-secondary-text">{{
|
||||||
|
'PROJECT.ROLE.ASSERTION_DESCRIPTION' | translate
|
||||||
|
}}</cnsl-info-section>
|
||||||
<mat-checkbox
|
<mat-checkbox
|
||||||
[(ngModel)]="project.projectRoleCheck"
|
[(ngModel)]="project.projectRoleCheck"
|
||||||
[disabled]="(['project.write$', 'project.write:' + project.id] | hasRole | async) === false"
|
[disabled]="(['project.write$', 'project.write:' + project.id] | hasRole | async) === false"
|
||||||
@@ -119,7 +131,9 @@
|
|||||||
>
|
>
|
||||||
{{ 'PROJECT.ROLE.CHECK' | translate }}</mat-checkbox
|
{{ 'PROJECT.ROLE.CHECK' | translate }}</mat-checkbox
|
||||||
>
|
>
|
||||||
<p class="desc cnsl-secondary-text">{{ 'PROJECT.ROLE.CHECK_DESCRIPTION' | translate }}</p>
|
<cnsl-info-section class="desc cnsl-secondary-text">{{
|
||||||
|
'PROJECT.ROLE.CHECK_DESCRIPTION' | translate
|
||||||
|
}}</cnsl-info-section>
|
||||||
<mat-checkbox
|
<mat-checkbox
|
||||||
[(ngModel)]="project.hasProjectCheck"
|
[(ngModel)]="project.hasProjectCheck"
|
||||||
[disabled]="(['project.write$', 'project.write:' + project.id] | hasRole | async) === false"
|
[disabled]="(['project.write$', 'project.write:' + project.id] | hasRole | async) === false"
|
||||||
@@ -127,10 +141,19 @@
|
|||||||
>
|
>
|
||||||
{{ 'PROJECT.HAS_PROJECT' | translate }}</mat-checkbox
|
{{ 'PROJECT.HAS_PROJECT' | translate }}</mat-checkbox
|
||||||
>
|
>
|
||||||
<p class="desc cnsl-secondary-text">{{ 'PROJECT.HAS_PROJECT_DESCRIPTION' | translate }}</p>
|
<cnsl-info-section class="desc cnsl-secondary-text">{{
|
||||||
|
'PROJECT.HAS_PROJECT_DESCRIPTION' | translate
|
||||||
|
}}</cnsl-info-section>
|
||||||
|
|
||||||
<div class="project-detail-btn-container">
|
<div class="project-detail-btn-container">
|
||||||
<button mat-raised-button color="primary" (click)="saveProject()">{{ 'ACTIONS.SAVE' | translate }}</button>
|
<button
|
||||||
|
mat-raised-button
|
||||||
|
[disabled]="(['project.app.write:' + project.id, 'project.app.write$'] | hasRole | async) === false"
|
||||||
|
color="primary"
|
||||||
|
(click)="saveProject()"
|
||||||
|
>
|
||||||
|
{{ 'ACTIONS.SAVE' | translate }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</cnsl-card>
|
</cnsl-card>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@@ -55,5 +55,5 @@
|
|||||||
|
|
||||||
.desc {
|
.desc {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,7 @@ import { CardModule } from 'src/app/modules/card/card.module';
|
|||||||
import { ChangesModule } from 'src/app/modules/changes/changes.module';
|
import { ChangesModule } from 'src/app/modules/changes/changes.module';
|
||||||
import { ContributorsModule } from 'src/app/modules/contributors/contributors.module';
|
import { ContributorsModule } from 'src/app/modules/contributors/contributors.module';
|
||||||
import { InfoRowModule } from 'src/app/modules/info-row/info-row.module';
|
import { InfoRowModule } from 'src/app/modules/info-row/info-row.module';
|
||||||
|
import { InfoSectionModule } from 'src/app/modules/info-section/info-section.module';
|
||||||
import { InputModule } from 'src/app/modules/input/input.module';
|
import { InputModule } from 'src/app/modules/input/input.module';
|
||||||
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
|
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
|
||||||
import { PaginatorModule } from 'src/app/modules/paginator/paginator.module';
|
import { PaginatorModule } from 'src/app/modules/paginator/paginator.module';
|
||||||
@@ -71,6 +72,7 @@ import { OwnedProjectDetailComponent } from './owned-project-detail.component';
|
|||||||
TopViewModule,
|
TopViewModule,
|
||||||
MatCheckboxModule,
|
MatCheckboxModule,
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
|
InfoSectionModule,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
MatProgressSpinnerModule,
|
MatProgressSpinnerModule,
|
||||||
ChangesModule,
|
ChangesModule,
|
||||||
|
@@ -1,65 +1,104 @@
|
|||||||
<cnsl-detail-layout [hasBackButton]="true" title="{{ 'PROJECT.GRANT.DETAIL.TITLE' | translate }}">
|
<cnsl-detail-layout [hasBackButton]="true" title="{{ 'PROJECT.GRANT.DETAIL.TITLE' | translate }}">
|
||||||
<p class="subinfo" sub>
|
<p class="subinfo" sub>
|
||||||
<span class="cnsl-secondary-text">{{ 'PROJECT.GRANT.DETAIL.DESC' | translate }}</span>
|
<span class="cnsl-secondary-text">{{ 'PROJECT.GRANT.DETAIL.DESC' | translate }}</span>
|
||||||
<a mat-icon-button href="https://docs.zitadel.com/docs/concepts/structure/projects#granted-organizations"
|
<a
|
||||||
target="_blank">
|
mat-icon-button
|
||||||
|
href="https://docs.zitadel.com/docs/concepts/structure/projects#granted-organizations"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
<i class="las la-info-circle"></i>
|
<i class="las la-info-circle"></i>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div actions>
|
<div actions>
|
||||||
<button class="actions-trigger-desk" mat-raised-button color="primary" [matMenuTriggerFor]="actions">
|
<button class="actions-trigger-desk" mat-raised-button color="primary" [matMenuTriggerFor]="actions">
|
||||||
<span>{{'ACTIONS.ACTIONS' | translate}}</span>
|
<span>{{ 'ACTIONS.ACTIONS' | translate }}</span>
|
||||||
<mat-icon class="icon">keyboard_arrow_down</mat-icon>
|
<mat-icon class="icon">keyboard_arrow_down</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button class="actions-trigger-mob" matTooltip="{{'ACTIONS.ACTIONS' | translate}}" mat-icon-button
|
<button
|
||||||
[matMenuTriggerFor]="actions">
|
class="actions-trigger-mob"
|
||||||
|
matTooltip="{{ 'ACTIONS.ACTIONS' | translate }}"
|
||||||
|
mat-icon-button
|
||||||
|
[matMenuTriggerFor]="actions"
|
||||||
|
>
|
||||||
<i class="las la-ellipsis-v"></i>
|
<i class="las la-ellipsis-v"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-menu #actions="matMenu" xPosition="before">
|
<mat-menu #actions="matMenu" xPosition="before">
|
||||||
<button mat-menu-item *ngIf="grant?.state === ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE"
|
<button
|
||||||
(click)="changeState(ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE)">{{'USER.PAGES.DEACTIVATE' |
|
mat-menu-item
|
||||||
translate}}</button>
|
*ngIf="grant?.state === ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE"
|
||||||
<button mat-menu-item *ngIf="grant?.state === ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE"
|
(click)="changeState(ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE)"
|
||||||
(click)="changeState(ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE)">{{'USER.PAGES.REACTIVATE' |
|
>
|
||||||
translate}}</button>
|
{{ 'USER.PAGES.DEACTIVATE' | translate }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
*ngIf="grant?.state === ProjectGrantState.PROJECT_GRANT_STATE_INACTIVE"
|
||||||
|
(click)="changeState(ProjectGrantState.PROJECT_GRANT_STATE_ACTIVE)"
|
||||||
|
>
|
||||||
|
{{ 'USER.PAGES.REACTIVATE' | translate }}
|
||||||
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
||||||
<div class="master-row">
|
<div class="master-row">
|
||||||
<div>
|
<div></div>
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<cnsl-project-grant-illustration *ngIf="grant" [grantedProject]="grant" [projectRoleOptions]="projectRoleOptions"
|
<cnsl-project-grant-illustration
|
||||||
(roleRemoved)="removeRole($event)" (editRoleClicked)="editRoles()">
|
*ngIf="grant && projectRoleOptions"
|
||||||
|
[grantedProject]="grant"
|
||||||
|
[projectRoleOptions]="projectRoleOptions"
|
||||||
|
(roleRemoved)="removeRole($event)"
|
||||||
|
(editRoleClicked)="editRoles()"
|
||||||
|
>
|
||||||
</cnsl-project-grant-illustration>
|
</cnsl-project-grant-illustration>
|
||||||
|
|
||||||
<h2 class="project-grant-h2">{{ 'PROJECT.GRANT.DETAIL.MEMBERTITLE' | translate }}</h2>
|
<h2 class="project-grant-h2">{{ 'PROJECT.GRANT.DETAIL.MEMBERTITLE' | translate }}</h2>
|
||||||
<p class="desc max-width-description">{{ 'PROJECT.GRANT.DETAIL.MEMBERDESC' | translate }}</p>
|
<p class="desc cnsl-secondary-text max-width-description">{{ 'PROJECT.GRANT.DETAIL.MEMBERDESC' | translate }}</p>
|
||||||
|
|
||||||
<cnsl-members-table *ngIf="grant" [dataSource]="dataSource"
|
<cnsl-members-table
|
||||||
[canWrite]="['project.grant.member.write','project.grant.member.write:' + grant.grantId] | hasRole | async"
|
*ngIf="grant"
|
||||||
[canDelete]="['project.grant.member.delete','project.grant.member.delete:' + grant.grantId] | hasRole | async"
|
[dataSource]="dataSource"
|
||||||
[memberRoleOptions]="memberRoleOptions" (updateRoles)="updateMemberRoles($event.member, $event.change)"
|
[canWrite]="['project.grant.member.write', 'project.grant.member.write:' + grant.grantId] | hasRole | async"
|
||||||
(deleteMember)="removeProjectMember($event)" [factoryLoadFunc]="changePageFactory"
|
[canDelete]="['project.grant.member.delete', 'project.grant.member.delete:' + grant.grantId] | hasRole | async"
|
||||||
(changedSelection)="selection = $event" [refreshTrigger]="changePage">
|
[memberRoleOptions]="memberRoleOptions"
|
||||||
<button class="cnsl-action-button" selectactions (click)="removeProjectMemberSelection()"
|
(updateRoles)="updateMemberRoles($event.member, $event.change)"
|
||||||
[disabled]="(['project.grant.member.delete','project.grant.member.delete:' + grant.grantId] | hasRole | async) === false"
|
(deleteMember)="removeProjectMember($event)"
|
||||||
matTooltip="{{'ORG_DETAIL.TABLE.DELETE' | translate}}" color="warn" mat-raised-button>
|
[factoryLoadFunc]="changePageFactory"
|
||||||
|
(changedSelection)="selection = $event"
|
||||||
|
[refreshTrigger]="changePage"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="cnsl-action-button"
|
||||||
|
selectactions
|
||||||
|
(click)="removeProjectMemberSelection()"
|
||||||
|
[disabled]="
|
||||||
|
(['project.grant.member.delete', 'project.grant.member.delete:' + grant.grantId] | hasRole | async) === false
|
||||||
|
"
|
||||||
|
matTooltip="{{ 'ORG_DETAIL.TABLE.DELETE' | translate }}"
|
||||||
|
color="warn"
|
||||||
|
mat-raised-button
|
||||||
|
>
|
||||||
<i class="las la-trash"></i>
|
<i class="las la-trash"></i>
|
||||||
<span>{{'ACTIONS.SELECTIONDELETE' | translate}}</span>
|
<span>{{ 'ACTIONS.SELECTIONDELETE' | translate }}</span>
|
||||||
<cnsl-action-keys [type]="ActionKeysType.DELETE" (actionTriggered)="removeProjectMemberSelection()">
|
<cnsl-action-keys [type]="ActionKeysType.DELETE" (actionTriggered)="removeProjectMemberSelection()">
|
||||||
</cnsl-action-keys>
|
</cnsl-action-keys>
|
||||||
</button>
|
</button>
|
||||||
<button class="cnsl-action-button" writeactions color="primary"
|
<button
|
||||||
[disabled]="(['project.grant.member.write','project.grant.member.write:' + grant.grantId] | hasRole | async) === false"
|
class="cnsl-action-button"
|
||||||
(click)="openAddMember()" color="primary" mat-raised-button>
|
writeactions
|
||||||
|
color="primary"
|
||||||
|
[disabled]="
|
||||||
|
(['project.grant.member.write', 'project.grant.member.write:' + grant.grantId] | hasRole | async) === false
|
||||||
|
"
|
||||||
|
(click)="openAddMember()"
|
||||||
|
color="primary"
|
||||||
|
mat-raised-button
|
||||||
|
>
|
||||||
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
|
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
|
||||||
<cnsl-action-keys (actionTriggered)="openAddMember()">
|
<cnsl-action-keys (actionTriggered)="openAddMember()"> </cnsl-action-keys>
|
||||||
</cnsl-action-keys>
|
|
||||||
</button>
|
</button>
|
||||||
</cnsl-members-table>
|
</cnsl-members-table>
|
||||||
</cnsl-detail-layout>
|
</cnsl-detail-layout>
|
||||||
|
@@ -3,17 +3,15 @@ import { MatDialog } from '@angular/material/dialog';
|
|||||||
import { PageEvent } from '@angular/material/paginator';
|
import { PageEvent } from '@angular/material/paginator';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { ActionKeysType } from 'src/app/modules/action-keys/action-keys.component';
|
import { ActionKeysType } from 'src/app/modules/action-keys/action-keys.component';
|
||||||
|
import { CreationType, MemberCreateDialogComponent } from 'src/app/modules/add-member-dialog/member-create-dialog.component';
|
||||||
import { UserGrantRoleDialogComponent } from 'src/app/modules/user-grant-role-dialog/user-grant-role-dialog.component';
|
import { UserGrantRoleDialogComponent } from 'src/app/modules/user-grant-role-dialog/user-grant-role-dialog.component';
|
||||||
import { Member } from 'src/app/proto/generated/zitadel/member_pb';
|
import { Member } from 'src/app/proto/generated/zitadel/member_pb';
|
||||||
import { GrantedProject, ProjectGrantState, Role } from 'src/app/proto/generated/zitadel/project_pb';
|
import { GrantedProject, ProjectGrantState, Role } from 'src/app/proto/generated/zitadel/project_pb';
|
||||||
|
import { User } from 'src/app/proto/generated/zitadel/user_pb';
|
||||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
|
||||||
import {
|
|
||||||
ProjectGrantMembersCreateDialogComponent,
|
|
||||||
ProjectGrantMembersCreateDialogExportType,
|
|
||||||
} from './project-grant-members-create-dialog/project-grant-members-create-dialog.component';
|
|
||||||
import { ProjectGrantMembersDataSource } from './project-grant-members-datasource';
|
import { ProjectGrantMembersDataSource } from './project-grant-members-datasource';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -69,25 +67,29 @@ export class ProjectGrantDetailComponent {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.mgmtService.getProjectGrantByID(this.grantid, this.projectid).then((resp) => {
|
this.mgmtService
|
||||||
if (resp.projectGrant) {
|
.getProjectGrantByID(this.grantid, this.projectid)
|
||||||
this.grant = resp.projectGrant;
|
.then((resp) => {
|
||||||
|
console.log(resp);
|
||||||
|
if (resp.projectGrant) {
|
||||||
|
this.grant = resp.projectGrant;
|
||||||
|
|
||||||
const breadcrumbs = [
|
const breadcrumbs = [
|
||||||
new Breadcrumb({
|
new Breadcrumb({
|
||||||
type: BreadcrumbType.ORG,
|
type: BreadcrumbType.ORG,
|
||||||
routerLink: ['/org'],
|
routerLink: ['/org'],
|
||||||
}),
|
}),
|
||||||
new Breadcrumb({
|
new Breadcrumb({
|
||||||
type: BreadcrumbType.PROJECT,
|
type: BreadcrumbType.PROJECT,
|
||||||
name: '',
|
name: '',
|
||||||
param: { key: 'projectid', value: resp.projectGrant.projectId },
|
param: { key: 'projectid', value: resp.projectGrant.projectId },
|
||||||
routerLink: ['/projects', resp.projectGrant.projectId],
|
routerLink: ['/projects', resp.projectGrant.projectId],
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
this.breadcrumbService.setBreadcrumb(breadcrumbs);
|
this.breadcrumbService.setBreadcrumb(breadcrumbs);
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.catch(this.toast.showError);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,36 +178,35 @@ export class ProjectGrantDetailComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async openAddMember(): Promise<any> {
|
public async openAddMember(): Promise<any> {
|
||||||
const keysList = await this.mgmtService.listProjectGrantMemberRoles();
|
const dialogRef = this.dialog.open(MemberCreateDialogComponent, {
|
||||||
|
|
||||||
const dialogRef = this.dialog.open(ProjectGrantMembersCreateDialogComponent, {
|
|
||||||
data: {
|
data: {
|
||||||
roleKeysList: keysList.resultList,
|
creationType: CreationType.PROJECT_GRANTED,
|
||||||
},
|
},
|
||||||
width: '400px',
|
width: '400px',
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((dataToAdd: ProjectGrantMembersCreateDialogExportType) => {
|
dialogRef.afterClosed().subscribe((resp) => {
|
||||||
if (dataToAdd) {
|
if (resp) {
|
||||||
Promise.all(
|
const users: User.AsObject[] = resp.users;
|
||||||
dataToAdd.userIds.map((userid: string) => {
|
const roles: string[] = resp.roles;
|
||||||
return this.mgmtService.addProjectGrantMember(
|
|
||||||
this.grant.projectId,
|
if (users && users.length && roles && roles.length) {
|
||||||
this.grant.grantId,
|
const userIds = users.map((user) => user.id);
|
||||||
userid,
|
Promise.all(
|
||||||
dataToAdd.rolesKeyList,
|
userIds.map((userid: string) => {
|
||||||
);
|
return this.mgmtService.addProjectGrantMember(this.grant.projectId, this.grant.grantId, userid, resp.roles);
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.toast.showInfo('PROJECT.GRANT.TOAST.PROJECTGRANTMEMBERADDED', true);
|
this.toast.showInfo('PROJECT.GRANT.TOAST.PROJECTGRANTMEMBERADDED', true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.changePage.emit();
|
this.changePage.emit();
|
||||||
}, 3000);
|
}, 3000);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.toast.showError(error);
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
|||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||||
import { ActionKeysModule } from 'src/app/modules/action-keys/action-keys.module';
|
import { ActionKeysModule } from 'src/app/modules/action-keys/action-keys.module';
|
||||||
|
import { MemberCreateDialogModule } from 'src/app/modules/add-member-dialog/member-create-dialog.module';
|
||||||
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
|
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
|
||||||
import { InputModule } from 'src/app/modules/input/input.module';
|
import { InputModule } from 'src/app/modules/input/input.module';
|
||||||
import { MembersTableModule } from 'src/app/modules/members-table/members-table.module';
|
import { MembersTableModule } from 'src/app/modules/members-table/members-table.module';
|
||||||
@@ -25,16 +26,12 @@ import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.mod
|
|||||||
import { ProjectGrantDetailRoutingModule } from './project-grant-detail-routing.module';
|
import { ProjectGrantDetailRoutingModule } from './project-grant-detail-routing.module';
|
||||||
import { ProjectGrantDetailComponent } from './project-grant-detail.component';
|
import { ProjectGrantDetailComponent } from './project-grant-detail.component';
|
||||||
import { ProjectGrantIllustrationComponent } from './project-grant-illustration/project-grant-illustration.component';
|
import { ProjectGrantIllustrationComponent } from './project-grant-illustration/project-grant-illustration.component';
|
||||||
import {
|
|
||||||
ProjectGrantMembersCreateDialogModule,
|
|
||||||
} from './project-grant-members-create-dialog/project-grant-members-create-dialog.module';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [ProjectGrantDetailComponent, ProjectGrantIllustrationComponent],
|
declarations: [ProjectGrantDetailComponent, ProjectGrantIllustrationComponent],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
ProjectGrantDetailRoutingModule,
|
ProjectGrantDetailRoutingModule,
|
||||||
ProjectGrantMembersCreateDialogModule,
|
|
||||||
MatAutocompleteModule,
|
MatAutocompleteModule,
|
||||||
HasRoleModule,
|
HasRoleModule,
|
||||||
MatChipsModule,
|
MatChipsModule,
|
||||||
@@ -54,6 +51,7 @@ import {
|
|||||||
TranslateModule,
|
TranslateModule,
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
DetailLayoutModule,
|
DetailLayoutModule,
|
||||||
|
MemberCreateDialogModule,
|
||||||
HasRolePipeModule,
|
HasRolePipeModule,
|
||||||
MembersTableModule,
|
MembersTableModule,
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
|
@@ -13,7 +13,6 @@ export class ProjectGrantIllustrationComponent {
|
|||||||
@Output() public editRoleClicked: EventEmitter<void> = new EventEmitter();
|
@Output() public editRoleClicked: EventEmitter<void> = new EventEmitter();
|
||||||
|
|
||||||
ProjectGrantState: any = ProjectGrantState;
|
ProjectGrantState: any = ProjectGrantState;
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
public removeRole(roleKey: string): void {
|
public removeRole(roleKey: string): void {
|
||||||
this.roleRemoved.emit(roleKey);
|
this.roleRemoved.emit(roleKey);
|
||||||
|
@@ -1,27 +0,0 @@
|
|||||||
<h1 mat-dialog-title>
|
|
||||||
<span class="title">{{'MEMBER.ADD' | translate}}</span>
|
|
||||||
</h1>
|
|
||||||
<p class="desc"> {{'ORG_DETAIL.MEMBER.ADDDESCRIPTION' | translate}}</p>
|
|
||||||
<div mat-dialog-content>
|
|
||||||
<cnsl-search-user-autocomplete (selectionChanged)="selectUsers($event)">
|
|
||||||
</cnsl-search-user-autocomplete>
|
|
||||||
|
|
||||||
<cnsl-form-field class="full-width" appearance="outline">
|
|
||||||
<cnsl-label>{{ 'PROJECT.MEMBER.ROLES' | translate }}</cnsl-label>
|
|
||||||
<mat-select [(ngModel)]="roleKeyList" multiple>
|
|
||||||
<mat-option *ngFor="let key of data.roleKeysList" [value]="key">
|
|
||||||
{{ key }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</cnsl-form-field>
|
|
||||||
</div>
|
|
||||||
<div mat-dialog-actions class="action">
|
|
||||||
<button mat-stroked-button (click)="closeDialog()">
|
|
||||||
{{'ACTIONS.CANCEL' | translate}}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button [disabled]="userIds.length === 0 || roleKeyList.length === 0" color="primary" mat-raised-button
|
|
||||||
class="ok-button" (click)="closeDialogWithSuccess()">
|
|
||||||
{{'ACTIONS.ADD' | translate}}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
@@ -1,12 +0,0 @@
|
|||||||
.full-width {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
.ok-button {
|
|
||||||
margin-left: .5rem;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,25 +0,0 @@
|
|||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { ProjectGrantMembersCreateDialogComponent } from './project-grant-members-create-dialog.component';
|
|
||||||
|
|
||||||
describe('ProjectGrantMembersCreateDialogComponent', () => {
|
|
||||||
let component: ProjectGrantMembersCreateDialogComponent;
|
|
||||||
let fixture: ComponentFixture<ProjectGrantMembersCreateDialogComponent>;
|
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [ProjectGrantMembersCreateDialogComponent],
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ProjectGrantMembersCreateDialogComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,42 +0,0 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
|
||||||
import { FormGroup } from '@angular/forms';
|
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
|
||||||
import { User } from 'src/app/proto/generated/zitadel/user_pb';
|
|
||||||
|
|
||||||
export interface ProjectGrantMembersCreateDialogExportType {
|
|
||||||
userIds: string[];
|
|
||||||
rolesKeyList: string[];
|
|
||||||
}
|
|
||||||
@Component({
|
|
||||||
selector: 'cnsl-project-grant-members-create-dialog',
|
|
||||||
templateUrl: './project-grant-members-create-dialog.component.html',
|
|
||||||
styleUrls: ['./project-grant-members-create-dialog.component.scss'],
|
|
||||||
})
|
|
||||||
export class ProjectGrantMembersCreateDialogComponent {
|
|
||||||
public form!: FormGroup;
|
|
||||||
public userIds: string[] = [];
|
|
||||||
public roleKeyList: string[] = [];
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
public dialogRef: MatDialogRef<ProjectGrantMembersCreateDialogComponent>,
|
|
||||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
|
||||||
) { }
|
|
||||||
|
|
||||||
public selectUsers(users: User.AsObject | User.AsObject[]): void {
|
|
||||||
if (Array.isArray(users)) {
|
|
||||||
this.userIds = users.map(user => user.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public closeDialog(): void {
|
|
||||||
this.dialogRef.close(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public closeDialogWithSuccess(): void {
|
|
||||||
const exportData: ProjectGrantMembersCreateDialogExportType = {
|
|
||||||
userIds: this.userIds,
|
|
||||||
rolesKeyList: this.roleKeyList,
|
|
||||||
};
|
|
||||||
this.dialogRef.close(exportData);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,27 +0,0 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { FormsModule } from '@angular/forms';
|
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
|
||||||
import { MatSelectModule } from '@angular/material/select';
|
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
|
||||||
import { InputModule } from 'src/app/modules/input/input.module';
|
|
||||||
import { SearchUserAutocompleteModule } from 'src/app/modules/search-user-autocomplete/search-user-autocomplete.module';
|
|
||||||
|
|
||||||
import { ProjectGrantMembersCreateDialogComponent } from './project-grant-members-create-dialog.component';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
declarations: [ProjectGrantMembersCreateDialogComponent],
|
|
||||||
imports: [
|
|
||||||
CommonModule,
|
|
||||||
FormsModule,
|
|
||||||
MatDialogModule,
|
|
||||||
MatButtonModule,
|
|
||||||
TranslateModule,
|
|
||||||
MatSelectModule,
|
|
||||||
InputModule,
|
|
||||||
SearchUserAutocompleteModule,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
export class ProjectGrantMembersCreateDialogModule { }
|
|
||||||
|
|
@@ -1,4 +1,9 @@
|
|||||||
<cnsl-create-layout title="{{ 'PROJECT.PAGES.CREATE' | translate }}" [createSteps]="1" [currentCreateStep]="1">
|
<cnsl-create-layout
|
||||||
|
title="{{ 'PROJECT.PAGES.CREATE' | translate }}"
|
||||||
|
[createSteps]="1"
|
||||||
|
[currentCreateStep]="1"
|
||||||
|
(closed)="close()"
|
||||||
|
>
|
||||||
<h1>{{ 'PROJECT.PAGES.CREATE_DESC' | translate }}</h1>
|
<h1>{{ 'PROJECT.PAGES.CREATE_DESC' | translate }}</h1>
|
||||||
<form cdkFocusRegionStart (ngSubmit)="saveProject()">
|
<form cdkFocusRegionStart (ngSubmit)="saveProject()">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sub {
|
.sub {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 1.5rem;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: map-get($foreground, base);
|
color: map-get($foreground, text);
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<div class="max-width-container">
|
<div class="max-width-container">
|
||||||
<cnsl-meta-layout>
|
<cnsl-meta-layout>
|
||||||
<cnsl-sidenav [(ngModel)]="currentSetting" [settingsList]="settingsList">
|
<cnsl-sidenav [(ngModel)]="currentSetting" [settingsList]="settingsList" queryParam="id">
|
||||||
<ng-container *ngIf="currentSetting === 'general'">
|
<ng-container *ngIf="currentSetting === 'general'">
|
||||||
<cnsl-card
|
<cnsl-card
|
||||||
*ngIf="user && user.human && user.human.profile"
|
*ngIf="user && user.human && user.human.profile"
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: map-get($foreground, base);
|
color: map-get($foreground, text);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
@@ -2,8 +2,9 @@ import { MediaMatcher } from '@angular/cdk/layout';
|
|||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, EventEmitter, OnDestroy } from '@angular/core';
|
import { Component, EventEmitter, OnDestroy } from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { ActivatedRoute, Params } from '@angular/router';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription, take } from 'rxjs';
|
||||||
import { ChangeType } from 'src/app/modules/changes/changes.component';
|
import { ChangeType } from 'src/app/modules/changes/changes.component';
|
||||||
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
|
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
|
||||||
import { UserGrantContext } from 'src/app/modules/user-grants/user-grants-datasource';
|
import { UserGrantContext } from 'src/app/modules/user-grants/user-grants-datasource';
|
||||||
@@ -57,7 +58,15 @@ export class AuthUserDetailComponent implements OnDestroy {
|
|||||||
private breadcrumbService: BreadcrumbService,
|
private breadcrumbService: BreadcrumbService,
|
||||||
private mediaMatcher: MediaMatcher,
|
private mediaMatcher: MediaMatcher,
|
||||||
private _location: Location,
|
private _location: Location,
|
||||||
|
activatedRoute: ActivatedRoute,
|
||||||
) {
|
) {
|
||||||
|
activatedRoute.queryParams.pipe(take(1)).subscribe((params: Params) => {
|
||||||
|
const { id } = params;
|
||||||
|
if (id) {
|
||||||
|
this.currentSetting = id;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const mediaq: string = '(max-width: 500px)';
|
const mediaq: string = '(max-width: 500px)';
|
||||||
const small = this.mediaMatcher.matchMedia(mediaq).matches;
|
const small = this.mediaMatcher.matchMedia(mediaq).matches;
|
||||||
if (small) {
|
if (small) {
|
||||||
|
@@ -1,42 +1,55 @@
|
|||||||
<div mat-dialog-title class="title-row">
|
<div class="title-row">
|
||||||
<h1 class="title">{{'USER.METADATA.TITLE' | translate}}</h1>
|
<h1 class="metadata-title">{{ 'USER.METADATA.TITLE' | translate }}</h1>
|
||||||
<span class="fill-space"></span>
|
<span class="fill-space"></span>
|
||||||
<p *ngIf="ts" class="ts cnsl-secondary-text">{{ts | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}</p>
|
<p *ngIf="ts" class="ts cnsl-secondary-text">{{ ts | timestampToDate | localizedDate: 'dd. MMM, HH:mm' }}</p>
|
||||||
<mat-spinner *ngIf="loading" diameter="20"></mat-spinner>
|
<mat-spinner *ngIf="loading" diameter="20"></mat-spinner>
|
||||||
<button class="icon-button" mat-icon-button (click)="load()">
|
<button class="icon-button" mat-icon-button (click)="load()">
|
||||||
<mat-icon class="icon">refresh</mat-icon>
|
<mat-icon class="icon">refresh</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="desc">{{'USER.METADATA.DESCRIPTION' | translate}}</p>
|
<p class="desc">{{ 'USER.METADATA.DESCRIPTION' | translate }}</p>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content class="metadata-dialog-content">
|
||||||
<form *ngFor="let md of metadata; index as i" (ngSubmit)="saveElement(i)">
|
<form *ngFor="let md of metadata; index as i" (ngSubmit)="saveElement(i)">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<cnsl-form-field #key id="key{{i}}" class="formfield">
|
<cnsl-form-field #key id="key{{ i }}" class="formfield">
|
||||||
<cnsl-label>{{ 'USER.METADATA.KEY' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.METADATA.KEY' | translate }}</cnsl-label>
|
||||||
<input cnslInput [(ngModel)]="md.key" [ngModelOptions]="{standalone: true}" />
|
<input cnslInput [(ngModel)]="md.key" [ngModelOptions]="{ standalone: true }" />
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field #value id="value{{i}}" class="formfield">
|
<cnsl-form-field #value id="value{{ i }}" class="formfield">
|
||||||
<cnsl-label>{{ 'USER.METADATA.VALUE' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.METADATA.VALUE' | translate }}</cnsl-label>
|
||||||
<input cnslInput [(ngModel)]="md.value" [ngModelOptions]="{standalone: true}" />
|
<input cnslInput [(ngModel)]="md.value" [ngModelOptions]="{ standalone: true }" />
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
<button mat-icon-button [disabled]="!(md.key && md.value)" class="set-button" type="submit" color="primary"
|
<button
|
||||||
matTooltip="{{ 'ACTIONS.SAVE' | translate }}">
|
mat-icon-button
|
||||||
|
[disabled]="!(md.key && md.value)"
|
||||||
|
class="set-button"
|
||||||
|
type="submit"
|
||||||
|
color="primary"
|
||||||
|
matTooltip="{{ 'ACTIONS.SAVE' | translate }}"
|
||||||
|
>
|
||||||
<i class="las la-save"></i>
|
<i class="las la-save"></i>
|
||||||
</button>
|
</button>
|
||||||
<button mat-icon-button (click)="removeEntry(i)" [disabled]="metadata.length < 2 && i === 0 && !md.key"
|
<button
|
||||||
class="rm-button" type="button" color="warn" matTooltip="{{ 'ACTIONS.REMOVE' | translate }}">
|
mat-icon-button
|
||||||
|
(click)="removeEntry(i)"
|
||||||
|
[disabled]="metadata.length < 2 && i === 0 && !md.key"
|
||||||
|
class="rm-button"
|
||||||
|
type="button"
|
||||||
|
color="warn"
|
||||||
|
matTooltip="{{ 'ACTIONS.REMOVE' | translate }}"
|
||||||
|
>
|
||||||
<i class="las la-trash"></i>
|
<i class="las la-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<button color="primary" (click)="addEntry()" mat-stroked-button color="primary" class="continue-button" type="button">
|
<button (click)="addEntry()" mat-stroked-button class="continue-button" type="button">
|
||||||
<mat-icon>add</mat-icon>
|
<mat-icon>add</mat-icon>
|
||||||
{{ 'ACTIONS.ADD' | translate }}
|
{{ 'ACTIONS.ADD' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div mat-dialog-actions class="action">
|
<div mat-dialog-actions class="action">
|
||||||
<button cdkFocusInitial color="primary" mat-stroked-button class="ok-button" (click)="closeDialog()">
|
<button cdkFocusInitial mat-stroked-button class="ok-button" (click)="closeDialog()">
|
||||||
{{'ACTIONS.CLOSE' | translate}}
|
{{ 'ACTIONS.CLOSE' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,8 +2,8 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.title {
|
.metadata-title {
|
||||||
font-size: 1.5rem;
|
font-size: 1.3rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,23 +23,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.metadata-dialog-content {
|
||||||
display: flex;
|
min-width: 400px;
|
||||||
align-items: center;
|
|
||||||
margin: 0 -0.5rem;
|
|
||||||
|
|
||||||
.formfield {
|
.content {
|
||||||
flex: 1;
|
display: flex;
|
||||||
margin: 0 0.5rem;
|
align-items: center;
|
||||||
|
margin: 0 -0.5rem;
|
||||||
|
|
||||||
@media only screen and (max-width: 450px) {
|
.formfield {
|
||||||
flex-basis: 100%;
|
flex: 1;
|
||||||
|
margin: 0 0.5rem;
|
||||||
|
|
||||||
|
@media only screen and (max-width: 450px) {
|
||||||
|
flex-basis: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.rm-button,
|
.rm-button,
|
||||||
.set-button {
|
.set-button {
|
||||||
margin-top: 14px;
|
margin-top: 14px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,22 +1,17 @@
|
|||||||
<cnsl-card class="metadata-details" title="{{ 'USER.METADATA.TITLE' | translate }}">
|
<cnsl-card class="metadata-details" title="{{ 'USER.METADATA.TITLE' | translate }}">
|
||||||
<div card-actions class="actions">
|
<div class="metadata-actions">
|
||||||
<mat-spinner class="spinner" diameter="20" *ngIf="loading"></mat-spinner>
|
<mat-spinner class="spinner" diameter="20" *ngIf="loading"></mat-spinner>
|
||||||
<button mat-raised-button color="primary" class="edit" (click)="editMetadata()">{{'ACTIONS.EDIT' |
|
<button mat-raised-button color="primary" class="edit" (click)="editMetadata()">{{ 'ACTIONS.EDIT' | translate }}</button>
|
||||||
translate}}</button>
|
|
||||||
<button matTooltip="{{'ACTIONS.REFRESH' | translate}}" class="refresh-btn" (click)="loadMetadata()" mat-icon-button
|
|
||||||
aria-label="refresh contributors">
|
|
||||||
<mat-icon class="icon">refresh</mat-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-container *ngIf="metadata?.length; else emptyList">
|
<ng-container *ngIf="metadata?.length; else emptyList">
|
||||||
<div class="metadata-set" *ngFor="let md of metadata">
|
<div class="metadata-set" *ngFor="let md of metadata">
|
||||||
<span class="first cnsl-secondary-text">{{md.key}}</span>
|
<span class="first cnsl-secondary-text">{{ md.key }}</span>
|
||||||
<span class="second">{{ md.value }}</span>
|
<span class="second">{{ md.value }}</span>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-template #emptyList>
|
<ng-template #emptyList>
|
||||||
<p class="empty-desc cnsl-secondary-text">{{'USER.METADATA.EMPTY' | translate}}</p>
|
<p class="empty-desc cnsl-secondary-text">{{ 'USER.METADATA.EMPTY' | translate }}</p>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</cnsl-card>
|
</cnsl-card>
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
.metadata-details {
|
.metadata-details {
|
||||||
padding-bottom: 1rem;
|
padding-bottom: 1rem;
|
||||||
|
|
||||||
.actions {
|
.metadata-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
.edit {
|
.edit {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -53,6 +54,7 @@
|
|||||||
.empty-desc {
|
.empty-desc {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.refresh-btn {
|
.refresh-btn {
|
||||||
|
@@ -16,8 +16,7 @@ export class MetadataComponent implements OnInit {
|
|||||||
public metadata: Metadata.AsObject[] = [];
|
public metadata: Metadata.AsObject[] = [];
|
||||||
public loading: boolean = false;
|
public loading: boolean = false;
|
||||||
|
|
||||||
constructor(private dialog: MatDialog, private service: ManagementService, private toast: ToastService,
|
constructor(private dialog: MatDialog, private service: ManagementService, private toast: ToastService) {}
|
||||||
) { }
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.loadMetadata();
|
this.loadMetadata();
|
||||||
@@ -37,17 +36,20 @@ export class MetadataComponent implements OnInit {
|
|||||||
|
|
||||||
public loadMetadata(): Promise<any> {
|
public loadMetadata(): Promise<any> {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
return (this.service as ManagementService).listUserMetadata(this.userId).then(resp => {
|
return (this.service as ManagementService)
|
||||||
this.loading = false;
|
.listUserMetadata(this.userId)
|
||||||
this.metadata = resp.resultList.map(md => {
|
.then((resp) => {
|
||||||
return {
|
this.loading = false;
|
||||||
key: md.key,
|
this.metadata = resp.resultList.map((md) => {
|
||||||
value: atob(md.value as string),
|
return {
|
||||||
};
|
key: md.key,
|
||||||
|
value: atob(md.value as string),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.loading = false;
|
||||||
|
this.toast.showError(error);
|
||||||
});
|
});
|
||||||
}).catch((error) => {
|
|
||||||
this.loading = false;
|
|
||||||
this.toast.showError(error);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,9 @@
|
|||||||
</cnsl-top-view>
|
</cnsl-top-view>
|
||||||
|
|
||||||
<div *ngIf="loading" class="max-width-container">
|
<div *ngIf="loading" class="max-width-container">
|
||||||
<mat-progress-spinner diameter="25" color="primary" mode="indeterminate"></mat-progress-spinner>
|
<div class="sp-wrapper">
|
||||||
|
<mat-progress-spinner diameter="25" color="primary" mode="indeterminate"></mat-progress-spinner>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="!loading && !user" class="max-width-container">
|
<div *ngIf="!loading && !user" class="max-width-container">
|
||||||
@@ -46,7 +48,7 @@
|
|||||||
|
|
||||||
<div class="max-width-container" *ngIf="user && (['user.write$', 'user.write:' + user.id] | hasRole) as canWrite$">
|
<div class="max-width-container" *ngIf="user && (['user.write$', 'user.write:' + user.id] | hasRole) as canWrite$">
|
||||||
<cnsl-meta-layout>
|
<cnsl-meta-layout>
|
||||||
<cnsl-sidenav [(ngModel)]="currentSetting" [settingsList]="settingsList">
|
<cnsl-sidenav [(ngModel)]="currentSetting" [settingsList]="settingsList" queryParam="id">
|
||||||
<div *ngIf="error" class="max-width-container">
|
<div *ngIf="error" class="max-width-container">
|
||||||
<p>{{ error }}</p>
|
<p>{{ error }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -42,3 +42,7 @@
|
|||||||
.resendemail {
|
.resendemail {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sp-wrapper {
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
@@ -65,9 +65,17 @@ export class UserDetailComponent implements OnInit {
|
|||||||
private _location: Location,
|
private _location: Location,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
activatedRoute: ActivatedRoute,
|
||||||
private mediaMatcher: MediaMatcher,
|
private mediaMatcher: MediaMatcher,
|
||||||
breadcrumbService: BreadcrumbService,
|
breadcrumbService: BreadcrumbService,
|
||||||
) {
|
) {
|
||||||
|
activatedRoute.queryParams.pipe(take(1)).subscribe((params: Params) => {
|
||||||
|
const { id } = params;
|
||||||
|
if (id) {
|
||||||
|
this.currentSetting = id;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
breadcrumbService.setBreadcrumb([
|
breadcrumbService.setBreadcrumb([
|
||||||
new Breadcrumb({
|
new Breadcrumb({
|
||||||
type: BreadcrumbType.ORG,
|
type: BreadcrumbType.ORG,
|
||||||
|
@@ -3,14 +3,17 @@
|
|||||||
<ng-container *ngSwitchCase="Type.TYPE_HUMAN">
|
<ng-container *ngSwitchCase="Type.TYPE_HUMAN">
|
||||||
<div class="users-title-row">
|
<div class="users-title-row">
|
||||||
<h1>{{ 'USER.PAGES.LIST' | translate }}</h1>
|
<h1>{{ 'USER.PAGES.LIST' | translate }}</h1>
|
||||||
<a mat-icon-button href="https://docs.zitadel.com/docs/concepts/structure/users" rel="noreferrer"
|
<a mat-icon-button href="https://docs.zitadel.com/docs/concepts/structure/users" rel="noreferrer" target="_blank">
|
||||||
target="_blank">
|
|
||||||
<i class="las la-info-circle"></i>
|
<i class="las la-info-circle"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<p class="user-list-sub cnsl-secondary-text">{{ 'USER.PAGES.DESCRIPTION' | translate }}</p>
|
<p class="user-list-sub cnsl-secondary-text">{{ 'USER.PAGES.DESCRIPTION' | translate }}</p>
|
||||||
|
|
||||||
<cnsl-user-table [type]="Type.TYPE_HUMAN" [disabled]="(['user.write$'] | hasRole | async) === false">
|
<cnsl-user-table
|
||||||
|
[type]="Type.TYPE_HUMAN"
|
||||||
|
[canWrite]="!!(['user.write$'] | hasRole | async)"
|
||||||
|
[canDelete]="!!(['user.delete$'] | hasRole | async)"
|
||||||
|
>
|
||||||
</cnsl-user-table>
|
</cnsl-user-table>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
@@ -18,8 +21,12 @@
|
|||||||
<h1>{{ 'USER.PAGES.LISTMACHINE' | translate }}</h1>
|
<h1>{{ 'USER.PAGES.LISTMACHINE' | translate }}</h1>
|
||||||
<p class="user-list-sub cnsl-secondary-text">{{ 'USER.PAGES.DESCRIPTIONMACHINE' | translate }}</p>
|
<p class="user-list-sub cnsl-secondary-text">{{ 'USER.PAGES.DESCRIPTIONMACHINE' | translate }}</p>
|
||||||
|
|
||||||
<cnsl-user-table [type]="Type.TYPE_MACHINE" [disabled]="(['user.write$'] | hasRole | async) === false">
|
<cnsl-user-table
|
||||||
|
[type]="Type.TYPE_MACHINE"
|
||||||
|
[canWrite]="!!(['user.write$'] | hasRole | async)"
|
||||||
|
[canDelete]="!!(['user.delete$'] | hasRole | async)"
|
||||||
|
>
|
||||||
</cnsl-user-table>
|
</cnsl-user-table>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -14,6 +14,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.user-list-sub {
|
.user-list-sub {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 1.5rem;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
@@ -1,35 +1,64 @@
|
|||||||
<cnsl-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="totalResult"
|
<cnsl-refresh-table
|
||||||
[hideRefresh]="true" [timestamp]="viewTimestamp" [selection]="selection"
|
[loading]="loading$ | async"
|
||||||
[emitRefreshOnPreviousRoutes]="refreshOnPreviousRoutes" [showBorder]="true">
|
(refreshed)="refreshPage()"
|
||||||
|
[dataSize]="totalResult"
|
||||||
|
[hideRefresh]="true"
|
||||||
|
[timestamp]="viewTimestamp"
|
||||||
|
[selection]="selection"
|
||||||
|
[emitRefreshOnPreviousRoutes]="refreshOnPreviousRoutes"
|
||||||
|
[showBorder]="true"
|
||||||
|
>
|
||||||
<div leftActions class="user-table-left-actions">
|
<div leftActions class="user-table-left-actions">
|
||||||
<button class="type-button" [ngClass]="{'active': type === Type.TYPE_HUMAN}"
|
<button class="type-button" [ngClass]="{ active: type === Type.TYPE_HUMAN }" (click)="setType(Type.TYPE_HUMAN)">
|
||||||
(click)="setType(Type.TYPE_HUMAN)">{{'USER.TABLE.TYPES.HUMAN' | translate}}</button>
|
{{ 'USER.TABLE.TYPES.HUMAN' | translate }}
|
||||||
<button class="type-button" [ngClass]="{'active': type === Type.TYPE_MACHINE}"
|
</button>
|
||||||
(click)="setType(Type.TYPE_MACHINE)">{{'USER.TABLE.TYPES.MACHINE' | translate}}</button>
|
<button class="type-button" [ngClass]="{ active: type === Type.TYPE_MACHINE }" (click)="setType(Type.TYPE_MACHINE)">
|
||||||
|
{{ 'USER.TABLE.TYPES.MACHINE' | translate }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-template cnslHasRole [hasRole]="['user.write']" actions>
|
<ng-template cnslHasRole [hasRole]="['user.write']" actions>
|
||||||
<button (click)="deactivateSelectedUsers()" class="cnsl-action-button bg-state inactive" mat-raised-button
|
<button
|
||||||
*ngIf="selection.hasValue() && multipleDeactivatePossible" [disabled]="disabled" color="primary">
|
(click)="deactivateSelectedUsers()"
|
||||||
<span class="">{{'USER.TABLE.DEACTIVATE' | translate}}</span>
|
class="cnsl-action-button bg-state inactive"
|
||||||
<cnsl-action-keys (actionTriggered)="deactivateSelectedUsers()" [type]="ActionKeysType.DEACTIVATE">
|
mat-raised-button
|
||||||
</cnsl-action-keys>
|
*ngIf="selection.hasValue() && multipleDeactivatePossible"
|
||||||
|
[disabled]="!canWrite"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
<span class="">{{ 'USER.TABLE.DEACTIVATE' | translate }}</span>
|
||||||
|
<cnsl-action-keys (actionTriggered)="deactivateSelectedUsers()" [type]="ActionKeysType.DEACTIVATE"> </cnsl-action-keys>
|
||||||
</button>
|
</button>
|
||||||
<button (click)="reactivateSelectedUsers()" class="cnsl-action-button bg-state active margin-left" mat-raised-button
|
<button
|
||||||
*ngIf="selection.hasValue() && multipleActivatePossible" [disabled]="disabled" color="primary">
|
(click)="reactivateSelectedUsers()"
|
||||||
<span class="">{{'USER.TABLE.ACTIVATE' | translate}}</span>
|
class="cnsl-action-button bg-state active margin-left"
|
||||||
<cnsl-action-keys (actionTriggered)="reactivateSelectedUsers()" [type]="ActionKeysType.REACTIVATE">
|
mat-raised-button
|
||||||
</cnsl-action-keys>
|
*ngIf="selection.hasValue() && multipleActivatePossible"
|
||||||
|
[disabled]="!canWrite"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
<span class="">{{ 'USER.TABLE.ACTIVATE' | translate }}</span>
|
||||||
|
<cnsl-action-keys (actionTriggered)="reactivateSelectedUsers()" [type]="ActionKeysType.REACTIVATE"> </cnsl-action-keys>
|
||||||
</button>
|
</button>
|
||||||
<cnsl-filter-user *ngIf="!selection.hasValue()" (filterChanged)="applySearchQuery($any($event))"
|
<cnsl-filter-user
|
||||||
(filterOpen)="filterOpen = $event"></cnsl-filter-user>
|
*ngIf="!selection.hasValue()"
|
||||||
<a *ngIf="!selection.hasValue()" [routerLink]="[ '/users',type === Type.TYPE_HUMAN ? 'create' : 'create-machine']"
|
(filterChanged)="applySearchQuery($any($event))"
|
||||||
color="primary" mat-raised-button [disabled]="disabled" class="cnsl-action-button">
|
(filterOpen)="filterOpen = $event"
|
||||||
|
></cnsl-filter-user>
|
||||||
|
<a
|
||||||
|
*ngIf="!selection.hasValue()"
|
||||||
|
[routerLink]="['/users', type === Type.TYPE_HUMAN ? 'create' : 'create-machine']"
|
||||||
|
color="primary"
|
||||||
|
mat-raised-button
|
||||||
|
[disabled]="!canWrite"
|
||||||
|
class="cnsl-action-button"
|
||||||
|
>
|
||||||
<mat-icon class="icon">add</mat-icon>
|
<mat-icon class="icon">add</mat-icon>
|
||||||
<span>{{ 'ACTIONS.NEW' | translate }}</span>
|
<span>{{ 'ACTIONS.NEW' | translate }}</span>
|
||||||
<cnsl-action-keys *ngIf="!filterOpen"
|
<cnsl-action-keys
|
||||||
(actionTriggered)="gotoRouterLink([ '/users',type === Type.TYPE_HUMAN ? 'create' : 'create-machine'])">
|
*ngIf="!filterOpen"
|
||||||
|
(actionTriggered)="gotoRouterLink(['/users', type === Type.TYPE_HUMAN ? 'create' : 'create-machine'])"
|
||||||
|
>
|
||||||
</cnsl-action-keys>
|
</cnsl-action-keys>
|
||||||
</a>
|
</a>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@@ -38,19 +67,37 @@
|
|||||||
<table class="table" mat-table [dataSource]="dataSource" matSort (matSortChange)="sortChange($event)">
|
<table class="table" mat-table [dataSource]="dataSource" matSort (matSortChange)="sortChange($event)">
|
||||||
<ng-container matColumnDef="select">
|
<ng-container matColumnDef="select">
|
||||||
<th mat-header-cell *matHeaderCellDef class="selection">
|
<th mat-header-cell *matHeaderCellDef class="selection">
|
||||||
<mat-checkbox [disabled]="disabled" color="primary" (change)="$event ? masterToggle() : null"
|
<mat-checkbox
|
||||||
|
[disabled]="!canWrite"
|
||||||
|
color="primary"
|
||||||
|
(change)="$event ? masterToggle() : null"
|
||||||
[checked]="selection.hasValue() && isAllSelected()"
|
[checked]="selection.hasValue() && isAllSelected()"
|
||||||
[indeterminate]="selection.hasValue() && !isAllSelected()">
|
[indeterminate]="selection.hasValue() && !isAllSelected()"
|
||||||
|
>
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let user" class="selection">
|
<td mat-cell *matCellDef="let user" class="selection">
|
||||||
<mat-checkbox [disabled]="disabled" color="primary" (click)="$event.stopPropagation()"
|
<mat-checkbox
|
||||||
(change)="$event ? selection.toggle(user) : null" [checked]="selection.isSelected(user)">
|
[disabled]="!canWrite"
|
||||||
|
color="primary"
|
||||||
|
(click)="$event.stopPropagation()"
|
||||||
|
(change)="$event ? selection.toggle(user) : null"
|
||||||
|
[checked]="selection.isSelected(user)"
|
||||||
|
>
|
||||||
<cnsl-avatar
|
<cnsl-avatar
|
||||||
*ngIf="user.human && user.human.profile.displayName && user.human?.profile.firstName && user.human?.profile.lastName; else cog"
|
*ngIf="
|
||||||
class="avatar" [name]="user.human.profile.displayName" [avatarUrl]="user.human?.profile?.avatarUrl || ''"
|
user.human &&
|
||||||
[forColor]="user?.preferredLoginName" [size]="32">
|
user.human.profile.displayName &&
|
||||||
|
user.human?.profile.firstName &&
|
||||||
|
user.human?.profile.lastName;
|
||||||
|
else cog
|
||||||
|
"
|
||||||
|
class="avatar"
|
||||||
|
[name]="user.human.profile.displayName"
|
||||||
|
[avatarUrl]="user.human?.profile?.avatarUrl || ''"
|
||||||
|
[forColor]="user?.preferredLoginName"
|
||||||
|
[size]="32"
|
||||||
|
>
|
||||||
</cnsl-avatar>
|
</cnsl-avatar>
|
||||||
<ng-template #cog>
|
<ng-template #cog>
|
||||||
<cnsl-avatar [forColor]="user?.preferredLoginName" [isMachine]="true">
|
<cnsl-avatar [forColor]="user?.preferredLoginName" [isMachine]="true">
|
||||||
@@ -62,58 +109,74 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="displayName">
|
<ng-container matColumnDef="displayName">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header
|
<th
|
||||||
[ngClass]="{'search-active': this.userSearchKey === UserListSearchKey.DISPLAY_NAME}">
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
mat-sort-header
|
||||||
|
[ngClass]="{ 'search-active': this.userSearchKey === UserListSearchKey.DISPLAY_NAME }"
|
||||||
|
>
|
||||||
{{ 'USER.PROFILE.DISPLAYNAME' | translate }}
|
{{ 'USER.PROFILE.DISPLAYNAME' | translate }}
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id ]: null">
|
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id] : null">
|
||||||
<span *ngIf="user.human">{{user.human.profile?.displayName}}</span>
|
<span *ngIf="user.human">{{ user.human.profile?.displayName }}</span>
|
||||||
<span *ngIf="user.machine">{{user.machine.name}}</span>
|
<span *ngIf="user.machine">{{ user.machine.name }}</span>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="username">
|
<ng-container matColumnDef="username">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header
|
<th
|
||||||
[ngClass]="{'search-active': this.userSearchKey === UserListSearchKey.USER_NAME}">
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
mat-sort-header
|
||||||
|
[ngClass]="{ 'search-active': this.userSearchKey === UserListSearchKey.USER_NAME }"
|
||||||
|
>
|
||||||
{{ 'USER.PROFILE.USERNAME' | translate }}
|
{{ 'USER.PROFILE.USERNAME' | translate }}
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id ]: null">
|
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id] : null">
|
||||||
{{user.userName}} </td>
|
{{ user.userName }}
|
||||||
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="email">
|
<ng-container matColumnDef="email">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header
|
<th
|
||||||
[ngClass]="{'search-active': this.UserListSearchKey === UserListSearchKey.EMAIL}">
|
mat-header-cell
|
||||||
|
*matHeaderCellDef
|
||||||
|
mat-sort-header
|
||||||
|
[ngClass]="{ 'search-active': this.UserListSearchKey === UserListSearchKey.EMAIL }"
|
||||||
|
>
|
||||||
{{ 'USER.EMAIL' | translate }}
|
{{ 'USER.EMAIL' | translate }}
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id ]: null">
|
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id] : null">
|
||||||
<span *ngIf="user.human?.email?.email">{{user.human?.email.email}}</span>
|
<span *ngIf="user.human?.email?.email">{{ user.human?.email.email }}</span>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="state">
|
<ng-container matColumnDef="state">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'USER.DATA.STATE' | translate }} </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'USER.DATA.STATE' | translate }}</th>
|
||||||
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id ]: null">
|
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id] : null">
|
||||||
<span class="state"
|
<span
|
||||||
[ngClass]="{'active': user.state === UserState.USER_STATE_ACTIVE, 'inactive': user.state === UserState.USER_STATE_INACTIVE}">
|
class="state"
|
||||||
{{ 'USER.DATA.STATE'+user.state | translate }}
|
[ngClass]="{
|
||||||
|
active: user.state === UserState.USER_STATE_ACTIVE,
|
||||||
|
inactive: user.state === UserState.USER_STATE_INACTIVE
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ 'USER.DATA.STATE' + user.state | translate }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="creationDate">
|
<ng-container matColumnDef="creationDate">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{'USER.TABLE.CREATIONDATE' | translate}} </th>
|
<th mat-header-cell *matHeaderCellDef>{{ 'USER.TABLE.CREATIONDATE' | translate }}</th>
|
||||||
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id ]: null">
|
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id] : null">
|
||||||
<span class="no-break">{{user.details.creationDate | timestampToDate | localizedDate: 'fromNow'
|
<span class="no-break">{{ user.details.creationDate | timestampToDate | localizedDate: 'fromNow' }}</span>
|
||||||
}}</span>
|
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="changeDate">
|
<ng-container matColumnDef="changeDate">
|
||||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.TABLE.CHANGEDATE' | translate }} </th>
|
<th mat-header-cell *matHeaderCellDef>{{ 'USER.TABLE.CHANGEDATE' | translate }}</th>
|
||||||
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id ]: null">
|
<td mat-cell *matCellDef="let user" [routerLink]="user.id ? ['/users', user.id] : null">
|
||||||
<span class="no-break">{{user.details.changeDate | timestampToDate | localizedDate: 'fromNow'
|
<span class="no-break">{{ user.details.changeDate | timestampToDate | localizedDate: 'fromNow' }}</span>
|
||||||
}}</span>
|
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
@@ -121,28 +184,41 @@
|
|||||||
<th mat-header-cell *matHeaderCellDef class="user-tr-actions"></th>
|
<th mat-header-cell *matHeaderCellDef class="user-tr-actions"></th>
|
||||||
<td mat-cell *matCellDef="let user" class="user-tr-actions">
|
<td mat-cell *matCellDef="let user" class="user-tr-actions">
|
||||||
<cnsl-table-actions>
|
<cnsl-table-actions>
|
||||||
<button actions matTooltip="{{'ACTIONS.REMOVE' | translate}}" color="warn" (click)="deleteUser(user)"
|
<button
|
||||||
mat-icon-button>
|
actions
|
||||||
|
matTooltip="{{ 'ACTIONS.REMOVE' | translate }}"
|
||||||
|
color="warn"
|
||||||
|
(click)="deleteUser(user)"
|
||||||
|
[disabled]="!canWrite || !canDelete"
|
||||||
|
mat-icon-button
|
||||||
|
>
|
||||||
<i class="las la-trash"></i>
|
<i class="las la-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</cnsl-table-actions>
|
</cnsl-table-actions>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="type === Type.TYPE_HUMAN ? displayedColumnsHuman : displayedColumnsMachine">
|
<tr mat-header-row *matHeaderRowDef="type === Type.TYPE_HUMAN ? displayedColumnsHuman : displayedColumnsMachine"></tr>
|
||||||
</tr>
|
<tr
|
||||||
<tr class="highlight pointer" mat-row
|
class="highlight pointer"
|
||||||
*matRowDef="let user; columns: (type === Type.TYPE_HUMAN ? displayedColumnsHuman : displayedColumnsMachine);">
|
mat-row
|
||||||
</tr>
|
*matRowDef="let user; columns: type === Type.TYPE_HUMAN ? displayedColumnsHuman : displayedColumnsMachine"
|
||||||
|
></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="(loading$ | async) === false && !dataSource?.data?.length" class="no-content-row">
|
<div *ngIf="(loading$ | async) === false && !dataSource?.data?.length" class="no-content-row">
|
||||||
<i class="las la-exclamation"></i>
|
<i class="las la-exclamation"></i>
|
||||||
<span>{{'USER.TABLE.EMPTY' | translate}}</span>
|
<span>{{ 'USER.TABLE.EMPTY' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
<cnsl-paginator #paginator class="paginator" [timestamp]="viewTimestamp" [length]="totalResult || 0"
|
<cnsl-paginator
|
||||||
[pageSize]="INITIAL_PAGE_SIZE" [timestamp]="viewTimestamp" [pageSizeOptions]="[10, 20, 50, 100]"
|
#paginator
|
||||||
(page)="changePage($event)"></cnsl-paginator>
|
class="paginator"
|
||||||
</cnsl-refresh-table>
|
[timestamp]="viewTimestamp"
|
||||||
|
[length]="totalResult || 0"
|
||||||
|
[pageSize]="INITIAL_PAGE_SIZE"
|
||||||
|
[timestamp]="viewTimestamp"
|
||||||
|
[pageSizeOptions]="[10, 20, 50, 100]"
|
||||||
|
(page)="changePage($event)"
|
||||||
|
></cnsl-paginator>
|
||||||
|
</cnsl-refresh-table>
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: map-get($foreground, base);
|
color: map-get($foreground, text);
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
|
@@ -37,7 +37,7 @@ export class UserTableComponent implements OnInit {
|
|||||||
public Type: any = Type;
|
public Type: any = Type;
|
||||||
@Input() public type: Type = Type.TYPE_HUMAN;
|
@Input() public type: Type = Type.TYPE_HUMAN;
|
||||||
@Input() refreshOnPreviousRoutes: string[] = [];
|
@Input() refreshOnPreviousRoutes: string[] = [];
|
||||||
@Input() disabled: boolean = false;
|
@Input() canWrite: boolean = false;
|
||||||
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
||||||
@ViewChild(MatSort) public sort!: MatSort;
|
@ViewChild(MatSort) public sort!: MatSort;
|
||||||
public INITIAL_PAGE_SIZE: number = 20;
|
public INITIAL_PAGE_SIZE: number = 20;
|
||||||
@@ -77,6 +77,7 @@ export class UserTableComponent implements OnInit {
|
|||||||
public filterOpen: boolean = false;
|
public filterOpen: boolean = false;
|
||||||
|
|
||||||
private searchQueries: SearchQuery[] = [];
|
private searchQueries: SearchQuery[] = [];
|
||||||
|
@Input() public canDelete: boolean = false;
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
public translate: TranslateService,
|
public translate: TranslateService,
|
||||||
|
@@ -1,37 +1,36 @@
|
|||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Router } from '@angular/router';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
export abstract class StatehandlerProcessorService {
|
export abstract class StatehandlerProcessorService {
|
||||||
public abstract createState(url: string): Observable<string | undefined>;
|
public abstract createState(url: string): string;
|
||||||
public abstract restoreState(state?: string): void;
|
public abstract restoreState(state?: string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StatehandlerProcessorServiceImpl implements StatehandlerProcessorService {
|
export class StatehandlerProcessorServiceImpl implements StatehandlerProcessorService {
|
||||||
constructor(private location: Location) {}
|
constructor(private location: Location, private router: Router) {}
|
||||||
|
|
||||||
public createState(url: string): Observable<string> {
|
public createState(url: string): string {
|
||||||
const externalUrl = this.location.prepareExternalUrl(url);
|
const externalUrl = this.location.prepareExternalUrl(url);
|
||||||
const urlId = uuidv4();
|
const urlId = uuidv4();
|
||||||
|
|
||||||
sessionStorage.setItem(urlId, externalUrl);
|
sessionStorage.setItem(urlId, externalUrl);
|
||||||
|
return urlId;
|
||||||
return of(urlId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public restoreState(state?: string): void {
|
public restoreState(state?: string): void {
|
||||||
if (state === undefined) {
|
if (state === undefined) {
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
const url = sessionStorage.getItem(state);
|
||||||
|
if (url === null) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
sessionStorage.removeItem(state);
|
||||||
|
// window.location.replace(window.location.origin + url);
|
||||||
|
this.router.navigate([url]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = sessionStorage.getItem(state);
|
|
||||||
if (url === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionStorage.removeItem(state);
|
|
||||||
window.location.href = window.location.origin + url;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,9 @@ export class StatehandlerServiceImpl implements StatehandlerService, OnDestroy {
|
|||||||
map(() => oauthService.state),
|
map(() => oauthService.state),
|
||||||
takeUntil(this.unsubscribe$),
|
takeUntil(this.unsubscribe$),
|
||||||
)
|
)
|
||||||
.subscribe((state) => processor.restoreState(state));
|
.subscribe((state) => {
|
||||||
|
processor.restoreState(state);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public initStateHandler(): void {
|
public initStateHandler(): void {
|
||||||
@@ -47,9 +49,11 @@ export class StatehandlerServiceImpl implements StatehandlerService, OnDestroy {
|
|||||||
switchMap((url: string) => {
|
switchMap((url: string) => {
|
||||||
if (url.includes('?login_hint=')) {
|
if (url.includes('?login_hint=')) {
|
||||||
const newUrl = this.removeParam('login_hint', url);
|
const newUrl = this.removeParam('login_hint', url);
|
||||||
return of(newUrl);
|
return of(this.processor.createState(newUrl));
|
||||||
|
} else if (url) {
|
||||||
|
return of(this.processor.createState(url));
|
||||||
} else {
|
} else {
|
||||||
return this.processor.createState(url);
|
return of(undefined);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@@ -57,9 +57,10 @@ export class ThemeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public saveTextColor(colorHex: string, isDark: boolean): void {
|
public saveTextColor(colorHex: string, isDark: boolean): void {
|
||||||
this.primaryColorPalette = this.computeColors(colorHex);
|
|
||||||
const theme = isDark ? 'dark' : 'light';
|
const theme = isDark ? 'dark' : 'light';
|
||||||
document.documentElement.style.setProperty(`--theme-${theme}-${'text'}`, colorHex);
|
document.documentElement.style.setProperty(`--theme-${theme}-${'text'}`, colorHex);
|
||||||
|
const secondaryTextHex = tinycolor(colorHex).setAlpha(0.78).toHex8String();
|
||||||
|
document.documentElement.style.setProperty(`--theme-${theme}-${'secondary-text'}`, secondaryTextHex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private computeColors(hex: string): Color[] {
|
private computeColors(hex: string): Color[] {
|
||||||
|
@@ -35,7 +35,7 @@
|
|||||||
},
|
},
|
||||||
"SHORTCUTS": {
|
"SHORTCUTS": {
|
||||||
"SHORTCUTS": "Shortcuts",
|
"SHORTCUTS": "Shortcuts",
|
||||||
"SETTINGS": "Organisation Einstellungen",
|
"SETTINGS": "Verfügbare Shortcuts",
|
||||||
"PROJECTS": "Projekte",
|
"PROJECTS": "Projekte",
|
||||||
"REORDER": "Zum Verschieben Kachel halten un ziehen",
|
"REORDER": "Zum Verschieben Kachel halten un ziehen",
|
||||||
"ADD": "Zum Hinzufügen Kachel halten und ziehen"
|
"ADD": "Zum Hinzufügen Kachel halten und ziehen"
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
"TEXT": "Hier können Sie zwischen Ihren Benutzerkonten wechseln und Ihre Sessions und Ihr Profil verwalten."
|
"TEXT": "Hier können Sie zwischen Ihren Benutzerkonten wechseln und Ihre Sessions und Ihr Profil verwalten."
|
||||||
},
|
},
|
||||||
"NAV": {
|
"NAV": {
|
||||||
"TEXT": "Diese Navigation ändert sich basierend auf den Breadcrumbs darüber."
|
"TEXT": "Diese Navigation ändert sich basierend auf Ihrer Organisation oder Instanz"
|
||||||
},
|
},
|
||||||
"CONTEXTCHANGED": {
|
"CONTEXTCHANGED": {
|
||||||
"TEXT": "Achtung! Soeben wurde die Organisation gewechselt."
|
"TEXT": "Achtung! Soeben wurde die Organisation gewechselt."
|
||||||
@@ -818,6 +818,7 @@
|
|||||||
"LOCKOUT": "Sperrmechanismen",
|
"LOCKOUT": "Sperrmechanismen",
|
||||||
"COMPLEXITY": "Passwordkomplexität",
|
"COMPLEXITY": "Passwordkomplexität",
|
||||||
"NOTIFICATIONS": "Benachrichtigungen",
|
"NOTIFICATIONS": "Benachrichtigungen",
|
||||||
|
"NOTIFICATIONS_DESC": "SMTP und SMS Einstellungen",
|
||||||
"MESSAGETEXTS": "Benachrichtigungstexte",
|
"MESSAGETEXTS": "Benachrichtigungstexte",
|
||||||
"IDP": "Identity Provider",
|
"IDP": "Identity Provider",
|
||||||
"DOMAIN": "Domain Einstellungen",
|
"DOMAIN": "Domain Einstellungen",
|
||||||
@@ -1181,11 +1182,11 @@
|
|||||||
"DESC": "Sobald der Nutzer identifiziert ist, wird das Branding der von ihm gewählten Organisation angezeigt, davor wird der Default des Systems angezeigt."
|
"DESC": "Sobald der Nutzer identifiziert ist, wird das Branding der von ihm gewählten Organisation angezeigt, davor wird der Default des Systems angezeigt."
|
||||||
},
|
},
|
||||||
"1": {
|
"1": {
|
||||||
"TITLE": "Durchsetzung der Richtlinie des Projekteigentümers",
|
"TITLE": "Einstellung des Projekteigentümers",
|
||||||
"DESC": "Das Branding der Organisation, die Eigentümerin des Projekts ist, wird angezeigt"
|
"DESC": "Das Branding der Organisation, die Eigentümerin des Projekts ist, wird angezeigt"
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
"TITLE": "Durchsetzung der Richtlinie des Benutzereigentümers",
|
"TITLE": "Einstellung des Benutzereigentümers",
|
||||||
"DESC": "Das Branding der Organisation des Projekts wird angezeigt, sobald der Benutzer identifiziert ist, wird jedoch auf die Einstellung der Organisation des identifizierten Benutzers, gewechselt."
|
"DESC": "Das Branding der Organisation des Projekts wird angezeigt, sobald der Benutzer identifiziert ist, wird jedoch auf die Einstellung der Organisation des identifizierten Benutzers, gewechselt."
|
||||||
},
|
},
|
||||||
"DIALOG": {
|
"DIALOG": {
|
||||||
@@ -1549,6 +1550,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DIALOG": {
|
"DIALOG": {
|
||||||
|
"CONFIG": {
|
||||||
|
"TITLE": "OIDC configuration ändern"
|
||||||
|
},
|
||||||
"DELETE": {
|
"DELETE": {
|
||||||
"TITLE": "App löschen",
|
"TITLE": "App löschen",
|
||||||
"DESCRIPTION": "Wollen Sie diese App wirklich löschen?"
|
"DESCRIPTION": "Wollen Sie diese App wirklich löschen?"
|
||||||
|
@@ -35,7 +35,7 @@
|
|||||||
},
|
},
|
||||||
"SHORTCUTS": {
|
"SHORTCUTS": {
|
||||||
"SHORTCUTS": "Shortcuts",
|
"SHORTCUTS": "Shortcuts",
|
||||||
"SETTINGS": "Organization Settings",
|
"SETTINGS": "Available shortcuts",
|
||||||
"PROJECTS": "Projects",
|
"PROJECTS": "Projects",
|
||||||
"REORDER": "Hold and drag the tile to move it",
|
"REORDER": "Hold and drag the tile to move it",
|
||||||
"ADD": "Hold and drag a tile to add"
|
"ADD": "Hold and drag a tile to add"
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
"TEXT": "Here you can switch between your user accounts and manage your sessions and profile."
|
"TEXT": "Here you can switch between your user accounts and manage your sessions and profile."
|
||||||
},
|
},
|
||||||
"NAV": {
|
"NAV": {
|
||||||
"TEXT": "This navigation changes based on the breadcrumbs above."
|
"TEXT": "This navigation changes based on your selected oranization above or your instance"
|
||||||
},
|
},
|
||||||
"CONTEXTCHANGED": {
|
"CONTEXTCHANGED": {
|
||||||
"TEXT": "Attention! The organization context has changed."
|
"TEXT": "Attention! The organization context has changed."
|
||||||
@@ -818,6 +818,7 @@
|
|||||||
"LOCKOUT": "Lockout",
|
"LOCKOUT": "Lockout",
|
||||||
"COMPLEXITY": "Password complexity",
|
"COMPLEXITY": "Password complexity",
|
||||||
"NOTIFICATIONS": "Notification providers and SMTP",
|
"NOTIFICATIONS": "Notification providers and SMTP",
|
||||||
|
"NOTIFICATIONS_DESC": "SMTP and SMS Settings",
|
||||||
"MESSAGETEXTS": "Message Texts",
|
"MESSAGETEXTS": "Message Texts",
|
||||||
"IDP": "Identity Providers",
|
"IDP": "Identity Providers",
|
||||||
"DOMAIN": "Domain settings",
|
"DOMAIN": "Domain settings",
|
||||||
@@ -1181,11 +1182,11 @@
|
|||||||
"DESC": "As soon as the user is identified, the branding of the organization of the identified user will be shown, before the system default is shown."
|
"DESC": "As soon as the user is identified, the branding of the organization of the identified user will be shown, before the system default is shown."
|
||||||
},
|
},
|
||||||
"1": {
|
"1": {
|
||||||
"TITLE": "Enforce project resource owner Policy",
|
"TITLE": "Use project setting",
|
||||||
"DESC": "The branding of the organization which owns the project will be shown"
|
"DESC": "The branding of the organization which owns the project will be shown"
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
"TITLE": "Allow Login User resource owner policy",
|
"TITLE": "Use User Organization setting",
|
||||||
"DESC": "The branding of the organization of the project will be shown, but as soon as the user is identified, the setting of the organization of the identified user, will be shown."
|
"DESC": "The branding of the organization of the project will be shown, but as soon as the user is identified, the setting of the organization of the identified user, will be shown."
|
||||||
},
|
},
|
||||||
"DIALOG": {
|
"DIALOG": {
|
||||||
@@ -1549,6 +1550,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DIALOG": {
|
"DIALOG": {
|
||||||
|
"CONFIG": {
|
||||||
|
"TITLE": "Change OIDC Configuration"
|
||||||
|
},
|
||||||
"DELETE": {
|
"DELETE": {
|
||||||
"TITLE": "Delete App",
|
"TITLE": "Delete App",
|
||||||
"DESCRIPTION": "Do you really want to delete this application?"
|
"DESCRIPTION": "Do you really want to delete this application?"
|
||||||
|
@@ -34,8 +34,8 @@
|
|||||||
"DESCRIPTION": "Iniziare rapidamente con ZITADEL."
|
"DESCRIPTION": "Iniziare rapidamente con ZITADEL."
|
||||||
},
|
},
|
||||||
"SHORTCUTS": {
|
"SHORTCUTS": {
|
||||||
"SHORTCUTS": "Shortcuts",
|
"SHORTCUTS": "Scorciatoie",
|
||||||
"SETTINGS": "Impostazioni dell' organizazzione",
|
"SETTINGS": "Scorciatoie disponibili",
|
||||||
"PROJECTS": "Progetti",
|
"PROJECTS": "Progetti",
|
||||||
"REORDER": "Per spostare, tieni premuto e trascina il riquadro",
|
"REORDER": "Per spostare, tieni premuto e trascina il riquadro",
|
||||||
"ADD": "Per aggiungere, tieni premuto e trascina il riquadro"
|
"ADD": "Per aggiungere, tieni premuto e trascina il riquadro"
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
"TEXT": "Qui puoi passare da un account utente all'altro e gestire le sessioni e il profilo."
|
"TEXT": "Qui puoi passare da un account utente all'altro e gestire le sessioni e il profilo."
|
||||||
},
|
},
|
||||||
"NAV": {
|
"NAV": {
|
||||||
"TEXT": "Questa navigazione cambia in base ai breadcrumb sopra."
|
"TEXT": "Questa navigazione cambia in base all' organizzazione impostata sopra e la tua istanza."
|
||||||
},
|
},
|
||||||
"CONTEXTCHANGED": {
|
"CONTEXTCHANGED": {
|
||||||
"TEXT": "Attenzione! L'organizzazione è appena stata cambiata."
|
"TEXT": "Attenzione! L'organizzazione è appena stata cambiata."
|
||||||
@@ -818,6 +818,7 @@
|
|||||||
"LOCKOUT": "Meccanismi di bloccaggio",
|
"LOCKOUT": "Meccanismi di bloccaggio",
|
||||||
"COMPLEXITY": "complessità della password",
|
"COMPLEXITY": "complessità della password",
|
||||||
"NOTIFICATIONS": "Notifiche",
|
"NOTIFICATIONS": "Notifiche",
|
||||||
|
"NOTIFICATIONS_DESC": "Impostazioni SMTP e SMS",
|
||||||
"MESSAGETEXTS": "Testi di notifica",
|
"MESSAGETEXTS": "Testi di notifica",
|
||||||
"IDP": "Identity Providers",
|
"IDP": "Identity Providers",
|
||||||
"DOMAIN": "Impostazioni del dominio",
|
"DOMAIN": "Impostazioni del dominio",
|
||||||
@@ -1181,11 +1182,11 @@
|
|||||||
"DESC": "Non appena l'utente viene identificato, viene mostrata l'impostazione Branding dell'organizzazione, prima che venga mostrato il default del sistema."
|
"DESC": "Non appena l'utente viene identificato, viene mostrata l'impostazione Branding dell'organizzazione, prima che venga mostrato il default del sistema."
|
||||||
},
|
},
|
||||||
"1": {
|
"1": {
|
||||||
"TITLE": "Applica l'impostazione Branding delle risorse del progetto",
|
"TITLE": "Applica l'impostazione del progetto",
|
||||||
"DESC": "Branding dell'organizzazione del progetto sar\u00e0 mostrata"
|
"DESC": "Branding dell'organizzazione del progetto sar\u00e0 mostrata"
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
"TITLE": "Consentire l'accesso all'impostazione Branding dell'utente",
|
"TITLE": "Applica l'impostazione dell' organizzazione dell' utente",
|
||||||
"DESC": "Verr\u00e0 mostrata l'impostazione Branding dell'organizzazione del progetto, ma non appena l'utente viene identificato, verr\u00e0 mostrata l'impostazione dell'organizzazione dell'utente identificato."
|
"DESC": "Verr\u00e0 mostrata l'impostazione Branding dell'organizzazione del progetto, ma non appena l'utente viene identificato, verr\u00e0 mostrata l'impostazione dell'organizzazione dell'utente identificato."
|
||||||
},
|
},
|
||||||
"DIALOG": {
|
"DIALOG": {
|
||||||
@@ -1549,6 +1550,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DIALOG": {
|
"DIALOG": {
|
||||||
|
"CONFIG": {
|
||||||
|
"TITLE": "Configurazione OIDC"
|
||||||
|
},
|
||||||
"DELETE": {
|
"DELETE": {
|
||||||
"TITLE": "Rimuovere App",
|
"TITLE": "Rimuovere App",
|
||||||
"DESCRIPTION": "Vuoi davvero rimuovere questa applicazione?"
|
"DESCRIPTION": "Vuoi davvero rimuovere questa applicazione?"
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
@import 'src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component';
|
@import 'src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component';
|
||||||
@import 'src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component';
|
@import 'src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component';
|
||||||
@import 'src/app/pages/projects/apps/app-detail/app-detail.component';
|
@import 'src/app/pages/projects/apps/app-detail/app-detail.component';
|
||||||
|
@import 'src/app/pages/projects/apps/redirect-uris/redirect-uris.component';
|
||||||
@import 'src/app/modules/top-view/top-view.component';
|
@import 'src/app/modules/top-view/top-view.component';
|
||||||
@import 'src/app/pages/projects/projects.component';
|
@import 'src/app/pages/projects/projects.component';
|
||||||
@import 'src/app/modules/edit-text/edit-text.component.scss';
|
@import 'src/app/modules/edit-text/edit-text.component.scss';
|
||||||
@@ -51,6 +52,7 @@
|
|||||||
@import 'src/app/pages/actions/add-action-dialog/add-action-dialog.component';
|
@import 'src/app/pages/actions/add-action-dialog/add-action-dialog.component';
|
||||||
@import 'src/app/modules/project-role-chip/project-role-chip.component';
|
@import 'src/app/modules/project-role-chip/project-role-chip.component';
|
||||||
@import 'src/app/pages/home/home.component.scss';
|
@import 'src/app/pages/home/home.component.scss';
|
||||||
|
@import 'src/app/modules/search-user-autocomplete/search-user-autocomplete.component.scss';
|
||||||
@import 'src/app/modules/policies/login-policy/factor-table/factor-table.component.scss';
|
@import 'src/app/modules/policies/login-policy/factor-table/factor-table.component.scss';
|
||||||
@import 'src/app/modules/info-overlay/info-overlay.component.scss';
|
@import 'src/app/modules/info-overlay/info-overlay.component.scss';
|
||||||
@import './styles/codemirror.scss';
|
@import './styles/codemirror.scss';
|
||||||
@@ -67,6 +69,7 @@
|
|||||||
@include top-view-theme($theme);
|
@include top-view-theme($theme);
|
||||||
@include info-overlay-theme($theme);
|
@include info-overlay-theme($theme);
|
||||||
@include app-auth-method-radio-theme($theme);
|
@include app-auth-method-radio-theme($theme);
|
||||||
|
@include search-user-autocomplete-theme($theme);
|
||||||
@include project-role-chips-theme($theme);
|
@include project-role-chips-theme($theme);
|
||||||
@include card-theme($theme);
|
@include card-theme($theme);
|
||||||
@include footer-theme($theme);
|
@include footer-theme($theme);
|
||||||
@@ -109,6 +112,7 @@
|
|||||||
@include user-grants-theme($theme);
|
@include user-grants-theme($theme);
|
||||||
@include info-row-theme($theme);
|
@include info-row-theme($theme);
|
||||||
@include action-dialog-theme($theme);
|
@include action-dialog-theme($theme);
|
||||||
|
@include redirect-uris-theme($theme);
|
||||||
@include action-keys-theme($theme);
|
@include action-keys-theme($theme);
|
||||||
@include codemirror-theme($theme);
|
@include codemirror-theme($theme);
|
||||||
@include contact-theme($theme);
|
@include contact-theme($theme);
|
||||||
|
@@ -229,6 +229,9 @@ $caos-light-warn: (
|
|||||||
$caos-dark-theme-text: var(--theme-dark-text);
|
$caos-dark-theme-text: var(--theme-dark-text);
|
||||||
$caos-light-theme-text: var(--theme-light-text);
|
$caos-light-theme-text: var(--theme-light-text);
|
||||||
|
|
||||||
|
$caos-dark-theme-secondary-text: var(--theme-dark-secondary-text);
|
||||||
|
$caos-light-theme-secondary-text: var(--theme-light-secondary-text);
|
||||||
|
|
||||||
$caos-dark-theme-background: (
|
$caos-dark-theme-background: (
|
||||||
status-bar: map_get($caos-dark-background, 300),
|
status-bar: map_get($caos-dark-background, 300),
|
||||||
app-bar: map_get($caos-dark-background, 500),
|
app-bar: map_get($caos-dark-background, 500),
|
||||||
@@ -287,7 +290,7 @@ $caos-light-theme-background: (
|
|||||||
unselected-chip: map_get($caos-light-background, 300),
|
unselected-chip: map_get($caos-light-background, 300),
|
||||||
disabled-list-option: map_get($caos-light-background, 200),
|
disabled-list-option: map_get($caos-light-background, 200),
|
||||||
tooltip: map_get($mat-gray, 700),
|
tooltip: map_get($mat-gray, 700),
|
||||||
infosection: map_get($caos-light-primary, 100),
|
infosection: map_get($caos-light-background, 600),
|
||||||
warninfosection: #ffc1c1,
|
warninfosection: #ffc1c1,
|
||||||
alertinfosection: rgb(251, 191, 36),
|
alertinfosection: rgb(251, 191, 36),
|
||||||
successinfosection: #cbf4c9,
|
successinfosection: #cbf4c9,
|
||||||
@@ -307,7 +310,7 @@ $caos-dark-theme-foreground: (
|
|||||||
disabled-text: $light-disabled-text,
|
disabled-text: $light-disabled-text,
|
||||||
elevation: black,
|
elevation: black,
|
||||||
hint-text: $light-disabled-text,
|
hint-text: $light-disabled-text,
|
||||||
secondary-text: $light-secondary-text,
|
secondary-text: $caos-dark-theme-secondary-text,
|
||||||
placeholder-text: rgba(white, 0.4),
|
placeholder-text: rgba(white, 0.4),
|
||||||
icon: rgba(white, 0.54),
|
icon: rgba(white, 0.54),
|
||||||
icons: rgba(white, 0.54),
|
icons: rgba(white, 0.54),
|
||||||
@@ -332,7 +335,7 @@ $caos-light-theme-foreground: (
|
|||||||
disabled-text: $dark-disabled-text,
|
disabled-text: $dark-disabled-text,
|
||||||
elevation: black,
|
elevation: black,
|
||||||
hint-text: $dark-disabled-text,
|
hint-text: $dark-disabled-text,
|
||||||
secondary-text: $dark-secondary-text,
|
secondary-text: $caos-light-theme-secondary-text,
|
||||||
placeholder-text: rgba(black, 0.3),
|
placeholder-text: rgba(black, 0.3),
|
||||||
icon: rgba(black, 0.54),
|
icon: rgba(black, 0.54),
|
||||||
icons: rgba(black, 0.54),
|
icons: rgba(black, 0.54),
|
||||||
@@ -340,7 +343,7 @@ $caos-light-theme-foreground: (
|
|||||||
slider-min: rgba(black, 0.87),
|
slider-min: rgba(black, 0.87),
|
||||||
slider-off: rgba(black, 0.26),
|
slider-off: rgba(black, 0.26),
|
||||||
slider-off-active: rgba(black, 0.38),
|
slider-off-active: rgba(black, 0.38),
|
||||||
infosection: #4a4a4a,
|
infosection: map-get(map-get($caos-light-background, contrast), 600),
|
||||||
warninfosection: #620e0e,
|
warninfosection: #620e0e,
|
||||||
alertinfosection: rgb(146, 64, 14),
|
alertinfosection: rgb(146, 64, 14),
|
||||||
successinfosection: #0e6245,
|
successinfosection: #0e6245,
|
||||||
@@ -514,7 +517,7 @@ $custom-typography: mat.define-typography-config(
|
|||||||
|
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
||||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
|
||||||
background-color: map-get($background, background);
|
background-color: map-get($background, background);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) !important;
|
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) !important;
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
border: none;
|
border: none;
|
||||||
border: 1px solid if($is-dark-theme, #f9f7f725, #1a191938);
|
border: 1px solid if($is-dark-theme, #f9f7f725, #1a191938);
|
||||||
background-color: if($is-dark-theme, #00000020, #00000005);
|
background-color: if($is-dark-theme, #00000020, #00000004);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
Reference in New Issue
Block a user