fix(console): migrate from tslint to eslint, project delete from table (#2490)

* es lint

* modify tsconfig, auto lint some stuff

* lint

* lint

* lint

* lint

* html ts lint

* lint

* lint, tsconfig

* fix project delete, state table

* eslint config, remove cnslHint directive

* mfa selector, info row fixes

* lint

* fix login policy, granted orgs table state, lint

Co-authored-by: Florian Forster <florian@caos.ch>
This commit is contained in:
Max Peintner 2021-10-22 10:47:06 +02:00 committed by GitHub
parent bdf63800f7
commit b1caef81da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
233 changed files with 7098 additions and 4878 deletions

53
console/.eslintrc.json Normal file
View File

@ -0,0 +1,53 @@
{
"root": true,
"ignorePatterns": [
"projects/**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"tsconfig.json",
"e2e/tsconfig.json"
],
"createDefaultProgram": true
},
"extends": [
"plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/template/process-inline-templates"
],
"rules": {
"@angular-eslint/no-conflicting-lifecycle": "off",
"@angular-eslint/no-host-metadata-property": "off",
"@angular-eslint/component-selector": [
"error",
{
"prefix": "cnsl",
"style": "kebab-case",
"type": "element"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"prefix": "cnsl",
"style": "camelCase",
"type": "attribute"
}
]
}
},
{
"files": [
"*.html"
],
"extends": [
"plugin:@angular-eslint/template/recommended"
],
"rules": {}
}
]
}

View File

@ -84,8 +84,8 @@
"budgets": [
{
"type": "initial",
"maximumWarning": "4mb",
"maximumError": "5mb"
"maximumWarning": "5mb",
"maximumError": "6mb"
},
{
"type": "anyComponentStyle",
@ -102,8 +102,7 @@
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
},
"options": {},
"configurations": {
"production": {
"browserTarget": "console:build:production"
@ -142,15 +141,11 @@
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"builder": "@angular-eslint/builder:lint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**",
"**/proto/generated/**"
"lintFilePatterns": [
"src/**/*.ts",
"src/**/*.html"
]
}
},
@ -174,6 +169,7 @@
},
"defaultProject": "console",
"cli": {
"analytics": "2b4e8e6c-f053-4562-b7a6-00c6c06a6791"
"analytics": "2b4e8e6c-f053-4562-b7a6-00c6c06a6791",
"defaultCollection": "@angular-eslint/schematics"
}
}

View File

@ -6,6 +6,6 @@ export class AppPage {
}
getTitleText() {
return element(by.css('app-root .content span')).getText() as Promise<string>;
return element(by.css('cnsl-root .content span')).getText() as Promise<string>;
}
}

2222
console/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -48,6 +48,14 @@
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-eslint/builder": "12.5.0",
"@angular-eslint/eslint-plugin": "12.5.0",
"@angular-eslint/eslint-plugin-template": "12.5.0",
"@angular-eslint/schematics": "12.5.0",
"@angular-eslint/template-parser": "12.5.0",
"@typescript-eslint/eslint-plugin": "4.28.2",
"@typescript-eslint/parser": "4.28.2",
"eslint": "^7.26.0",
"@angular-devkit/build-angular": "~12.2.8",
"@angular/cli": "~12.2.8",
"@angular/compiler-cli": "~12.2.8",
@ -69,7 +77,6 @@
"stylelint-config-standard": "^22.0.0",
"stylelint-scss": "^3.21.0",
"ts-node": "~10.2.1",
"tslint": "~6.1.3",
"typescript": "^4.2.4"
}
}

View File

@ -1,4 +1,4 @@
<ng-container *ngIf="(authService.user | async) || {} as user">
<ng-container *ngIf="$any(authService.user | async) || {} as user">
<ng-container *ngIf="((['iam.read$','iam.write$'] | hasRole)) as iamuser$">
<mat-toolbar class="root-header">
<button *ngIf="authenticationService.authenticated" aria-label="Toggle sidenav" mat-icon-button
@ -7,7 +7,7 @@
</button>
<ng-container *ngIf="labelpolicy && !labelpolicy?.disableWatermark">
<a class="title" [routerLink]="['/']">
<img class="logo" alt="zitadel logo" *ngIf="componentCssClass == 'dark-theme'; else lighttheme"
<img class="logo" alt="zitadel logo" *ngIf="componentCssClass === 'dark-theme'; else lighttheme"
src="../assets/images/zitadel-logo-solo-light.svg" />
<ng-template #lighttheme>
<img alt="zitadel logo" class="logo" src="../assets/images/zitadel-logo-solo-dark.svg" />
@ -48,7 +48,7 @@
<button class="show-all" mat-menu-item [routerLink]="[ '/org/overview' ]">{{'MENU.SHOWORGS' |
translate}}</button>
<ng-template appHasRole [appHasRole]="['org.create','iam.write']">
<ng-template cnslHasRole [hasRole]="['org.create','iam.write']">
<button mat-menu-item [routerLink]="[ '/org/create' ]">
<mat-icon class="avatar">add</mat-icon>
{{'MENU.NEWORG' | translate}}
@ -60,20 +60,20 @@
<a class="doc-link" href="https://docs.zitadel.ch" mat-stroked-button target="_blank">{{'MENU.DOCUMENTATION'
| translate}}</a>
<div (clickOutside)="closeAccountCard()" class="icon-container">
<app-avatar
<cnsl-avatar
*ngIf="user && (user.human?.profile?.displayName || (user.human?.profile?.firstName && user.human?.profile?.lastName))"
class="avatar dontcloseonclick" (click)="showAccount = !showAccount" [active]="showAccount" [avatarUrl]="user.human?.profile?.avatarUrl || ''" [forColor]="user?.preferredLoginName"
[name]="user.human.profile.displayName ? user.human.profile.displayName : (user.human.profile.firstName + ' '+ user.human.profile.lastName)"
[size]="38">
</app-avatar>
<app-accounts-card @accounts class="a_card mat-elevation-z1" *ngIf="showAccount"
(close)="showAccount = false" [user]="user" [iamuser]="iamuser$ | async">
</app-accounts-card>
</cnsl-avatar>
<cnsl-accounts-card @accounts class="a_card mat-elevation-z1" *ngIf="showAccount"
(closedCard)="showAccount = false" [user]="user" [iamuser]="iamuser$ | async">
</cnsl-accounts-card>
</div>
</mat-toolbar>
<mat-drawer-container class="main-container">
<mat-drawer #drawer class="sidenav" [mode]="(isHandset$ | async) ? 'over' : 'side'"
[opened]="!(isHandset$ | async) && authenticationService.authenticated">
[opened]="(isHandset$ | async) === false && authenticationService.authenticated">
<div class="side-column">
<div class="list">
<a @navitem class="nav-item" [routerLinkActive]="['active']"
@ -92,8 +92,7 @@
</ng-container>
<div *ngIf="org" [@navAnimation]="org">
<ng-template appHasRole
[appHasRole]="['org.read']">
<ng-template cnslHasRole [hasRole]="['org.read']">
<div @navitem class="divider">
<div class="line"></div>
<span>{{org?.name ? org.name : ('MENU.ORGSECTION' | translate)}}</span>
@ -101,7 +100,7 @@
</div>
</ng-template>
<ng-template appHasRole [appHasRole]="['org.read']">
<ng-template cnslHasRole [hasRole]="['org.read']">
<a @navitem matTooltip="{{'MENU.TOOLTIP.ORG' | translate}}" class="nav-item"
[routerLinkActive]="['active']" [routerLink]="[ '/org']">
<i class="icon las la-cog"></i>
@ -109,7 +108,7 @@
</a>
</ng-template>
<ng-template appHasRole [appHasRole]="['project.read(:[0-9]*)?']">
<ng-template cnslHasRole [hasRole]="['project.read(:[0-9]*)?']">
<a @navitem matTooltip="{{'MENU.TOOLTIP.SELFPROJECTS' | translate}}" class="nav-item"
[routerLinkActive]="['active']" [routerLink]="[ '/projects']">
<i class="icon las la-layer-group"></i>
@ -133,7 +132,7 @@
</a>
</ng-template>
<ng-template appHasRole [appHasRole]="['user.read(:[0-9]*)?']">
<ng-template cnslHasRole [hasRole]="['user.read(:[0-9]*)?']">
<a @navitem matTooltip="{{'MENU.TOOLTIP.HUMANUSERS' | translate}}" class="nav-item"
[routerLinkActive]="['active']" [routerLink]="[ '/users/list/humans']"
[routerLinkActiveOptions]="{ exact: true }">
@ -149,7 +148,7 @@
</a>
</ng-template>
<ng-template appHasRole [appHasRole]="['user.grant.read(:[0-9]*)?']">
<ng-template cnslHasRole [hasRole]="['user.grant.read(:[0-9]*)?']">
<a @navitem matTooltip="{{'MENU.TOOLTIP.AUTHZ' | translate}}" class="nav-item"
[routerLinkActive]="['active']" [routerLink]="[ '/grants']"
[routerLinkActiveOptions]="{ exact: true }">

View File

@ -15,7 +15,6 @@ import { accountCard, adminLineAnimation, navAnimations, routeAnimations, toolba
import { TextQueryMethod } from './proto/generated/zitadel/object_pb';
import { Org, OrgNameQuery, OrgQuery } from './proto/generated/zitadel/org_pb';
import { LabelPolicy, PrivacyPolicy } from './proto/generated/zitadel/policy_pb';
import { User } from './proto/generated/zitadel/user_pb';
import { AuthenticationService } from './services/authentication.service';
import { GrpcAuthService } from './services/grpc-auth.service';
import { ManagementService } from './services/mgmt.service';
@ -24,7 +23,7 @@ import { UpdateService } from './services/update.service';
@Component({
selector: 'app-root',
selector: 'cnsl-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
animations: [
@ -48,7 +47,7 @@ export class AppComponent implements OnDestroy {
public showAccount: boolean = false;
public org!: Org.AsObject;
public orgs$: Observable<Org.AsObject[]> = of([]);
public user!: User.AsObject;
// public user!: User.AsObject;
public isDarkTheme: Observable<boolean> = of(true);
public orgLoading$: BehaviorSubject<any> = new BehaviorSubject(false);
@ -350,7 +349,7 @@ export class AppComponent implements OnDestroy {
this.authService.user.subscribe(userprofile => {
if (userprofile) {
this.user = userprofile;
// this.user = userprofile;
const cropped = navigator.language.split('-')[0] ?? 'en';
const fallbackLang = cropped.match(/en|de/) ? cropped : 'en';

View File

@ -1,7 +1,7 @@
import { Directive, EventEmitter, HostListener, Input, Output } from '@angular/core';
@Directive({
selector: '[appCopyToClipboard]',
selector: '[cnslCopyToClipboard]',
})
export class CopyToClipboardDirective {
@Input() valueToCopy: string = '';

View File

@ -3,12 +3,12 @@ import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
@Directive({
selector: '[appHasFeature]',
selector: '[cnslHasFeature]',
})
export class HasFeatureDirective {
private hasView: boolean = false;
@Input() public set appHasFeature(features: string[] | RegExp[]) {
@Input() public set hasFeature(features: string[] | RegExp[]) {
if (features && features.length > 0) {
this.authService.canUseFeature(features).subscribe(isAllowed => {
if (isAllowed && !this.hasView) {

View File

@ -3,12 +3,12 @@ import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
@Directive({
selector: '[appHasRole]',
selector: '[cnslHasRole]',
})
export class HasRoleDirective {
private hasView: boolean = false;
@Input() public set appHasRole(roles: string[] | RegExp[]) {
@Input() public set hasRole(roles: string[] | RegExp[]) {
if (roles && roles.length > 0) {
this.authService.isAllowed(roles).subscribe(isAllowed => {
if (isAllowed && !this.hasView) {

View File

@ -1,7 +1,7 @@
import { Directive, ElementRef, EventEmitter, HostListener, Output } from '@angular/core';
@Directive({
selector: '[appOutsideClick]',
selector: '[cnslOutsideClick]',
})
export class OutsideClickDirective {
constructor(private elementRef: ElementRef) { }

View File

@ -1,7 +1,7 @@
import { Directive, ElementRef, EventEmitter, HostListener, Output } from '@angular/core';
@Directive({
selector: '[appScrollable]',
selector: '[cnslScrollable]',
})
export class ScrollableDirective {
// when using this directive, add overflow-y scroll to css

View File

@ -1,22 +1,22 @@
<div class="card" appOutsideClick (clickOutside)="closeCard($event)">
<app-avatar
<div class="card" cnslOutsideClick (clickOutside)="closeCard($event)">
<cnsl-avatar
*ngIf="user.human?.profile && (user.human?.profile?.displayName || (user.human?.profile?.firstName && user.human?.profile?.lastName))"
class="avatar" [forColor]="user.preferredLoginName" [avatarUrl]="user.human?.profile?.avatarUrl || ''"
[name]="user.human?.profile?.displayName ? user.human?.profile?.displayName : (user.human?.profile?.firstName + ' '+ user.human?.profile?.lastName)"
[name]="(user.human && user.human.profile && user.human.profile.displayName) ? user.human.profile.displayName : (user.human?.profile?.firstName + ' '+ user.human?.profile?.lastName)"
[size]="80">
</app-avatar>
</cnsl-avatar>
<span class="u-name">{{user.human?.profile?.displayName ? user.human?.profile?.displayName : 'A'}}</span>
<span class="u-email">{{user?.preferredLoginName}}</span>
<span class="u-email" *ngIf="user.preferredLoginName">{{user.preferredLoginName}}</span>
<span class="iamuser" *ngIf="iamuser">IAM USER</span>
<button color="primary" (click)="editUserProfile()" mat-stroked-button>{{'USER.EDITACCOUNT' | translate}}</button>
<div class="l-accounts">
<mat-progress-bar *ngIf="loadingUsers" color="primary" mode="indeterminate"></mat-progress-bar>
<a class="row" *ngFor="let session of sessions" (click)="selectAccount(session.loginName)">
<app-avatar *ngIf="session && session.displayName" class="small-avatar" [avatarUrl]="session.avatarUrl || ''"
<cnsl-avatar *ngIf="session && session.displayName" class="small-avatar" [avatarUrl]="session.avatarUrl || ''"
[forColor]="session.loginName" [size]="32">
</app-avatar>
</cnsl-avatar>
<div class="col">
<span class="user-title">{{session.displayName ? session.displayName : session.userName}} </span>

View File

@ -6,15 +6,15 @@ import { AuthenticationService } from 'src/app/services/authentication.service';
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
@Component({
selector: 'app-accounts-card',
selector: 'cnsl-accounts-card',
templateUrl: './accounts-card.component.html',
styleUrls: ['./accounts-card.component.scss'],
})
export class AccountsCardComponent implements OnInit {
@Input() public user!: User.AsObject;
@Input() public iamuser: boolean = false;
@Input() public iamuser: boolean | null = false;
@Output() public close: EventEmitter<void> = new EventEmitter();
@Output() public closedCard: EventEmitter<void> = new EventEmitter();
public sessions: Session.AsObject[] = [];
public loadingUsers: boolean = false;
constructor(public authService: AuthenticationService, private router: Router, private userService: GrpcAuthService) {
@ -37,12 +37,12 @@ export class AccountsCardComponent implements OnInit {
public editUserProfile(): void {
this.router.navigate(['users/me']);
this.close.emit();
this.closedCard.emit();
}
public closeCard(element: HTMLElement): void {
if (!element.classList.contains('dontcloseonclick')) {
this.close.emit();
this.closedCard.emit();
}
}
@ -69,6 +69,6 @@ export class AccountsCardComponent implements OnInit {
public logout(): void {
this.authService.signout();
this.close.emit();
this.closedCard.emit();
}
}

View File

@ -27,7 +27,7 @@
{{'ACTIONS.CANCEL' | translate}}
</button>
<button color="primary" mat-raised-button class="ok-button" [disabled]="type == undefined || dateControl.invalid"
<button color="primary" mat-raised-button class="ok-button" [disabled]="type === undefined || dateControl.invalid"
(click)="closeDialogWithSuccess()">
{{'ACTIONS.ADD' | translate}}
</button>

View File

@ -9,7 +9,7 @@ export enum AddKeyDialogType {
}
@Component({
selector: 'app-add-key-dialog',
selector: 'cnsl-add-key-dialog',
templateUrl: './add-key-dialog.component.html',
styleUrls: ['./add-key-dialog.component.scss'],
})

View File

@ -10,7 +10,7 @@
<cnsl-label>{{ 'MEMBER.CREATIONTYPE' | translate }}</cnsl-label>
<mat-select [(ngModel)]="creationType" (selectionChange)="loadRoles()">
<mat-option *ngFor="let type of creationTypes" [value]="type.type"
[disabled]="(type.disabled$ | async) == false">
[disabled]="(type.disabled$ | async) === false">
{{ 'MEMBER.CREATIONTYPES.'+type.type | translate}}
</mat-option>
</mat-select>
@ -19,16 +19,16 @@
<ng-container
*ngIf="creationType === CreationType.PROJECT_OWNED || creationType === CreationType.PROJECT_GRANTED">
<p>{{'PROJECT.GRANT.CREATE.SEL_PROJECT' | translate}}</p>
<app-search-project-autocomplete class="block" singleOutput="true"
<cnsl-search-project-autocomplete class="block" [singleOutput]="true"
(selectionChanged)="selectProject($event)"
[autocompleteType]="creationType === CreationType.PROJECT_OWNED ? ProjectAutocompleteType.PROJECT_OWNED : creationType === CreationType.PROJECT_GRANTED ? ProjectAutocompleteType.PROJECT_GRANTED : undefined">
</app-search-project-autocomplete>
</cnsl-search-project-autocomplete>
</ng-container>
</ng-container>
<!-- if no context end -->
<app-search-user-autocomplete [users]="preselectedUsers" (selectionChanged)="users = $event">
</app-search-user-autocomplete>
<cnsl-search-user-autocomplete [users]="preselectedUsers" (selectionChanged)="users = $any($event)">
</cnsl-search-user-autocomplete>
<cnsl-form-field class="full-width" appearance="outline"
*ngIf="creationType === CreationType.PROJECT_OWNED || creationType === CreationType.PROJECT_GRANTED || creationType === CreationType.IAM">
@ -41,8 +41,8 @@
</cnsl-form-field>
<ng-container *ngIf="creationType === CreationType.ORG">
<app-org-member-roles-autocomplete (selectionChanged)="setOrgMemberRoles($event)">
</app-org-member-roles-autocomplete>
<cnsl-org-member-roles-autocomplete (selectionChanged)="setOrgMemberRoles($event)">
</cnsl-org-member-roles-autocomplete>
</ng-container>
</div>
@ -51,7 +51,7 @@
{{'ACTIONS.CANCEL' | translate}}
</button>
<button [disabled]="users.length == 0 || roles.length == 0" color="primary" mat-raised-button class="ok-button"
<button [disabled]="users.length === 0 || roles.length === 0" color="primary" mat-raised-button class="ok-button"
(click)="closeDialogWithSuccess()">
{{'ACTIONS.ADD' | translate}}
</button>

View File

@ -17,7 +17,7 @@ export enum CreationType {
IAM = 3,
}
@Component({
selector: 'app-member-create-dialog',
selector: 'cnsl-member-create-dialog',
templateUrl: './member-create-dialog.component.html',
styleUrls: ['./member-create-dialog.component.scss'],
})

View File

@ -1,5 +1,5 @@
<div class="cnsl-app-card" [ngClass]="{'web': type == OIDCAppType.OIDC_APP_TYPE_WEB,
'useragent': type == OIDCAppType.OIDC_APP_TYPE_USER_AGENT,
'native': type == OIDCAppType.OIDC_APP_TYPE_NATIVE, 'api': isApiApp}">
<div class="cnsl-app-card" [ngClass]="{'web': type === OIDCAppType.OIDC_APP_TYPE_WEB,
'useragent': type === OIDCAppType.OIDC_APP_TYPE_USER_AGENT,
'native': type === OIDCAppType.OIDC_APP_TYPE_NATIVE, 'api': isApiApp}">
<ng-content></ng-content>
</div>

View File

@ -8,7 +8,7 @@ import { OIDCAppType } from 'src/app/proto/generated/zitadel/app_pb';
})
export class AppCardComponent {
@Input() public outline: boolean = false;
@Input() public type!: OIDCAppType;
@Input() public type: OIDCAppType | undefined = undefined;
@Input() public isApiApp: boolean = false;
public OIDCAppType: any = OIDCAppType;
}

View File

@ -2,7 +2,7 @@
<ng-container *ngFor="let method of authMethods; index as i">
<input type="radio" [disabled]="method.disabled" (change)="emitChange()" [value]="method.key" [id]="method.key"
[(ngModel)]="selected" />
<label class="cnsl-radio-button" [ngClass]="{'first': i == 0, 'last': i == authMethods.length - 1}"
<label class="cnsl-radio-button" [ngClass]="{'first': i === 0, 'last': i === authMethods.length - 1}"
[for]="method.key">
<div class="recommended" [ngClass]="{'not': method.notRecommended}"
*ngIf="method.recommended || method.notRecommended">
@ -11,25 +11,25 @@
<div class="cnsl-radio-header" [ngStyle]="{'background': method.background}">
<span>{{method.prefix}}</span>
<div class="current" *ngIf="current == method.key">{{'APP.OIDC.CURRENT' | translate}}</div>
<div class="current" *ngIf="current === method.key">{{'APP.OIDC.CURRENT' | translate}}</div>
</div>
<p>{{method.titleI18nKey | translate}}</p>
<p class="type-desc">{{method.descI18nKey | translate}}</p>
<span class="fill-space"></span>
<div class="app-specs">
<div class="row" *ngIf="isOIDC && method && method.responseType != undefined">
<div class="row" *ngIf="isOIDC && method && method.responseType !== undefined">
<span>{{'APP.OIDC.RESPONSETYPE' | translate}}</span>
<span>{{('APP.OIDC.RESPONSE.'+method.responseType.toString()) | translate}}</span>
</div>
<div class="row" *ngIf="isOIDC && method.grantType != undefined">
<div class="row" *ngIf="isOIDC && method.grantType !== undefined">
<span>{{'APP.GRANT' | translate}}</span>
<span>{{('APP.OIDC.GRANT.'+method.grantType.toString()) | translate}}</span>
</div>
<div class="row" *ngIf="isOIDC && method.authMethod != undefined">
<div class="row" *ngIf="isOIDC && method.authMethod !== undefined">
<span>{{'APP.AUTHMETHOD' | translate}}</span>
<span>{{('APP.OIDC.AUTHMETHOD.'+method.authMethod.toString()) | translate}}</span>
</div>
<div class="row" *ngIf="!isOIDC && method.apiAuthMethod != undefined">
<div class="row" *ngIf="!isOIDC && method.apiAuthMethod !== undefined">
<span>{{'APP.AUTHMETHOD' | translate}}</span>
<span>{{('APP.API.AUTHMETHOD.'+method.apiAuthMethod.toString()) | translate}}</span>
</div>

View File

@ -22,7 +22,7 @@ export interface RadioItemAuthType {
}
@Component({
selector: 'app-auth-method-radio',
selector: 'cnsl-auth-method-radio',
templateUrl: './app-auth-method-radio.component.html',
styleUrls: ['./app-auth-method-radio.component.scss'],
})

View File

@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
import { RadioItemAppType, WEB_TYPE } from 'src/app/pages/projects/apps/authtypes';
@Component({
selector: 'app-type-radio',
selector: 'cnsl-type-radio',
templateUrl: './app-type-radio.component.html',
styleUrls: ['./app-type-radio.component.scss'],
})

View File

@ -1,5 +1,5 @@
<div class="avatar-circle dontcloseonclick" matRipple [matRippleColor]="'#ffffff20'" matRippleUnbounded="true"
matRippleCentered="true"
<div class="avatar-circle dontcloseonclick" matRipple [matRippleColor]="'#ffffff20'" [matRippleUnbounded]="true"
[matRippleCentered]="true"
[ngStyle]="{'height': size+'px', 'width': size+'px', 'fontSize': (fontSize-1)+'px', 'background': color}"
[ngClass]="{'active': active}">
<img class="dontcloseonclick" *ngIf="avatarUrl; else creds" [src]="avatarUrl"/>

View File

@ -1,7 +1,7 @@
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-avatar',
selector: 'cnsl-avatar',
templateUrl: './avatar.component.html',
styleUrls: ['./avatar.component.scss'],
})
@ -77,7 +77,7 @@ export class AvatarComponent implements OnInit {
return colors[hash % colors.length];
}
// tslint:disable
/* eslint-disable */
private hashCode(str: string, seed: number = 0): number {
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
for (let i = 0, ch; i < str.length; i++) {
@ -89,5 +89,5 @@ export class AvatarComponent implements OnInit {
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
}
// tslint:enable
/* eslint-enable */
}

View File

@ -2,7 +2,7 @@ import { animate, style, transition, trigger } from '@angular/animations';
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-card',
selector: 'cnsl-card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.scss'],
animations: [

View File

@ -5,17 +5,18 @@
</button>
</div>
<div class="scroll-container" appScrollable (scrollPosition)="scrollHandler($event)">
<div class="scroll-container" cnslScrollable (scrollPosition)="scrollHandler($event)">
<li class="item change-item-back" *ngFor="let hist of data | async; index as histindex">
<span *ngIf="hist.values[0].dates[0]" class="date">{{
hist.values[0]?.dates[0]| timestampToDate | localizedDate: 'dd. MMMM YYYY' }}</span>
<span *ngIf="hist.values[0].dates[0]" class="date">
{{ hist.values[0].dates[0]| timestampToDate | localizedDate: 'dd. MMMM YYYY' }}
</span>
<div class="item" *ngFor="let dayelement of hist.values; index as i">
<div class="row">
<app-avatar matTooltip="{{ dayelement.editorDisplayName }}"
<cnsl-avatar matTooltip="{{ dayelement.editorDisplayName }}"
*ngIf="dayelement.editorDisplayName; else spacer" class="avatar"
[name]="dayelement.editorDisplayName" [size]="32" [forColor]="dayelement?.editorPreferredLoginName"
[name]="dayelement.editorDisplayName" [size]="32" [forColor]="dayelement?.editorPreferredLoginName ?? 'A'"
[avatarUrl]="dayelement.editorAvatarUrl || ''">
</app-avatar>
</cnsl-avatar>
<ng-template #spacer>
<div class="spacer"></div>
</ng-template>

View File

@ -29,6 +29,9 @@ export interface MappedChange {
dates: Timestamp.AsObject[];
editorId: string;
editorName: string;
editorDisplayName: string;
editorAvatarUrl: string;
editorPreferredLoginName: string;
eventTypes: Array<{ key: string; localizedMessage: string; }>;
sequences: number[];
}>;
@ -41,7 +44,7 @@ type ListChanges = ListMyUserChangesResponse.AsObject |
ListAppChangesResponse.AsObject;
@Component({
selector: 'app-changes',
selector: 'cnsl-changes',
templateUrl: './changes.component.html',
styleUrls: ['./changes.component.scss'],
})
@ -253,7 +256,7 @@ export class ChangesComponent implements OnInit, OnDestroy {
}
// Order by ascending property value
// tslint:disable
/* eslint-disable */
valueAscOrder = (a: KeyValue<number, string>, b: KeyValue<number, string>): number => {
return a.value.localeCompare(b.value);
};
@ -262,5 +265,5 @@ export class ChangesComponent implements OnInit, OnDestroy {
keyDescOrder = (a: KeyValue<number, string>, b: KeyValue<number, string>): number => {
return a.key > b.key ? -1 : (b.key > a.key ? 1 : 0);
};
// tslint:enable
/* eslint-enable */
}

View File

@ -1,7 +1,7 @@
<app-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="dataSource.data.length"
<cnsl-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="dataSource.data.length"
[timestamp]="keyResult?.details?.viewTimestamp" [selection]="selection">
<div actions>
<a [disabled]="([('project.app.write:' + projectId), 'project.app.write'] | hasRole | async) == false"
<a [disabled]="([('project.app.write:' + projectId), 'project.app.write'] | hasRole | async) === false"
color="primary" mat-raised-button (click)="openAddKey()">
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
</a>
@ -51,7 +51,7 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let key">
<button
[disabled]="([('project.app.write:' + projectId), 'project.app.write'] | hasRole | async) == false"
[disabled]="([('project.app.write:' + projectId), 'project.app.write'] | hasRole | async) === false"
mat-icon-button color="warn" matTooltip="{{'ACTIONS.DELETE' | translate}}"
(click)="deleteKey(key)">
<i class="las la-trash"></i>
@ -68,4 +68,4 @@
<cnsl-paginator #paginator class="paginator" [timestamp]="keyResult?.details?.viewTimestamp" [length]="keyResult?.details?.totalResult || 0" [pageSize]="10"
[pageSizeOptions]="[5, 10, 20]" (page)="changePage($event)"></cnsl-paginator>
</div>
</app-refresh-table>
</cnsl-refresh-table>

View File

@ -16,7 +16,7 @@ import { ToastService } from 'src/app/services/toast.service';
import { PageEvent, PaginatorComponent } from '../paginator/paginator.component';
@Component({
selector: 'app-client-keys',
selector: 'cnsl-client-keys',
templateUrl: './client-keys.component.html',
styleUrls: ['./client-keys.component.scss'],
})
@ -79,7 +79,7 @@ export class ClientKeysComponent implements OnInit {
width: '400px',
});
dialogRef.afterClosed().subscribe(resp => {
dialogRef.afterClosed().subscribe((resp) => {
if (resp) {
const type: KeyType = resp.type;
@ -96,7 +96,7 @@ export class ClientKeysComponent implements OnInit {
}
if (type) {
return this.mgmtService.addAppKey(
this.mgmtService.addAppKey(
this.projectId,
this.appId,
type,

View File

@ -6,16 +6,15 @@
<div class="people">
<div class="img-list" [@cardAnimation]="totalResult">
<mat-spinner class="spinner" diameter="20" *ngIf="loading"></mat-spinner>
<ng-container *ngIf="totalResult < 10; else compact">
<ng-container *ngFor="let member of membersSubject | async; index as i">
<div @animate (click)="emitShowDetail()" class="avatar-circle"
matTooltip="{{ member.displayName }} | {{member.rolesList?.join(' ')}}" [ngStyle]="{'z-index': 100 - i}">
<app-avatar *ngIf="member && member.displayName && member.firstName && member.lastName; else cog"
class="avatar dontcloseonclick" [avatarUrl]="member.avatarUrl|| ''" [forColor]="member?.userName"
[forColor]="member?.preferredLoginName"
<cnsl-avatar *ngIf="member && member.displayName && member.firstName && member.lastName; else cog"
class="avatar dontcloseonclick" [avatarUrl]="member.avatarUrl|| ''"
[forColor]="member.preferredLoginName ?? 'A'"
[name]="member.displayName ? member.displayName : (member.firstName + ' '+ member.lastName)" [size]="32">
</app-avatar>
</cnsl-avatar>
<ng-template #cog>
<div class="sa-icon">
<i class="las la-user-cog"></i>

View File

@ -4,7 +4,7 @@ import { BehaviorSubject } from 'rxjs';
import { Member } from 'src/app/proto/generated/zitadel/member_pb';
@Component({
selector: 'app-contributors',
selector: 'cnsl-contributors',
templateUrl: './contributors.component.html',
styleUrls: ['./contributors.component.scss'],
animations: [
@ -29,7 +29,7 @@ export class ContributorsComponent {
@Input() description: string = '';
@Input() disabled: boolean = false;
@Input() totalResult: number = 0;
@Input() loading: boolean = false;
@Input() loading: boolean | null = false;
@Input() membersSubject!: BehaviorSubject<Member.AsObject[]>;
@Output() addClicked: EventEmitter<void> = new EventEmitter();
@Output() showDetailClicked: EventEmitter<void> = new EventEmitter();

View File

@ -1,13 +1,12 @@
import { Component, Input } from '@angular/core';
import { RouterLink } from '@angular/router';
@Component({
selector: 'app-detail-layout',
selector: 'cnsl-detail-layout',
templateUrl: './detail-layout.component.html',
styleUrls: ['./detail-layout.component.scss'],
})
export class DetailLayoutComponent {
@Input() backRouterLink!: RouterLink;
@Input() backRouterLink: any = undefined;
@Input() title: string | null = '';
@Input() description: string | null = '';
@Input() maxWidth: boolean = true;

View File

@ -8,24 +8,24 @@
<cnsl-form-field class="formfield" >
<cnsl-label>{{key.key}}</cnsl-label>
<textarea class="text" cnslInput [formControlName]="key.key" [placeholder]="defaultmap[key.key]" [name]="key.key" [ngClass]="{'defaulttext': form.get(key.key)?.value === ''}"></textarea>
<div class="chips" *ngIf="warnText[key.key] == undefined">
<div class="chips" *ngIf="warnText[key.key] === undefined">
<ng-container *ngFor="let chip of chips" >
<div class="chip" appCopyToClipboard [valueToCopy]="chip.value" (copiedValue)="copied = $event" (click)="addChip(key.key, chip.value)">
<div class="chip" cnslCopyToClipboard [valueToCopy]="chip.value" (copiedValue)="copied = $event" (click)="addChip(key.key, chip.value)">
<span class="key">{{chip.key | translate}}</span>
<span class="value">{{chip.value}}</span>
<i *ngIf="copied != chip.value" class="las la-clipboard"></i>
<i *ngIf="copied == chip.value" class="las la-clipboard-check"></i>
<i *ngIf="copied !== chip.value" class="las la-clipboard"></i>
<i *ngIf="copied === chip.value" class="las la-clipboard-check"></i>
</div>
</ng-container>
</div>
</cnsl-form-field>
<div class="actions">
<button matTooltip="{{'ACTIONS.RESETDEFAULT'| translate }}" mat-icon-button [disabled]="form.get(key.key)?.value == defaultmap[key.key] || disabled" (click)="form.get(key.key)?.setValue(defaultmap[key.key])" (mouseenter) = "form.get(key.key)?.value != defaultmap[key.key] && setWarnText(key.key, defaultmap[key.key])" (mouseleave) ="setWarnText(key.key, undefined)"><i class="las la-history"></i></button>
<button matTooltip="{{'ACTIONS.RESETCURRENT'| translate }}" mat-icon-button [disabled]="form.get(key.key)?.value == currentMap[key.key] || disabled" (click)="form.get(key.key)?.setValue(currentMap[key.key])" (mouseenter) = "form.get(key.key)?.value != currentMap[key.key] && setWarnText(key.key, currentMap[key.key])" (mouseleave) ="setWarnText(key.key, undefined)"><i class="las la-undo"></i></button>
<button matTooltip="{{'ACTIONS.RESETDEFAULT'| translate }}" mat-icon-button [disabled]="form.get(key.key)?.value === defaultmap[key.key] || disabled" (click)="form.get(key.key)?.setValue(defaultmap[key.key])" (mouseenter) = "form.get(key.key)?.value !== defaultmap[key.key] && setWarnText(key.key, defaultmap[key.key])" (mouseleave) ="setWarnText(key.key, undefined)"><i class="las la-history"></i></button>
<button matTooltip="{{'ACTIONS.RESETCURRENT'| translate }}" mat-icon-button [disabled]="form.get(key.key)?.value === currentMap[key.key] || disabled" (click)="form.get(key.key)?.setValue(currentMap[key.key])" (mouseenter) = "form.get(key.key)?.value !== currentMap[key.key] && setWarnText(key.key, currentMap[key.key])" (mouseleave) ="setWarnText(key.key, undefined)"><i class="las la-undo"></i></button>
</div>
</div>
</div>
<cnsl-info-section *ngIf="warnText[key.key] !== undefined" class="info" type="WARN">{{'ACTIONS.RESETTO'| translate }} <cite>'{{warnText[key.key]}}'</cite></cnsl-info-section>
<cnsl-info-section *ngIf="warnText[key.key] !== undefined" class="info" [type]="InfoSectionType.WARN">{{'ACTIONS.RESETTO'| translate }} <cite>'{{warnText[key.key]}}'</cite></cnsl-info-section>
</ng-container>
</form>
</div>

View File

@ -3,6 +3,8 @@ import { FormControl, FormGroup } from '@angular/forms';
import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { InfoSectionType } from '../info-section/info-section.component';
@Component({
selector: 'cnsl-edit-text',
templateUrl: './edit-text.component.html',
@ -23,6 +25,7 @@ export class EditTextComponent implements OnInit, OnDestroy {
@Input() public disabled: boolean = true;
public copied: string = '';
public InfoSectionType: any = InfoSectionType;
public ngOnInit(): void {
this.current$.pipe(takeUntil(this.destroy$)).subscribe(value => {

View File

@ -1,4 +1,4 @@
<app-detail-layout [backRouterLink]="[ serviceType === FeatureServiceType.ADMIN ? '/iam/policies' : '/org']"
<cnsl-detail-layout [backRouterLink]="[ serviceType === FeatureServiceType.ADMIN ? '/iam/policies' : '/org']"
[title]="('FEATURES.TITLE' | translate)" [description]="'FEATURES.DESCRIPTION' | translate">
<h2>{{'FEATURES.TIER.TITLE' | translate}}</h2>
@ -17,7 +17,7 @@
<ng-container *ngIf="serviceType === FeatureServiceType.MGMT">
<mat-spinner class="spinner" diameter="20" *ngIf="customerLoading || stripeLoading"></mat-spinner>
<div class="detail" *ngIf="stripeCustomer || stripeCustomer == null">
<div class="detail" *ngIf="stripeCustomer || stripeCustomer === null">
<p class="title">{{'FEATURES.TIER.DETAILS' | translate}}
<a (click)="setCustomer()">{{'ACTIONS.EDIT' | translate}}</a>
</p>
@ -32,7 +32,7 @@
</p>
</div>
<p class="error" *ngIf="(stripeCustomer || stripeCustomer == null) && !customerValid">{{'FEATURES.TIER.CUSTOMERINVALID' | translate}}</p>
<p class="error" *ngIf="(stripeCustomer || stripeCustomer === null) && !customerValid">{{'FEATURES.TIER.CUSTOMERINVALID' | translate}}</p>
<div class="current-tier">
<a color="primary" [disabled]="!org.id || !customerValid || !stripeURL" mat-raised-button [href]="stripeURL" target="_blank"
@ -40,7 +40,7 @@
</div>
</ng-container>
<ng-template appHasRole [appHasRole]="['iam.features.delete']">
<ng-template cnslHasRole [hasRole]="['iam.features.delete']">
<button *ngIf="serviceType === FeatureServiceType.MGMT && !isDefault"
matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="resetFeatures()" mat-stroked-button>
{{'POLICY.RESET' | translate}}
@ -268,12 +268,12 @@
</div>
</div>
<div class="btn-container" *ngIf="(['iam.features.write'] | hasRole | async) == true">
<div class="btn-container" *ngIf="(['iam.features.write'] | hasRole | async) === true">
<button (click)="savePolicy()" color="primary"
type="submit" mat-raised-button>{{ 'ACTIONS.SAVE' | translate
}}</button>
</div>
</app-detail-layout>
</cnsl-detail-layout>
<ng-template #templateRef let-active="active">
<span class="state" [ngClass]="{'active': active, 'inactive': !active}">

View File

@ -26,7 +26,7 @@ export enum FeatureServiceType {
}
@Component({
selector: 'app-features',
selector: 'cnsl-features',
templateUrl: './features.component.html',
styleUrls: ['./features.component.scss'],
})
@ -133,15 +133,16 @@ export class FeaturesComponent implements OnDestroy {
});
}
private async getData(): Promise<GetFeaturesResponse.AsObject | GetOrgFeaturesResponse.AsObject | undefined> {
private async getData(): Promise<GetFeaturesResponse.AsObject | GetOrgFeaturesResponse.AsObject> {
switch (this.serviceType) {
case FeatureServiceType.MGMT:
return this.managementService.getFeatures();
case FeatureServiceType.ADMIN:
if (this.org?.id) {
return this.adminService.getDefaultFeatures();
} else {
return Promise.reject();
}
break;
}
}

View File

@ -17,7 +17,7 @@ function compare(a: Country, b: Country): number {
}
@Component({
selector: 'app-payment-info-dialog',
selector: 'cnsl-payment-info-dialog',
templateUrl: './payment-info-dialog.component.html',
styleUrls: ['./payment-info-dialog.component.scss'],
})

View File

@ -5,7 +5,7 @@ let nextUniqueId = 0;
export const CNSL_ERROR = new InjectionToken<CnslErrorDirective>('CnslError');
@Directive({
selector: '[cnsl-error]',
selector: '[cnslError]',
host: {
'class': 'cnsl-error',
'role': 'alert',

View File

@ -22,7 +22,6 @@ import { startWith, takeUntil } from 'rxjs/operators';
import { cnslFormFieldAnimations } from './animations';
import { CNSL_ERROR, CnslErrorDirective } from './error.directive';
import { _CNSL_HINT, CnslHintDirective } from './hint.directive';
export const CNSL_FORM_FIELD = new InjectionToken<CnslFormFieldComponent>('CnslFormFieldComponent');
@ -74,7 +73,6 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
_subscriptAnimationState: string = '';
@ContentChildren(CNSL_ERROR as any, { descendants: true }) _errorChildren!: QueryList<CnslErrorDirective>;
@ContentChildren(_CNSL_HINT, { descendants: true }) _hintChildren!: QueryList<CnslHintDirective>;
@HostListener('blur', ['false'])
_focusChanged(isFocused: boolean): void {

View File

@ -6,13 +6,11 @@ import { LabelModule } from 'src/app/modules/label/label.module';
import { LabelComponent } from '../label/label.component';
import { CnslErrorDirective } from './error.directive';
import { CnslFormFieldComponent } from './form-field.component';
import { CnslHintDirective } from './hint.directive';
@NgModule({
declarations: [
CnslFormFieldComponent,
CnslErrorDirective,
CnslHintDirective,
],
imports: [
CommonModule,
@ -23,7 +21,6 @@ import { CnslHintDirective } from './hint.directive';
CnslFormFieldComponent,
LabelComponent,
CnslErrorDirective,
CnslHintDirective,
],
})
export class FormFieldModule { }

View File

@ -1,33 +0,0 @@
import { Directive, InjectionToken, Input } from '@angular/core';
let nextUniqueId = 0;
/**
* Injection token that can be used to reference instances of `MatHint`. It serves as
* alternative token to the actual `MatHint` class which could cause unnecessary
* retention of the class and its directive metadata.
*
* *Note*: This is not part of the public API as the MDC-based form-field will not
* need a lightweight token for `MatHint` and we want to reduce breaking changes.
*/
export const _CNSL_HINT = new InjectionToken<CnslHintDirective>('CnslHintDirective');
/** Hint text to be shown underneath the form field control. */
@Directive({
selector: 'cnsl-hint',
host: {
'class': 'cnsl-hint',
'[class.cnsl-form-field-hint-end]': 'align === "end"',
'[attr.id]': 'id',
// Remove align attribute to prevent it from interfering with layout.
'[attr.align]': 'null',
},
providers: [{ provide: _CNSL_HINT, useExisting: CnslHintDirective }],
})
export class CnslHintDirective {
/** Whether to align the hint label at the start or end of the line. */
@Input() align: 'start' | 'end' = 'start';
/** Unique ID for the hint. Used for the aria-describedby on the form field control. */
@Input() id: string = `mat-hint-${nextUniqueId++}`;
}

View File

@ -17,7 +17,7 @@ import { PolicyComponentServiceType } from '../policies/policy-component-types.e
import { JWT, OIDC, RadioItemIdpType } from './idptypes';
@Component({
selector: 'app-idp-create',
selector: 'cnsl-idp-create',
templateUrl: './idp-create.component.html',
styleUrls: ['./idp-create.component.scss'],
})

View File

@ -1,4 +1,4 @@
<app-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="dataSource.data.length"
<cnsl-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="dataSource.data.length"
[emitRefreshOnPreviousRoutes]="['/iam/idp/create']" [timestamp]="idpResult?.details?.viewTimestamp"
[selection]="selection">
<div actions>
@ -23,15 +23,15 @@
<mat-checkbox color="primary" (change)="$event ? masterToggle() : null"
[checked]="selection.hasValue() && isAllSelected()"
[indeterminate]="selection.hasValue() && !isAllSelected()"
[disabled]="serviceType==PolicyComponentServiceType.MGMT">
[disabled]="serviceType === PolicyComponentServiceType.MGMT">
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let idp">
<mat-checkbox color="primary" (click)="$event.stopPropagation()" class="chbox"
[disabled]="serviceType==PolicyComponentServiceType.MGMT && idp?.owner == IDPOwnerType.IDP_OWNER_TYPE_SYSTEM"
[disabled]="serviceType === PolicyComponentServiceType.MGMT && idp?.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM"
(change)="$event ? selection.toggle(idp) : null" [checked]="selection.isSelected(idp)">
<img src="../../../assets/images/google.png"
*ngIf="idp.stylingType == IDPSTYLINGTYPE.IDPSTYLINGTYPE_GOOGLE" alt="google" />
*ngIf="idp.stylingType === IDPSTYLINGTYPE.IDPSTYLINGTYPE_GOOGLE" alt="google" />
</mat-checkbox>
</td>
</ng-container>
@ -91,7 +91,7 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let idp">
<button
[disabled]="serviceType==PolicyComponentServiceType.MGMT && idp?.providerType == IDPOwnerType.IDP_OWNER_TYPE_ORG"
[disabled]="serviceType === PolicyComponentServiceType.MGMT && idp?.providerType === IDPOwnerType.IDP_OWNER_TYPE_ORG"
mat-icon-button color="warn" matTooltip="{{'ACTIONS.REMOVE' | translate}}"
(click)="removeIdp(idp)">
<i class="las la-trash"></i>
@ -107,4 +107,4 @@
</div>
<cnsl-paginator #paginator class="paginator" [timestamp]="idpResult?.details?.viewTimestamp" [length]="idpResult?.details?.totalResult || 0" [pageSize]="10"
[pageSizeOptions]="[5, 10, 20]" (page)="changePage($event)"></cnsl-paginator>
</app-refresh-table>
</cnsl-refresh-table>

View File

@ -17,7 +17,7 @@ import { PolicyComponentServiceType } from '../policies/policy-component-types.e
import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
@Component({
selector: 'app-idp-table',
selector: 'cnsl-idp-table',
templateUrl: './idp-table.component.html',
styleUrls: ['./idp-table.component.scss'],
})

View File

@ -1,4 +1,4 @@
<app-detail-layout [backRouterLink]="backroutes" [title]="idp?.name"
<cnsl-detail-layout [backRouterLink]="backroutes" [title]="'IDP.DETAIL.TITLE' | translate"
[description]="'IDP.DETAIL.DESCRIPTION' | translate">
<div *ngIf="canWrite | async" actions>
<button class="actions-trigger" mat-raised-button color="primary" [matMenuTriggerFor]="idpactions">
@ -7,17 +7,15 @@
</button>
<mat-menu #idpactions="matMenu" xPosition="before">
<button mat-menu-item
*ngIf="idp?.state !== IDPState.IDP_STATE_INACTIVE"
<button mat-menu-item *ngIf="idp?.state !== IDPState.IDP_STATE_INACTIVE"
(click)="changeState(IDPState.IDP_STATE_INACTIVE)">
{{'ACTIONS.DEACTIVATE' | translate}}
</button>
<button mat-menu-item *ngIf="idp?.state == IDPState.IDP_STATE_INACTIVE"
<button mat-menu-item *ngIf="idp?.state === IDPState.IDP_STATE_INACTIVE"
(click)="changeState(IDPState.IDP_STATE_ACTIVE)">
{{'ACTIONS.REACTIVATE' | translate}}
</button>
<button mat-menu-item matTooltip="{{'IDP.DELETE' | translate}}"
(click)="deleteIdp()">
<button mat-menu-item matTooltip="{{'IDP.DELETE' | translate}}" (click)="deleteIdp()">
<span [style.color]="'var(--warn)'">{{'IDP.DELETE_TITLE' | translate}}</span>
</button>
</mat-menu>
@ -55,8 +53,8 @@
</ng-container>
<div class="btn-wrapper">
<button color="primary" mat-raised-button class="continue-button" [disabled]="idpForm.invalid || (canWrite | async) === false"
type="submit">
<button color="primary" mat-raised-button class="continue-button"
[disabled]="idpForm.invalid || (canWrite | async) === false" type="submit">
{{ 'ACTIONS.SAVE' | translate }}
</button>
</div>
@ -89,18 +87,17 @@
<cnsl-form-field appearance="outline" class="formfield">
<cnsl-label>{{ 'IDP.SCOPESLIST' | translate }}</cnsl-label>
<input cnslInput [matChipInputFor]="chipScopesList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addScope($event)">
<input cnslInput [matChipInputFor]="chipScopesList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true" (matChipInputTokenEnd)="addScope($event)">
</cnsl-form-field>
<button (click)="addScope($event)" mat-icon-button>
<button (click)="addScope($any($event))" mat-icon-button>
<mat-icon>add</mat-icon>
</button>
</div>
<cnsl-form-field appearance="outline" class="formfield fullwidth">
<mat-chip-list class="chip-list" #chipScopesList aria-label="scope selection">
<mat-chip class="chip" *ngFor="let scope of scopesList?.value" selectable="false"
removable (removed)="removeScope(scope)" [disabled]="(canWrite | async) === false">
<mat-chip class="chip" *ngFor="let scope of scopesList?.value" selectable="false" removable
(removed)="removeScope(scope)" [disabled]="(canWrite | async) === false">
{{scope}} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
@ -173,4 +170,4 @@
</ng-container>
</div>
</app-detail-layout>
</cnsl-detail-layout>

View File

@ -27,7 +27,7 @@ import { PolicyComponentServiceType } from '../policies/policy-component-types.e
import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
@Component({
selector: 'app-idp',
selector: 'cnsl-idp',
templateUrl: './idp.component.html',
styleUrls: ['./idp.component.scss'],
})

View File

@ -2,26 +2,29 @@
<div class="info">
<p class="title">{{ 'USER.PAGES.STATE' | translate }}</p>
<p *ngIf="user && user.state !== undefined" class="state"
[ngClass]="{'active': user.state === UserState.USER_STATE_ACTIVE, 'inactive': user.state === UserState.USER_STATE_INACTIVE}">{{'USER.DATA.STATE'+user.state
[ngClass]="{'active': user.state === UserState.USER_STATE_ACTIVE, 'inactive': user.state === UserState.USER_STATE_INACTIVE}">
{{'USER.DATA.STATE'+user.state
| translate}}</p>
</div>
<div class="info">
<p class="title">{{ 'USER.DETAILS.DATECREATED' | translate }}</p>
<p class="desc">{{user?.details?.creationDate | timestampToDate | localizedDate: 'dd. MMMM YYYY, HH:mm' }}</p>
<p *ngIf="user && user.details && user.details.creationDate" class="desc">{{user.details.creationDate |
timestampToDate | localizedDate: 'dd. MMMM YYYY, HH:mm' }}</p>
</div>
<div class="info">
<p class="title">{{ 'USER.DETAILS.DATECHANGED' | translate }}</p>
<p class="desc">{{user?.details?.changeDate | timestampToDate | localizedDate: 'dd. MMMM YYYY, HH:mm' }}</p>
<p *ngIf="user && user.details && user.details.changeDate" class="desc">{{user.details.changeDate | timestampToDate
| localizedDate: 'dd. MMMM YYYY, HH:mm' }}</p>
</div>
<div class="info width">
<p class="title">{{ 'USER.PAGES.LOGINNAMES' | translate }}</p>
<div class="copy-row" *ngFor="let login of user?.loginNamesList">
<button [disabled]="copied == login"
[matTooltip]="(copied != login ? 'ACTIONS.COPY' : 'ACTIONS.COPIED' ) | translate"
appCopyToClipboard [valueToCopy]="login" (copiedValue)="copied = $event">
<button [disabled]="copied === login"
[matTooltip]="(copied !== login ? 'ACTIONS.COPY' : 'ACTIONS.COPIED' ) | translate" cnslCopyToClipboard
[valueToCopy]="login" (copiedValue)="copied = $event">
{{login}}
</button>
</div>
@ -32,34 +35,37 @@
<div class="info">
<p class="title">{{ 'APP.PAGES.STATE' | translate }}</p>
<p *ngIf="app && app.state !== undefined" class="state"
[ngClass]="{'active': app.state === AppState.APP_STATE_ACTIVE, 'inactive': app.state === AppState.APP_STATE_INACTIVE}">{{'APP.PAGES.DETAIL.STATE.'+app.state
[ngClass]="{'active': app.state === AppState.APP_STATE_ACTIVE, 'inactive': app.state === AppState.APP_STATE_INACTIVE}">
{{'APP.PAGES.DETAIL.STATE.'+app.state
| translate}}</p>
</div>
<div class="info">
<p class="title">{{ 'APP.PAGES.DATECREATED' | translate }}</p>
<p class="desc">{{app?.details?.creationDate | timestampToDate | localizedDate: 'dd. MMMM YYYY, HH:mm' }}</p>
<p *ngIf="app && app.details && app.details.creationDate" class="desc">{{app.details.creationDate | timestampToDate
| localizedDate: 'dd. MMMM YYYY, HH:mm' }}</p>
</div>
<div class="info">
<p class="title">{{ 'APP.PAGES.DATECHANGED' | translate }}</p>
<p class="desc">{{app?.details?.changeDate | timestampToDate | localizedDate: 'dd. MMMM YYYY, HH:mm' }}</p>
<p *ngIf="app && app.details && app.details.changeDate" class="desc">{{app.details.changeDate | timestampToDate |
localizedDate: 'dd. MMMM YYYY, HH:mm' }}</p>
</div>
<div class="info">
<p class="title">{{ 'APP.OIDC.INFO.CLIENTID' | translate }}</p>
<div class="copy-row" *ngIf="app?.oidcConfig?.clientId">
<button [disabled]="copied == app.oidcConfig?.clientId"
[matTooltip]="(copied != app.oidcConfig?.clientId ? 'ACTIONS.COPY' : 'ACTIONS.COPIED' ) | translate"
appCopyToClipboard [valueToCopy]="app.oidcConfig?.clientId" (copiedValue)="copied = $event">
<button *ngIf="app.oidcConfig && app.oidcConfig?.clientId" [disabled]="copied === app.oidcConfig?.clientId"
[matTooltip]="(copied !== app.oidcConfig?.clientId ? 'ACTIONS.COPY' : 'ACTIONS.COPIED' ) | translate"
cnslCopyToClipboard [valueToCopy]="app.oidcConfig.clientId" (copiedValue)="copied = $event">
{{app.oidcConfig?.clientId}}
</button>
</div>
<div class="copy-row" *ngIf="app?.apiConfig?.clientId">
<button [disabled]="copied == app.apiConfig?.clientId"
[matTooltip]="(copied != app.apiConfig?.clientId ? 'ACTIONS.COPY' : 'ACTIONS.COPIED' ) | translate"
appCopyToClipboard [valueToCopy]="app.apiConfig?.clientId" (copiedValue)="copied = $event">
<button *ngIf="app && app.apiConfig && app.apiConfig.clientId" [disabled]="copied === app.apiConfig?.clientId"
[matTooltip]="(copied !== app.apiConfig?.clientId ? 'ACTIONS.COPY' : 'ACTIONS.COPIED' ) | translate"
cnslCopyToClipboard [valueToCopy]="app.apiConfig.clientId" (copiedValue)="copied = $event">
{{app.apiConfig?.clientId}}
</button>
</div>
@ -70,10 +76,9 @@
<div class="copy-row" *ngFor="let environmentV of (environmentMap | keyvalue)">
<div *ngIf="environmentV.value" class="environment">
<span class="key">{{environmentV.key}}</span>
<button [disabled]="copied == environmentV.value"
[matTooltip]="(copied != environmentV.value ? 'ACTIONS.COPY' : 'ACTIONS.COPIED' ) | translate"
appCopyToClipboard [valueToCopy]="environmentV.value"
(copiedValue)="copied = environmentV.key">
<button [disabled]="copied === environmentV.value"
[matTooltip]="(copied !== environmentV.value ? 'ACTIONS.COPY' : 'ACTIONS.COPIED' ) | translate"
cnslCopyToClipboard [valueToCopy]="environmentV.value" (copiedValue)="copied = environmentV.key">
{{environmentV.value}}
</button>
</div>
@ -85,9 +90,9 @@
<div class="info width">
<p class="title">{{ 'IDP.ID' | translate }}</p>
<div class="copy-row">
<button [disabled]="copied == idp.id"
[matTooltip]="(copied != idp.id ? 'ACTIONS.COPY' : 'ACTIONS.COPIED' ) | translate"
appCopyToClipboard [valueToCopy]="idp.id" (copiedValue)="copied = $event">
<button [disabled]="copied === idp.id"
[matTooltip]="(copied !== idp.id ? 'ACTIONS.COPY' : 'ACTIONS.COPIED' ) | translate" cnslCopyToClipboard
[valueToCopy]="idp.id" (copiedValue)="copied = $event">
{{idp.id}}
</button>
</div>
@ -95,18 +100,21 @@
<div class="info">
<p class="title">{{ 'IDP.DETAIL.DATECREATED' | translate }}</p>
<p class="desc">{{idp?.details?.creationDate | timestampToDate | localizedDate: 'dd. MMMM YYYY, HH:mm' }}</p>
<p class="desc" *ngIf="idp && idp.details && idp.details.creationDate">{{idp.details.creationDate | timestampToDate
| localizedDate: 'dd. MMMM YYYY, HH:mm' }}</p>
</div>
<div class="info">
<p class="title">{{ 'IDP.DETAIL.DATECHANGED' | translate }}</p>
<p class="desc">{{idp?.details?.changeDate | timestampToDate | localizedDate: 'dd. MMMM YYYY, HH:mm' }}</p>
<p class="desc" *ngIf="idp && idp.details && idp.details.changeDate">{{idp.details.changeDate | timestampToDate |
localizedDate: 'dd. MMMM YYYY, HH:mm' }}</p>
</div>
<div class="info">
<p class="title">{{ 'IDP.STATE' | translate }}</p>
<p *ngIf="idp && idp.state !== undefined" class="state"
[ngClass]="{'active': idp.state === IDPState.IDP_STATE_ACTIVE, 'inactive': idp.state === IDPState.IDP_STATE_INACTIVE}">{{'IDP.STATES.'+idp.state
[ngClass]="{'active': idp.state === IDPState.IDP_STATE_ACTIVE, 'inactive': idp.state === IDPState.IDP_STATE_INACTIVE}">
{{'IDP.STATES.'+idp.state
| translate}}</p>
</div>
</div>

View File

@ -1,6 +1,6 @@
<div class="info-section-row" [ngClass]="{'info': type == 'INFO', 'warn': type == 'WARN'}">
<i *ngIf="type == 'INFO'" class="icon las la-info"></i>
<i *ngIf="type == 'WARN'" class="icon las la-exclamation"></i>
<div class="info-section-row" [ngClass]="{'info': type === 'INFO', 'warn': type === 'WARN'}">
<i *ngIf="type === 'INFO'" class="icon las la-info"></i>
<i *ngIf="type === 'WARN'" class="icon las la-exclamation"></i>
<div class="info-section-content">
<ng-content></ng-content>

View File

@ -1,6 +1,6 @@
import { Component, Input } from '@angular/core';
enum InfoSectionType {
export enum InfoSectionType {
INFO = 'INFO',
SUCCESS = 'SUCCESS',
WARN = 'WARN',
@ -14,5 +14,5 @@ enum InfoSectionType {
export class InfoSectionComponent {
@Input() type: InfoSectionType = InfoSectionType.INFO;
@Input() featureLink: string = '';
@Input() featureLink: string | string[] = '';
}

View File

@ -184,7 +184,7 @@ export class InputDirective extends _MatInputMixinBase implements MatFormFieldCo
* Implemented as part of MatFormFieldControl.
* @docs-private
*/
// tslint:disable-next-line:no-input-rename
// eslint-disable-next-line @angular-eslint/no-input-rename
@Input('aria-describedby') userAriaDescribedBy!: string;
/**
@ -319,10 +319,10 @@ export class InputDirective extends _MatInputMixinBase implements MatFormFieldCo
// In Ivy the `host` bindings will be merged when this class is extended, whereas in
// ViewEngine they're overwritten.
/** Callback for the cases where the focused state of the input changes. */
// tslint:disable:no-host-decorator-in-concrete
/* eslint-disable */
@HostListener('focus', ['true'])
@HostListener('blur', ['false'])
// tslint:enable:no-host-decorator-in-concrete
/* eslint-enable */
_focusChanged(isFocused: boolean): void {
if (isFocused !== this.focused && (!this.readonly || !isFocused)) {
this.focused = isFocused;
@ -333,7 +333,7 @@ export class InputDirective extends _MatInputMixinBase implements MatFormFieldCo
// We have to use a `HostListener` here in order to support both Ivy and ViewEngine.
// In Ivy the `host` bindings will be merged when this class is extended, whereas in
// ViewEngine they're overwritten.
// tslint:disable-next-line:no-host-decorator-in-concrete
// eslint-disable-next-line
@HostListener('input')
_onInput(): void {
// This is a noop function and is used to let Angular know whenever the value changes.
@ -441,7 +441,7 @@ export class InputDirective extends _MatInputMixinBase implements MatFormFieldCo
this.focus();
}
}
// tslint:disable
/* eslint-disable */
static ngAcceptInputType_disabled: BooleanInput;
static ngAcceptInputType_readonly: BooleanInput;
static ngAcceptInputType_required: BooleanInput;
@ -449,5 +449,5 @@ export class InputDirective extends _MatInputMixinBase implements MatFormFieldCo
// Accept `any` to avoid conflicts with other directives on `<input>` that may
// accept different types.
static ngAcceptInputType_value: any;
// tslint:enable
/* eslint-enable */
}

View File

@ -5,7 +5,7 @@
</div>
<div class="row">
<ng-container *ngFor="let link of links">
<ng-template *ngIf="link.withRole" appHasRole [appHasRole]="link.withRole">
<ng-template *ngIf="link.withRole" cnslHasRole [hasRole]="link.withRole">
<div class="step card">
<ng-content select="[icon]"></ng-content>
<h6>{{ link.i18nTitle | translate }}</h6>

View File

@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input } from '@angular/core';
export interface CnslLinks {
@ -7,7 +7,7 @@ export interface CnslLinks {
routerLink?: any;
href?: string;
iconClasses?: string;
withRole?: Array<string | RegExp>;
withRole?: string[] | RegExp[];
}
@Component({
@ -15,11 +15,6 @@ export interface CnslLinks {
templateUrl: './links.component.html',
styleUrls: ['./links.component.scss'],
})
export class LinksComponent implements OnInit {
export class LinksComponent {
@Input() links: Array<CnslLinks> = [];
constructor() { }
ngOnInit(): void {
}
}

View File

@ -1,7 +1,7 @@
<app-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="dataSource.data.length"
<cnsl-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="dataSource.data.length"
[timestamp]="keyResult?.details?.viewTimestamp" [selection]="selection">
<div actions>
<a [disabled]="([('user.write:' + userId), 'user.write'] | hasRole | async) == false" color="primary"
<a [disabled]="([('user.write:' + userId), 'user.write'] | hasRole | async) === false" color="primary"
mat-raised-button (click)="openAddKey()">
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
</a>
@ -50,7 +50,7 @@
<ng-container matColumnDef="actions" stickyEnd>
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let key">
<button [disabled]="([('user.write:' + userId), 'user.write'] | hasRole | async) == false"
<button [disabled]="([('user.write:' + userId), 'user.write'] | hasRole | async) === false"
mat-icon-button color="warn" matTooltip="{{'ACTIONS.DELETE' | translate}}"
(click)="deleteKey(key)">
<i class="las la-trash"></i>
@ -67,4 +67,4 @@
<cnsl-paginator #paginator class="paginator" [timestamp]="keyResult?.details?.viewTimestamp" [length]="keyResult?.details?.totalResult || 0" [pageSize]="10"
[pageSizeOptions]="[5, 10, 20]" (page)="changePage($event)"></cnsl-paginator>
</div>
</app-refresh-table>
</cnsl-refresh-table>

View File

@ -16,7 +16,7 @@ import { ToastService } from 'src/app/services/toast.service';
import { PageEvent, PaginatorComponent } from '../paginator/paginator.component';
@Component({
selector: 'app-machine-keys',
selector: 'cnsl-machine-keys',
templateUrl: './machine-keys.component.html',
styleUrls: ['./machine-keys.component.scss'],
})
@ -95,7 +95,7 @@ export class MachineKeysComponent implements OnInit {
}
if (type) {
return this.mgmtService.addMachineKey(this.userId, type, date).then((response) => {
this.mgmtService.addMachineKey(this.userId, type, date).then((response) => {
if (response) {
setTimeout(() => {
this.refreshPage();

View File

@ -1,4 +1,4 @@
<app-refresh-table *ngIf="dataSource" (refreshed)="changePage()" [dataSize]="dataSource.totalResult"
<cnsl-refresh-table *ngIf="dataSource" (refreshed)="changePage()" [dataSize]="dataSource.totalResult"
[timestamp]="dataSource.viewTimestamp" [selection]="selection" [loading]="dataSource?.loading$ | async">
<ng-container actions *ngIf="selection.hasValue()">
@ -21,9 +21,9 @@
<td class="selection" mat-cell *matCellDef="let row">
<mat-checkbox [disabled]="!canWrite" color="primary" (click)="$event.stopPropagation()"
(change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)">
<app-avatar *ngIf="row?.displayName && row.firstName && row.lastName; else cog" class="avatar"
<cnsl-avatar *ngIf="row?.displayName && row.firstName && row.lastName; else cog" class="avatar"
[name]="row.displayName" [avatarUrl]="row.avatarUrl || ''" [avatarUrl]="row.avatarUrl|| ''" [forColor]="row?.preferredLoginName" [size]="32">
</app-avatar>
</cnsl-avatar>
<ng-template #cog>
<div class="sa-icon">
<i class="las la-user-cog"></i>
@ -94,4 +94,4 @@
<cnsl-paginator *ngIf="dataSource" class="paginator" #paginator [timestamp]="dataSource?.viewTimestamp" [pageSize]="INITIALPAGESIZE"
[length]="dataSource.totalResult" [pageSizeOptions]="[25, 50, 100, 250]" (page)="changePage($event)">
</cnsl-paginator>
</app-refresh-table>
</cnsl-refresh-table>

View File

@ -6,22 +6,25 @@ import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { IamMembersDataSource } from 'src/app/pages/iam/iam-members/iam-members-datasource';
import { OrgMembersDataSource } from 'src/app/pages/orgs/org-members/org-members-datasource';
import {
ProjectGrantMembersDataSource,
} from 'src/app/pages/projects/owned-projects/project-grant-detail/project-grant-members-datasource';
import { Member } from 'src/app/proto/generated/zitadel/member_pb';
import { PageEvent, PaginatorComponent } from '../paginator/paginator.component';
import { ProjectMembersDataSource } from '../project-members/project-members-datasource';
type MemberDatasource = OrgMembersDataSource | ProjectMembersDataSource | IamMembersDataSource;
type MemberDatasource = OrgMembersDataSource | ProjectMembersDataSource | ProjectGrantMembersDataSource | IamMembersDataSource;
@Component({
selector: 'app-members-table',
selector: 'cnsl-members-table',
templateUrl: './members-table.component.html',
styleUrls: ['./members-table.component.scss'],
})
export class MembersTableComponent implements OnInit, OnDestroy {
public INITIALPAGESIZE: number = 25;
@Input() public canDelete: boolean = false;
@Input() public canWrite: boolean = false;
@Input() public canDelete: boolean | null = false;
@Input() public canWrite: boolean | null = false;
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
@ViewChild(MatTable) public table!: MatTable<Member.AsObject>;
@Input() public dataSource!: MemberDatasource;

View File

@ -4,7 +4,7 @@ import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Component({
selector: 'app-meta-layout',
selector: 'cnsl-meta-layout',
templateUrl: './meta-layout.component.html',
styleUrls: ['./meta-layout.component.scss'],
})

View File

@ -2,7 +2,7 @@ import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
@Component({
selector: 'app-name-dialog',
selector: 'cnsl-name-dialog',
templateUrl: './name-dialog.component.html',
styleUrls: ['./name-dialog.component.scss'],
})

View File

@ -14,7 +14,7 @@ export interface PageEvent {
styleUrls: ['./paginator.component.scss'],
})
export class PaginatorComponent {
@Input() public timestamp!: Timestamp.AsObject;
@Input() public timestamp: Timestamp.AsObject | undefined = undefined;
@Input() public length: number = 0;
@Input() public pageSize: number = 10;
@Input() public pageIndex: number = 0;

View File

@ -1,10 +1,10 @@
<div class="validation-col" *ngIf="this.policy">
<div class="val" *ngIf="this.policy.minLength">
<i *ngIf="password?.value?.length == 0; else showSpinner" class="las la-times red"></i>
<i *ngIf="password?.value?.length === 0; else showSpinner" class="las la-times red"></i>
<ng-template #showSpinner>
<div *ngIf="(password?.errors?.minlength || password?.value?.length == 0) as currentError; else trueminlength"
<div *ngIf="(password?.errors?.minlength || password?.value?.length === 0) as currentError; else trueminlength"
class="sp-wrapper">
<mat-progress-spinner class="spinner" diameter="20" [color]="currentError ? 'warn': 'valid'"
mode="determinate" [value]="(password?.value?.length / policy.minLength) * 100">

View File

@ -1,18 +1,13 @@
import { Component, Input, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Component, Input } from '@angular/core';
import { AbstractControl } from '@angular/forms';
import { PasswordComplexityPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
@Component({
selector: 'app-password-complexity-view',
selector: 'cnsl-password-complexity-view',
templateUrl: './password-complexity-view.component.html',
styleUrls: ['./password-complexity-view.component.scss'],
})
export class PasswordComplexityViewComponent implements OnInit {
@Input() public password!: FormControl;
export class PasswordComplexityViewComponent {
@Input() public password: AbstractControl | null = null;
@Input() public policy!: PasswordComplexityPolicy.AsObject;
constructor() { }
ngOnInit(): void {
}
}

View File

@ -4,7 +4,7 @@
<p class="desc"> {{'LOGINPOLICY.ADDIDP.DESCRIPTION' | translate}}</p>
<div mat-dialog-content>
<cnsl-form-field *ngIf="serviceType == PolicyComponentServiceType.MGMT" class="full-width" appearance="outline">
<cnsl-form-field *ngIf="serviceType === PolicyComponentServiceType.MGMT" class="full-width" appearance="outline">
<cnsl-label>{{ 'IDP.TYPE' | translate }}</cnsl-label>
<mat-select [(ngModel)]="idpType" (selectionChange)="loadIdps()">
<mat-option *ngFor="let type of idpTypes" [value]="type">

View File

@ -8,7 +8,7 @@ import { ToastService } from 'src/app/services/toast.service';
import { PolicyComponentServiceType } from '../../../policy-component-types.enum';
@Component({
selector: 'app-add-idp-dialog',
selector: 'cnsl-add-idp-dialog',
templateUrl: './add-idp-dialog.component.html',
styleUrls: ['./add-idp-dialog.component.scss'],
})
@ -23,7 +23,7 @@ export class AddIdpDialogComponent {
];
public idp: IDP.AsObject | undefined = undefined;
public availableIdps: Array<IDP.AsObject[] | IDP.AsObject> | string[] = [];
public availableIdps: IDP.AsObject[] = [];
constructor(
private mgmtService: ManagementService,

View File

@ -1,8 +1,6 @@
<div class="idps">
<div class="idp mat-elevation-z1"
*ngFor="let idp of idps">
<img src="../../../assets/images/google.png"
*ngIf="idp.idpName.toLowerCase() == 'google'" alt="google" />
<div class="idp mat-elevation-z1" *ngFor="let idp of idps">
<img src="../../../assets/images/google.png" *ngIf="idp.idpName.toLowerCase() === 'google'" alt="google" />
<div>
<span class="name">{{idp.idpName}}</span>
<span class="meta-info">{{ 'IDP.TYPES.'+idp.idpType | translate }}</span>
@ -13,8 +11,7 @@
<mat-icon matTooltip="{{'ACTIONS.REMOVE' | translate}}">remove_circle</mat-icon>
</button>
</div>
<button mat-raised-button color="primary" [disabled]="disabled"
class="new-idp" (click)="openDialog()" >
<button mat-raised-button color="primary" [disabled]="disabled" class="new-idp" (click)="openDialog()">
<span>{{'IDP.ADD' | translate}}</span>
<mat-icon class="icon">add</mat-icon>
</button>

View File

@ -1,6 +1,6 @@
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
<cnsl-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
[title]="'POLICY.LOGIN_POLICY.TITLE' | translate"
[description]="(serviceType==PolicyComponentServiceType.MGMT ? 'POLICY.LOGIN_POLICY.DESCRIPTIONCREATEMGMT' : PolicyComponentServiceType.ADMIN ? 'POLICY.LOGIN_POLICY.DESCRIPTIONCREATEADMIN' : '') | translate">
[description]="(serviceType === PolicyComponentServiceType.MGMT ? 'POLICY.LOGIN_POLICY.DESCRIPTIONCREATEMGMT' : PolicyComponentServiceType.ADMIN ? 'POLICY.LOGIN_POLICY.DESCRIPTIONCREATEADMIN' : '') | translate">
<cnsl-info-section *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</cnsl-info-section>
<div class="spinner-wr">
@ -8,63 +8,76 @@
</div>
<ng-container *ngIf="serviceType === PolicyComponentServiceType.MGMT">
<ng-template appHasRole [appHasRole]="['policy.delete']">
<button *ngIf="!isDefault" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['login_policy'] | hasFeature | async) == false" color="primary" matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()"
mat-stroked-button>
<ng-template cnslHasRole [hasRole]="['policy.delete']">
<button *ngIf="!isDefault" color="primary" matTooltip="{{'POLICY.RESET' | translate}}" color="warn"
(click)="removePolicy()" mat-stroked-button>
{{'POLICY.RESET' | translate}}
</button>
</ng-template>
<ng-template appHasRole [appHasRole]="['policy.write']">
<button *ngIf="isDefault" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['login_policy'] | hasFeature | async) == false" color="primary" matTooltip="{{'POLICY.CREATECUSTOM' | translate}}" (click)="savePolicy()"
mat-raised-button>
<ng-template cnslHasRole [hasRole]="['policy.write']">
<button *ngIf="isDefault" color="primary" matTooltip="{{'POLICY.CREATECUSTOM' | translate}}"
(click)="savePolicy()" mat-raised-button>
{{'POLICY.CREATECUSTOM' | translate}}
</button>
</ng-template>
</ng-container>
<app-card title="{{ 'IDP.LIST.ACTIVETITLE' | translate }}"
[expanded]="true">
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['login_policy.idp'] | hasFeature | async) == false" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-card title="{{ 'IDP.LIST.ACTIVETITLE' | translate }}" [expanded]="true">
<cnsl-info-section
*ngIf="serviceType === PolicyComponentServiceType.MGMT && (['login_policy.idp'] | hasFeature | async) === false"
[featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'login_policy.idp'})"></span>
</cnsl-info-section>
<cnsl-login-policy-idps [serviceType]="serviceType" [service]="service" [disabled]="disabled || (serviceType == PolicyComponentServiceType.MGMT && (['login_policy.idp'] | hasFeature | async) == false)"></cnsl-login-policy-idps>
</app-card>
<cnsl-login-policy-idps [serviceType]="serviceType" [service]="service"
[disabled]="disabled || (serviceType === PolicyComponentServiceType.MGMT && (['login_policy.idp'] | hasFeature | async) === false)">
</cnsl-login-policy-idps>
</cnsl-card>
<app-card title="{{ 'MFA.LIST.MULTIFACTORTITLE' | translate }}" description="{{'MFA.LIST.MULTIFACTORDESCRIPTION' | translate}}" [expanded]="false">
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) == false" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-card title="{{ 'MFA.LIST.MULTIFACTORTITLE' | translate }}"
description="{{'MFA.LIST.MULTIFACTORDESCRIPTION' | translate}}" [expanded]="false">
<cnsl-info-section
*ngIf="serviceType === PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) === false"
[featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'login_policy.factors'})"></span>
</cnsl-info-section>
<app-mfa-table [service]="service" [serviceType]="serviceType"
<cnsl-mfa-table [service]="service" [serviceType]="serviceType"
[componentType]="LoginMethodComponentType.MultiFactor"
[disabled]="(([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.policy.write' : serviceType == PolicyComponentServiceType.MGMT ? 'policy.write' : ''] | hasRole | async) == false) || (serviceType == PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) == false)">
</app-mfa-table>
</app-card>
[disabled]="(([serviceType === PolicyComponentServiceType.ADMIN ? 'iam.policy.write' : serviceType === PolicyComponentServiceType.MGMT ? 'policy.write' : ''] | hasRole | async) === false) || (serviceType === PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) === false)">
</cnsl-mfa-table>
</cnsl-card>
<app-card title="{{ 'MFA.LIST.SECONDFACTORTITLE' | translate }}" description="{{'MFA.LIST.SECONDFACTORDESCRIPTION' | translate}}" [expanded]="false">
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) == false" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-card title="{{ 'MFA.LIST.SECONDFACTORTITLE' | translate }}"
description="{{'MFA.LIST.SECONDFACTORDESCRIPTION' | translate}}" [expanded]="false">
<cnsl-info-section
*ngIf="serviceType === PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) === false"
[featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'login_policy.factors'})"></span>
</cnsl-info-section>
<app-mfa-table [service]="service" [serviceType]="serviceType"
<cnsl-mfa-table [service]="service" [serviceType]="serviceType"
[componentType]="LoginMethodComponentType.SecondFactor"
[disabled]="([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.policy.write' : serviceType == PolicyComponentServiceType.MGMT ? 'policy.write' : ''] | hasRole | async) == false || (serviceType == PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) == false)">
</app-mfa-table>
</app-card>
[disabled]="([serviceType === PolicyComponentServiceType.ADMIN ? 'iam.policy.write' : serviceType === PolicyComponentServiceType.MGMT ? 'policy.write' : ''] | hasRole | async) === false || (serviceType === PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) === false)">
</cnsl-mfa-table>
</cnsl-card>
<app-card title="{{ 'POLICY.LOGIN_POLICY.ADVANCED' | translate }}" [expanded]="false">
<cnsl-card title="{{ 'POLICY.LOGIN_POLICY.ADVANCED' | translate }}" [expanded]="false">
<div class="content" *ngIf="loginData">
<div class="row">
<mat-slide-toggle class="toggle" color="primary" [disabled]="disabled || serviceType == PolicyComponentServiceType.MGMT && (['login_policy.username_login'] | hasFeature | async) == false" ngDefaultControl
[(ngModel)]="loginData.allowUsernamePassword">
<mat-slide-toggle class="toggle" color="primary"
[disabled]="disabled || serviceType === PolicyComponentServiceType.MGMT && (['login_policy.username_login'] | hasFeature | async) === false"
ngDefaultControl [(ngModel)]="loginData.allowUsernamePassword">
{{'POLICY.DATA.ALLOWUSERNAMEPASSWORD' | translate}}
</mat-slide-toggle>
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['login_policy.username_login'] | hasFeature | async) == false; else usernameInfo" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-info-section
*ngIf="serviceType === PolicyComponentServiceType.MGMT && (['login_policy.username_login'] | hasFeature | async) === false; else usernameInfo"
[featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'login_policy.username_login'})"></span>
</cnsl-info-section>
@ -75,13 +88,17 @@
</ng-template>
</div>
<div class="row">
<mat-slide-toggle class="toggle" color="primary"
[disabled]="disabled || (serviceType == PolicyComponentServiceType.MGMT && (['login_policy.registration'] | hasFeature | async) == false)"
[disabled]="disabled || (serviceType === PolicyComponentServiceType.MGMT && (['login_policy.registration'] | hasFeature | async) === false)"
ngDefaultControl [(ngModel)]="loginData.allowRegister">
{{'POLICY.DATA.ALLOWREGISTER' | translate}}
</mat-slide-toggle>
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['login_policy.registration'] | hasFeature | async) == false; else regInfo" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-info-section
*ngIf="serviceType === PolicyComponentServiceType.MGMT && (['login_policy.registration'] | hasFeature | async) === false; else regInfo"
[featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'login_policy.registration'})"></span>
</cnsl-info-section>
@ -92,12 +109,15 @@
</ng-template>
</div>
<div class="row">
<mat-slide-toggle class="toggle" color="primary" [disabled]="disabled || serviceType == PolicyComponentServiceType.MGMT && (['login_policy.idp'] | hasFeature | async) == false" ngDefaultControl
[(ngModel)]="loginData.allowExternalIdp">
<mat-slide-toggle class="toggle" color="primary"
[disabled]="disabled || serviceType === PolicyComponentServiceType.MGMT && (['login_policy.idp'] | hasFeature | async) === false"
ngDefaultControl [(ngModel)]="loginData.allowExternalIdp">
{{'POLICY.DATA.ALLOWEXTERNALIDP' | translate}}
</mat-slide-toggle>
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['login_policy.idp'] | hasFeature | async) == false; else idpInfo" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-info-section
*ngIf="serviceType === PolicyComponentServiceType.MGMT && (['login_policy.idp'] | hasFeature | async) === false; else idpInfo"
[featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'login_policy.idp'})"></span>
</cnsl-info-section>
@ -108,12 +128,15 @@
</ng-template>
</div>
<div class="row">
<mat-slide-toggle class="toggle" color="primary" [disabled]="disabled || serviceType == PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) == false" ngDefaultControl
[(ngModel)]="loginData.forceMfa">
<mat-slide-toggle class="toggle" color="primary"
[disabled]="disabled || serviceType === PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) === false"
ngDefaultControl [(ngModel)]="loginData.forceMfa">
{{'POLICY.DATA.FORCEMFA' | translate}}
</mat-slide-toggle>
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) == false; else factorsInfo" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-info-section
*ngIf="serviceType === PolicyComponentServiceType.MGMT && (['login_policy.factors'] | hasFeature | async) === false; else factorsInfo"
[featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'login_policy.factors'})"></span>
</cnsl-info-section>
@ -124,12 +147,16 @@
</ng-template>
</div>
<div class="row">
<mat-slide-toggle class="toggle" color="primary" [disabled]="disabled || serviceType == PolicyComponentServiceType.MGMT && (['login_policy.password_reset'] | hasFeature | async) == false" ngDefaultControl
[(ngModel)]="loginData.hidePasswordReset">
<mat-slide-toggle class="toggle" color="primary"
[disabled]="disabled || serviceType === PolicyComponentServiceType.MGMT && (['login_policy.password_reset'] | hasFeature | async) === false"
ngDefaultControl [(ngModel)]="loginData.hidePasswordReset">
{{'POLICY.DATA.HIDEPASSWORDRESET' | translate}}
</mat-slide-toggle>
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['login_policy.password_reset'] | hasFeature | async) == false; else passwordResetInfo" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-info-section
*ngIf="serviceType === PolicyComponentServiceType.MGMT && (['login_policy.password_reset'] | hasFeature | async) === false; else passwordResetInfo"
[featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'login_policy.password_reset'})"></span>
</cnsl-info-section>
@ -144,34 +171,38 @@
<cnsl-form-field class="form-field" label="Access Code" required="true">
<cnsl-label>{{'LOGINPOLICY.PASSWORDLESS' | translate}}</cnsl-label>
<mat-select [(ngModel)]="loginData.passwordlessType"
[disabled]="disabled || (serviceType == PolicyComponentServiceType.MGMT && (['login_policy.passwordless'] | hasFeature | async) == false)">
[disabled]="disabled || (serviceType === PolicyComponentServiceType.MGMT && (['login_policy.passwordless'] | hasFeature | async) === false)">
<mat-option *ngFor="let pt of passwordlessTypes" [value]="pt">
{{'LOGINPOLICY.PASSWORDLESSTYPE.'+pt | translate}}
</mat-option>
</mat-select>
</cnsl-form-field>
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['login_policy.passwordless'] | hasFeature | async) == false" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-info-section
*ngIf="serviceType === PolicyComponentServiceType.MGMT && (['login_policy.passwordless'] | hasFeature | async) === false"
[featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'login_policy.passwordless'})"></span>
</cnsl-info-section>
</div>
</div>
</app-card>
</cnsl-card>
<button [disabled]="disabled" class="save-button" (click)="savePolicy()" color="primary" type="submit"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
<div class="divider"></div>
<ng-template appHasRole [appHasRole]="['org.idp.read']">
<app-card title="{{ 'IDP.LIST.TITLE' | translate }}" description="{{ 'IDP.LIST.DESCRIPTION' | translate }}"
<ng-template cnslHasRole [hasRole]="['org.idp.read']">
<cnsl-card title="{{ 'IDP.LIST.TITLE' | translate }}" description="{{ 'IDP.LIST.DESCRIPTION' | translate }}"
[expanded]="false">
<app-idp-table [service]="service" [serviceType]="serviceType"
[disabled]="([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.idp.write' : serviceType == PolicyComponentServiceType.MGMT ? 'org.idp.write' : ''] | hasRole | async) == false || ((serviceType == PolicyComponentServiceType.MGMT && (['login_policy.idp'] | hasFeature | async) == false))">
</app-idp-table>
</app-card>
<cnsl-idp-table [service]="service" [serviceType]="serviceType"
[disabled]="([serviceType === PolicyComponentServiceType.ADMIN ? 'iam.idp.write' : serviceType === PolicyComponentServiceType.MGMT ? 'org.idp.write' : ''] | hasRole | async) === false || ((serviceType === PolicyComponentServiceType.MGMT && (['login_policy.idp'] | hasFeature | async) === false))">
</cnsl-idp-table>
</cnsl-card>
</ng-template>
<app-policy-grid class="grid" [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="security"></app-policy-grid>
</app-detail-layout>
<cnsl-policy-grid class="grid" [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="security">
</cnsl-policy-grid>
</cnsl-detail-layout>

View File

@ -16,12 +16,13 @@ import { AdminService } from 'src/app/services/admin.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import { InfoSectionType } from '../../info-section/info-section.component';
import { GridPolicy, LOGIN_POLICY } from '../../policy-grid/policies';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
import { LoginMethodComponentType } from './mfa-table/mfa-table.component';
@Component({
selector: 'app-login-policy',
selector: 'cnsl-login-policy',
templateUrl: './login-policy.component.html',
styleUrls: ['./login-policy.component.scss'],
})
@ -39,6 +40,7 @@ export class LoginPolicyComponent implements OnDestroy {
public disabled: boolean = true;
public currentPolicy: GridPolicy = LOGIN_POLICY;
public InfoSectionType: any = InfoSectionType;
constructor(
private route: ActivatedRoute,
private toast: ToastService,

View File

@ -6,7 +6,7 @@
<cnsl-label>{{'MFA.TYPE' | translate}}</cnsl-label>
<mat-select [(ngModel)]="newMfaType">
<mat-option *ngFor="let mfa of availableMfaTypes" [value]="mfa">
{{(data.componentType == LoginMethodComponentType.SecondFactor ? 'MFA.SECONDFACTORTYPES.':
{{(data.componentType === LoginMethodComponentType.SecondFactor ? 'MFA.SECONDFACTORTYPES.':
LoginMethodComponentType.MultiFactor ? 'MFA.MULTIFACTORTYPES.': '')+mfa | translate}}
</mat-option>
</mat-select>

View File

@ -8,7 +8,7 @@ enum LoginMethodComponentType {
}
@Component({
selector: 'app-dialog-add-type',
selector: 'cnsl-dialog-add-type',
templateUrl: './dialog-add-type.component.html',
styleUrls: ['./dialog-add-type.component.scss'],
})

View File

@ -4,7 +4,7 @@
<div class="mfa-list">
<div class="mfa mat-elevation-z1" *ngFor="let mfa of mfas">
<span>
{{(componentType == LoginMethodComponentType.SecondFactor ? 'MFA.SECONDFACTORTYPES.':
{{(componentType === LoginMethodComponentType.SecondFactor ? 'MFA.SECONDFACTORTYPES.':
LoginMethodComponentType.MultiFactor ? 'MFA.MULTIFACTORTYPES.': '')+mfa | translate}}
</span>

View File

@ -30,7 +30,7 @@ export enum LoginMethodComponentType {
}
@Component({
selector: 'app-mfa-table',
selector: 'cnsl-mfa-table',
templateUrl: './mfa-table.component.html',
styleUrls: ['./mfa-table.component.scss'],
})

View File

@ -1,4 +1,4 @@
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
<cnsl-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
[title]="'POLICY.LOGIN_TEXTS.TITLE' | translate"
[description]="'POLICY.LOGIN_TEXTS.DESCRIPTION' | translate">
@ -35,23 +35,23 @@
</cnsl-form-field>
</form>
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.login'] | hasFeature | async) == false" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-info-section *ngIf="serviceType === PolicyComponentServiceType.MGMT && (['custom_text.login'] | hasFeature | async) === false" [featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'custom_text.login'})"></span>
</cnsl-info-section>
<div class="divider"></div>
<div class="content" >
<cnsl-edit-text label="one" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.login'] | hasFeature | async) == false" [default$]="getDefaultInitMessageTextMap$" [current$]="getCustomInitMessageTextMap$" (changedValues)="updateCurrentValues(
<cnsl-edit-text label="one" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['custom_text.login'] | hasFeature | async) === false" [default$]="getDefaultInitMessageTextMap$" [current$]="getCustomInitMessageTextMap$" (changedValues)="updateCurrentValues(
$event)"></cnsl-edit-text>
</div>
<div class="actions">
<button class="reset-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.login'] | hasFeature | async) == false" (click)="resetDefault()" color="warn" type="submit"
<button class="reset-button" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['custom_text.login'] | hasFeature | async) === false" (click)="resetDefault()" color="warn" type="submit"
mat-stroked-button><i class="las la-history"></i> {{ 'ACTIONS.RESETDEFAULT' | translate }}</button>
<button class="save-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.login'] | hasFeature | async) == false" (click)="saveCurrentMessage()" color="primary" type="submit"
<button class="save-button" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['custom_text.login'] | hasFeature | async) === false" (click)="saveCurrentMessage()" color="primary" type="submit"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
</div>
<app-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></app-policy-grid>
</app-detail-layout>
<cnsl-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></cnsl-policy-grid>
</cnsl-detail-layout>

View File

@ -19,12 +19,13 @@ import { AdminService } from 'src/app/services/admin.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import { InfoSectionType } from '../../info-section/info-section.component';
import { GridPolicy, LOGIN_TEXTS_POLICY } from '../../policy-grid/policies';
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
import { mapRequestValues } from './helper';
// tslint:disable
/* eslint-disable */
const KeyNamesArray = [
'emailVerificationDoneText',
'emailVerificationText',
@ -61,7 +62,7 @@ const KeyNamesArray = [
'passwordlessText',
'externalRegistrationUserOverviewText'
];
// tslint:enable
/* eslint-enable */
const REQUESTMAP = {
[PolicyComponentServiceType.MGMT]: {
@ -88,7 +89,7 @@ const REQUESTMAP = {
},
};
@Component({
selector: 'app-login-texts',
selector: 'cnsl-login-texts',
templateUrl: './login-texts.component.html',
styleUrls: ['./login-texts.component.scss'],
})
@ -114,6 +115,7 @@ export class LoginTextsComponent implements OnDestroy {
public currentPolicy: GridPolicy = LOGIN_TEXTS_POLICY;
public destroy$: Subject<void> = new Subject();
public InfoSectionType: any = InfoSectionType;
public form: FormGroup = new FormGroup({
currentSubMap: new FormControl('emailVerificationDoneText'),

View File

@ -1,10 +1,10 @@
<app-detail-layout [maxWidth]="false" [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
<cnsl-detail-layout [maxWidth]="false" [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
[title]="'POLICY.MESSAGE_TEXTS.TITLE' | translate"
[description]="'POLICY.MESSAGE_TEXTS.DESCRIPTION' | translate">
<div class="top-actions">
<div class="message-type">
<button (click)="setCurrentType(type.value)" [ngClass]="{'active': currentType == type.value}" mat-button *ngFor="let type of MESSAGETYPES | keyvalue">{{'POLICY.MESSAGE_TEXTS.TYPES.'+type.value | translate}}</button>
<button (click)="setCurrentType($any(type).value)" [ngClass]="{'active': currentType === type.value}" mat-button *ngFor="let type of MESSAGETYPES | keyvalue">{{'POLICY.MESSAGE_TEXTS.TYPES.'+type.value | translate}}</button>
</div>
<cnsl-form-field class="language">
@ -19,23 +19,23 @@
</cnsl-form-field>
</div>
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.message'] | hasFeature | async) == false" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-info-section *ngIf="serviceType === PolicyComponentServiceType.MGMT && (['custom_text.message'] | hasFeature | async) === false" [featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'custom_text.message'})"></span>
</cnsl-info-section>
<div class="content" >
<cnsl-edit-text [chips]="chips[currentType]" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.message'] | hasFeature | async) == false" label="one" [default$]="getDefaultInitMessageTextMap$" [current$]="getCustomInitMessageTextMap$" (changedValues)="updateCurrentValues(
<cnsl-edit-text [chips]="chips[currentType]" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['custom_text.message'] | hasFeature | async) === false" label="one" [default$]="getDefaultInitMessageTextMap$" [current$]="getCustomInitMessageTextMap$" (changedValues)="updateCurrentValues(
$event)"></cnsl-edit-text>
</div>
<div class="actions">
<button class="reset-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['custom_text.message'] | hasFeature | async) == false" (click)="resetDefault()" color="warn" type="submit"
<button class="reset-button" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['custom_text.message'] | hasFeature | async) === false" (click)="resetDefault()" color="warn" type="submit"
mat-stroked-button><i class="las la-history"></i> {{ 'ACTIONS.RESETDEFAULT' | translate }}</button>
<button class="save-button" [disabled]="!updateRequest || serviceType == PolicyComponentServiceType.MGMT && (['custom_text.message'] | hasFeature | async) == false" (click)="saveCurrentMessage()" color="primary" type="submit"
<button class="save-button" [disabled]="!updateRequest || serviceType === PolicyComponentServiceType.MGMT && (['custom_text.message'] | hasFeature | async) === false" (click)="saveCurrentMessage()" color="primary" type="submit"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
</div>
<div class="divider"></div>
<app-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></app-policy-grid>
</app-detail-layout>
<cnsl-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></cnsl-policy-grid>
</cnsl-detail-layout>

View File

@ -40,6 +40,7 @@ import { AdminService } from 'src/app/services/admin.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import { InfoSectionType } from '../../info-section/info-section.component';
import { GridPolicy, MESSAGE_TEXTS_POLICY } from '../../policy-grid/policies';
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
@ -267,7 +268,7 @@ const REQUESTMAP = {
},
};
@Component({
selector: 'app-message-texts',
selector: 'cnsl-message-texts',
templateUrl: './message-texts.component.html',
styleUrls: ['./message-texts.component.scss'],
})
@ -285,6 +286,7 @@ export class MessageTextsComponent implements OnDestroy {
public updateRequest!: SetCustomInitMessageTextRequest | SetDefaultInitMessageTextRequest;
public InfoSectionType: any = InfoSectionType;
public chips: {
[messagetype: string]: Array<{ key: string; value: string; }>;
} = {
@ -446,6 +448,8 @@ export class MessageTextsComponent implements OnDestroy {
return this.stripDetails((this.service as ManagementService).getCustomDomainClaimedMessageText(req));
case MESSAGETYPES.PASSWORDLESS:
return this.stripDetails((this.service as ManagementService).getCustomPasswordlessRegistrationMessageText(req));
default:
return undefined;
}
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
switch (type) {
@ -461,7 +465,11 @@ export class MessageTextsComponent implements OnDestroy {
return this.stripDetails((this.service as AdminService).getCustomDomainClaimedMessageText(req));
case MESSAGETYPES.PASSWORDLESS:
return this.stripDetails((this.service as AdminService).getCustomPasswordlessRegistrationMessageText(req));
default:
return undefined;
}
} else {
return undefined;
}
}
@ -548,8 +556,7 @@ export class MessageTextsComponent implements OnDestroy {
});
dialogRef.afterClosed().subscribe(resp => {
if (resp) {
if (this.serviceType === PolicyComponentServiceType.MGMT) {
if (resp && this.serviceType === PolicyComponentServiceType.MGMT) {
const handler = (prom: Promise<any>): Promise<any> => {
return prom.then(() => {
setTimeout(() => {
@ -574,10 +581,11 @@ export class MessageTextsComponent implements OnDestroy {
case MESSAGETYPES.DOMAINCLAIMED:
return handler((this.service as ManagementService)
.resetCustomPasswordlessRegistrationMessageTextToDefault(this.locale));
}
default:
return Promise.reject();
}
} else {
return Promise.reject();
}
});
}

View File

@ -1,8 +1,8 @@
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
<cnsl-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
[title]="'POLICY.IAM_POLICY.TITLE' | translate" [description]="'POLICY.IAM_POLICY.DESCRIPTION' | translate">
<cnsl-info-section *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</cnsl-info-section>
<ng-template appHasRole [appHasRole]="['iam.policy.delete']">
<ng-template cnslHasRole [hasRole]="['iam.policy.delete']">
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
{{'POLICY.RESET' | translate}}
@ -24,5 +24,5 @@
}}</button>
</div>
<app-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="login"></app-policy-grid>
</app-detail-layout>
<cnsl-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="login"></cnsl-policy-grid>
</cnsl-detail-layout>

View File

@ -15,7 +15,7 @@ import { GridPolicy, IAM_POLICY } from '../../policy-grid/policies';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
@Component({
selector: 'app-org-iam-policy',
selector: 'cnsl-org-iam-policy',
templateUrl: './org-iam-policy.component.html',
styleUrls: ['./org-iam-policy.component.scss'],
})
@ -65,7 +65,7 @@ export class OrgIamPolicyComponent implements OnDestroy {
});
}
private async getData(): Promise<GetCustomOrgIAMPolicyResponse.AsObject | GetOrgIAMPolicyResponse.AsObject | undefined> {
private async getData(): Promise<GetCustomOrgIAMPolicyResponse.AsObject | GetOrgIAMPolicyResponse.AsObject | any> {
switch (this.serviceType) {
case PolicyComponentServiceType.MGMT:
return this.managementService.getOrgIAMPolicy();
@ -74,6 +74,8 @@ export class OrgIamPolicyComponent implements OnDestroy {
return this.adminService.getCustomOrgIAMPolicy(this.org.id);
}
break;
default:
return Promise.reject();
}
}

View File

@ -1,6 +1,6 @@
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
<cnsl-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
[title]="'POLICY.PWD_AGE.TITLE' | translate" [description]="'POLICY.PWD_AGE.DESCRIPTION' | translate">
<ng-template appHasRole [appHasRole]="['policy.delete']">
<ng-template cnslHasRole [hasRole]="['policy.delete']">
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
{{'POLICY.RESET' | translate}}
@ -41,4 +41,4 @@
<button (click)="savePolicy()" color="primary" type="submit"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
</div>
</app-detail-layout>
</cnsl-detail-layout>

View File

@ -15,7 +15,7 @@ import { PolicyComponentServiceType } from '../policy-component-types.enum';
@Component({
selector: 'app-password-age-policy',
selector: 'cnsl-password-age-policy',
templateUrl: './password-age-policy.component.html',
styleUrls: ['./password-age-policy.component.scss'],
})

View File

@ -1,9 +1,9 @@
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
<cnsl-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
[title]="'POLICY.PWD_COMPLEXITY.TITLE' | translate" [description]="'POLICY.PWD_COMPLEXITY.DESCRIPTION' | translate">
<cnsl-info-section *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</cnsl-info-section>
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) == false" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-info-section *ngIf="serviceType === PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) === false" [featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'password_complexity_policy'})"></span>
</cnsl-info-section>
@ -11,8 +11,8 @@
<mat-spinner diameter="30" *ngIf="loading" color="primary"></mat-spinner>
</div>
<ng-template appHasRole [appHasRole]="['policy.delete']">
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) == false"
<ng-template cnslHasRole [hasRole]="['policy.delete']">
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) === false"
matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
{{'POLICY.RESET' | translate}}
</button>
@ -24,11 +24,11 @@
<span class="left-desc">{{'POLICY.DATA.MINLENGTH' | translate}}</span>
<span class="fill-space"></span>
<div class="length-wrapper">
<button mat-icon-button (click)="decrementLength()" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) == false">
<button mat-icon-button (click)="decrementLength()" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) === false">
<mat-icon>remove</mat-icon>
</button>
<span>{{complexityData?.minLength}}</span>
<button mat-icon-button (click)="incrementLength()" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) == false">
<button mat-icon-button (click)="incrementLength()" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) === false">
<mat-icon>add</mat-icon>
</button>
</div>
@ -37,14 +37,14 @@
<mat-icon class="icon" svgIcon="mdi_numeric"></mat-icon>
<span class="left-desc">{{'POLICY.DATA.HASNUMBER' | translate}}</span>
<span class="fill-space"></span>
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl [(ngModel)]="complexityData.hasNumber" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) == false">
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl [(ngModel)]="complexityData.hasNumber" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) === false">
</mat-slide-toggle>
</div>
<div class="row">
<mat-icon class="icon" svgIcon="mdi_symbol"></mat-icon>
<span class="left-desc">{{'POLICY.DATA.HASSYMBOL' | translate}}</span>
<span class="fill-space"></span>
<mat-slide-toggle color="primary" name="hasSymbol" ngDefaultControl [(ngModel)]="complexityData.hasSymbol" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) == false">
<mat-slide-toggle color="primary" name="hasSymbol" ngDefaultControl [(ngModel)]="complexityData.hasSymbol" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) === false">
</mat-slide-toggle>
</div>
<div class="row">
@ -52,7 +52,7 @@
<span class="left-desc">{{'POLICY.DATA.HASLOWERCASE' | translate}}</span>
<span class="fill-space"></span>
<mat-slide-toggle color="primary" name="hasLowercase" ngDefaultControl
[(ngModel)]="complexityData.hasLowercase" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) == false">
[(ngModel)]="complexityData.hasLowercase" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) === false">
</mat-slide-toggle>
</div>
<div class="row">
@ -60,15 +60,15 @@
<span class="left-desc">{{'POLICY.DATA.HASUPPERCASE' | translate}}</span>
<span class="fill-space"></span>
<mat-slide-toggle color="primary" name="hasUppercase" ngDefaultControl
[(ngModel)]="complexityData.hasUppercase" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) == false">
[(ngModel)]="complexityData.hasUppercase" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) === false">
</mat-slide-toggle>
</div>
</div>
<div class="btn-container">
<button (click)="savePolicy()" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) == false" color="primary" type="submit" mat-raised-button>{{ 'ACTIONS.SAVE' | translate
<button (click)="savePolicy()" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['password_complexity_policy'] | hasFeature | async) === false" color="primary" type="submit" mat-raised-button>{{ 'ACTIONS.SAVE' | translate
}}</button>
</div>
<app-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="security"></app-policy-grid>
</app-detail-layout>
<cnsl-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="security"></cnsl-policy-grid>
</cnsl-detail-layout>

View File

@ -13,11 +13,12 @@ import { AdminService } from 'src/app/services/admin.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import { InfoSectionType } from '../../info-section/info-section.component';
import { COMPLEXITY_POLICY, GridPolicy } from '../../policy-grid/policies';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
@Component({
selector: 'app-password-policy',
selector: 'cnsl-password-policy',
templateUrl: './password-complexity-policy.component.html',
styleUrls: ['./password-complexity-policy.component.scss'],
})
@ -32,6 +33,7 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
public loading: boolean = false;
public currentPolicy: GridPolicy = COMPLEXITY_POLICY;
public InfoSectionType: any = InfoSectionType;
constructor(
private route: ActivatedRoute,

View File

@ -1,14 +1,14 @@
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
<cnsl-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
[title]="'POLICY.PWD_LOCKOUT.TITLE' | translate" [description]="'POLICY.PWD_LOCKOUT.DESCRIPTION' | translate">
<cnsl-info-section class="default" *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</cnsl-info-section>
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['lockout_policy'] | hasFeature | async) == false" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-info-section *ngIf="serviceType === PolicyComponentServiceType.MGMT && (['lockout_policy'] | hasFeature | async) === false" [featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'lockout_policy'})"></span>
</cnsl-info-section>
<ng-template appHasRole [appHasRole]="['policy.delete']">
<button [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['lockout_policy'] | hasFeature | async) == false" *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
<ng-template cnslHasRole [hasRole]="['policy.delete']">
<button [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['lockout_policy'] | hasFeature | async) === false" *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="resetPolicy()" mat-stroked-button>
{{'POLICY.RESET' | translate}}
</button>
@ -19,11 +19,11 @@
<span class="left-desc">{{'POLICY.DATA.MAXATTEMPTS' | translate}}</span>
<span class="fill-space"></span>
<div class="length-wrapper">
<button [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['lockout_policy'] | hasFeature | async) == false" mat-icon-button (click)="decrementMaxAttempts()">
<button [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['lockout_policy'] | hasFeature | async) === false" mat-icon-button (click)="decrementMaxAttempts()">
<mat-icon>remove</mat-icon>
</button>
<span>{{lockoutData?.maxPasswordAttempts}}</span>
<button [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['lockout_policy'] | hasFeature | async) == false" mat-icon-button (click)="incrementMaxAttempts()">
<button [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['lockout_policy'] | hasFeature | async) === false" mat-icon-button (click)="incrementMaxAttempts()">
<mat-icon>add</mat-icon>
</button>
</div>
@ -31,7 +31,7 @@
</div>
<div class="btn-container">
<button (click)="savePolicy()" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['lockout_policy'] | hasFeature | async) == false" color="primary" type="submit" mat-raised-button>{{ 'ACTIONS.SAVE' | translate
<button (click)="savePolicy()" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['lockout_policy'] | hasFeature | async) === false" color="primary" type="submit" mat-raised-button>{{ 'ACTIONS.SAVE' | translate
}}</button>
</div>
</app-detail-layout>
</cnsl-detail-layout>

View File

@ -12,10 +12,11 @@ import { AdminService } from 'src/app/services/admin.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import { InfoSectionType } from '../../info-section/info-section.component';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
@Component({
selector: 'app-password-lockout-policy',
selector: 'cnsl-password-lockout-policy',
templateUrl: './password-lockout-policy.component.html',
styleUrls: ['./password-lockout-policy.component.scss'],
})
@ -27,6 +28,7 @@ export class PasswordLockoutPolicyComponent implements OnDestroy {
public lockoutData!: LockoutPolicy.AsObject;
private sub: Subscription = new Subscription();
public PolicyComponentServiceType: any = PolicyComponentServiceType;
public InfoSectionType: any = InfoSectionType;
constructor(
private route: ActivatedRoute,

View File

@ -1,10 +1,10 @@
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
<cnsl-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam/policies' : '/org']"
[title]="'POLICY.PRIVACY_POLICY.TITLE' | translate"
[description]="'POLICY.PRIVACY_POLICY.DESCRIPTION' | translate">
<cnsl-info-section *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</cnsl-info-section>
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['privacy_policy'] | hasFeature | async) == false" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-info-section *ngIf="serviceType === PolicyComponentServiceType.MGMT && (['privacy_policy'] | hasFeature | async) === false" [featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'privacy_policy'})"></span>
</cnsl-info-section>
@ -25,12 +25,11 @@
</div>
<div class="actions">
<button *ngIf="!privacyPolicy?.isDefault" class="reset-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['privacy_policy'] | hasFeature | async) == false" (click)="resetDefault()" color="warn" type="submit"
<button *ngIf="!privacyPolicy?.isDefault" class="reset-button" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['privacy_policy'] | hasFeature | async) === false" (click)="resetDefault()" color="warn" type="submit"
mat-stroked-button><i class="las la-history"></i> {{ 'ACTIONS.RESETDEFAULT' | translate }}</button>
<button class="save-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['privacy_policy'] | hasFeature | async) == false" (click)="saveCurrentMessage()" color="primary" type="submit"
<button class="save-button" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['privacy_policy'] | hasFeature | async) === false" (click)="saveCurrentMessage()" color="primary" type="submit"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
</div>
<app-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></app-policy-grid>
</app-detail-layout>
<cnsl-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></cnsl-policy-grid>
</cnsl-detail-layout>

View File

@ -18,13 +18,14 @@ import { AdminService } from 'src/app/services/admin.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import { InfoSectionType } from '../../info-section/info-section.component';
import { CnslLinks } from '../../links/links.component';
import { GridPolicy, PRIVACY_POLICY } from '../../policy-grid/policies';
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
@Component({
selector: 'app-privacy-policy',
selector: 'cnsl-privacy-policy',
templateUrl: './privacy-policy.component.html',
styleUrls: ['./privacy-policy.component.scss'],
})
@ -39,6 +40,7 @@ export class PrivacyPolicyComponent implements OnDestroy {
public privacyPolicy!: PrivacyPolicy.AsObject;
public form!: FormGroup;
public currentPolicy: GridPolicy = PRIVACY_POLICY;
public InfoSectionType: any = InfoSectionType;
constructor(
private route: ActivatedRoute,

View File

@ -1,33 +1,33 @@
<div class="preview" *ngIf="policy">
<span class="label">{{label}}</span>
<div class="dashed" [ngClass]="{'dark': theme === Theme.DARK, 'light': theme === Theme.LIGHT}" [style.background]="theme == Theme.DARK ? policy.backgroundColorDark : policy.backgroundColor">
<div class="login-wrapper" [style.color]="theme == Theme.DARK ? policy.fontColorDark : policy.fontColor">
<div class="dashed" [ngClass]="{'dark': theme === Theme.DARK, 'light': theme === Theme.LIGHT}" [style.background]="theme === Theme.DARK ? policy.backgroundColorDark : policy.backgroundColor">
<div class="login-wrapper" [style.color]="theme === Theme.DARK ? policy.fontColorDark : policy.fontColor">
<ng-container *ngIf="preview === Preview.PREVIEW; else currentimgs">
<img *ngIf="images['previewLogo'] && theme == Theme.LIGHT" [src]="images['previewLogo']" alt="logo-mock" />
<img *ngIf="images['previewDarkLogo'] && theme == Theme.DARK" [src]="images['previewDarkLogo']" alt="logo-mock" />
<img *ngIf="images['previewLogo'] && theme === Theme.LIGHT" [src]="images['previewLogo']" alt="logo-mock" />
<img *ngIf="images['previewDarkLogo'] && theme === Theme.DARK" [src]="images['previewDarkLogo']" alt="logo-mock" />
</ng-container>
<ng-template #currentimgs>
<img *ngIf="images['logo'] && theme == Theme.LIGHT" [src]="images['logo']" alt="logo-mock" />
<img *ngIf="images['darkLogo'] && theme == Theme.DARK" [src]="images['darkLogo']" alt="logo-mock" />
<img *ngIf="images['logo'] && theme === Theme.LIGHT" [src]="images['logo']" alt="logo-mock" />
<img *ngIf="images['darkLogo'] && theme === Theme.DARK" [src]="images['darkLogo']" alt="logo-mock" />
</ng-template>
<h1 [style.color]="theme == Theme.DARK ? policy.fontColorDark : policy.fontColor">{{'POLICY.PRIVATELABELING.PREVIEW.TITLE' | translate}}</h1>
<p [style.color]="theme == Theme.DARK ? policy.fontColorDark : policy.fontColor" class="desc-text">{{'POLICY.PRIVATELABELING.PREVIEW.SECOND' | translate}}</p>
<h1 [style.color]="theme === Theme.DARK ? policy.fontColorDark : policy.fontColor">{{'POLICY.PRIVATELABELING.PREVIEW.TITLE' | translate}}</h1>
<p [style.color]="theme === Theme.DARK ? policy.fontColorDark : policy.fontColor" class="desc-text">{{'POLICY.PRIVATELABELING.PREVIEW.SECOND' | translate}}</p>
<cnsl-form-field class="formfield">
<cnsl-label>Loginname</cnsl-label>
<input cnslInput [style.color]="theme == Theme.DARK ? policy.fontColorDark : policy.fontColor" value="road.runner"/>
<input cnslInput [style.color]="theme === Theme.DARK ? policy.fontColorDark : policy.fontColor" value="road.runner"/>
</cnsl-form-field>
<div class="error-msg" [style.color]="theme == Theme.DARK ? policy.warnColorDark : policy.warnColor">
<i class="las la-exclamation-circle" [style.color]="theme == Theme.DARK ? policy.warnColorDark : policy.warnColor"></i>
<span [style.color]="theme == Theme.DARK ? policy.warnColorDark : policy.warnColor">{{'POLICY.PRIVATELABELING.PREVIEW.ERROR' | translate}}</span>
<div class="error-msg" [style.color]="theme === Theme.DARK ? policy.warnColorDark : policy.warnColor">
<i class="las la-exclamation-circle" [style.color]="theme === Theme.DARK ? policy.warnColorDark : policy.warnColor"></i>
<span [style.color]="theme === Theme.DARK ? policy.warnColorDark : policy.warnColor">{{'POLICY.PRIVATELABELING.PREVIEW.ERROR' | translate}}</span>
</div>
<div class="btn-wrapper">
<button mat-stroked-button [style.color]="theme == Theme.DARK ? policy.primaryColorDark : policy.primaryColor">{{'POLICY.PRIVATELABELING.PREVIEW.SECONDARYBUTTON' | translate}}</button>
<button *ngIf="theme == Theme.DARK" mat-raised-button [style.background]="policy.primaryColorDark" [style.color]="policy.primaryColorDark == '#ffffff' ? '#000000' : '#ffffff'">{{'POLICY.PRIVATELABELING.PREVIEW.PRIMARYBUTTON' | translate}}</button>
<button *ngIf="theme == Theme.LIGHT" mat-raised-button [style.background]="policy.primaryColor" [style.color]="policy.primaryColor == '#ffffff' ? '#000000' : '#ffffff'">{{'POLICY.PRIVATELABELING.PREVIEW.PRIMARYBUTTON' | translate}}</button>
<button mat-stroked-button [style.color]="theme === Theme.DARK ? policy.primaryColorDark : policy.primaryColor">{{'POLICY.PRIVATELABELING.PREVIEW.SECONDARYBUTTON' | translate}}</button>
<button *ngIf="theme === Theme.DARK" mat-raised-button [style.background]="policy.primaryColorDark" [style.color]="policy.primaryColorDark === '#ffffff' ? '#000000' : '#ffffff'">{{'POLICY.PRIVATELABELING.PREVIEW.PRIMARYBUTTON' | translate}}</button>
<button *ngIf="theme === Theme.LIGHT" mat-raised-button [style.background]="policy.primaryColor" [style.color]="policy.primaryColor === '#ffffff' ? '#000000' : '#ffffff'">{{'POLICY.PRIVATELABELING.PREVIEW.PRIMARYBUTTON' | translate}}</button>
</div>
</div>
</div>

View File

@ -11,7 +11,7 @@
<p class="desc">{{'POLICY.PRIVATELABELING.PREVIEW_DESCRIPTION' | translate}}</p>
<cnsl-info-section *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</cnsl-info-section>
<cnsl-info-section *ngIf="serviceType == PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async) == false" [featureLink]="['/org/features']" class="info" type="WARN">
<cnsl-info-section *ngIf="serviceType === PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async) === false" [featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'label_policy.private_label'})"></span>
</cnsl-info-section>
@ -34,14 +34,14 @@
<span class="fill-space"></span>
<ng-template appHasRole [appHasRole]="['policy.delete']">
<ng-template cnslHasRole [hasRole]="['policy.delete']">
<button class="reset-button" *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
{{'POLICY.RESET' | translate}}
</button>
</ng-template>
<button class="activate-button" [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async) == false" mat-raised-button color="primary" (click)="activatePolicy()">
<button class="activate-button" [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async) === false" mat-raised-button color="primary" (click)="activatePolicy()">
{{'POLICY.PRIVATELABELING.ACTIVATEPREVIEW' | translate}}
</button>
</div>
@ -99,8 +99,8 @@
<label class="file-label">
<i class="icon las la-image"></i>
<span>{{isHoveringOverDarkLogo ? ('POLICY.PRIVATELABELING.RELEASE' | translate): ('POLICY.PRIVATELABELING.DROP' | translate)}}</span>
<input #selectedFile style="display: none;" class="file-input" type="file" (change)="onDropLogo(theme, $event.target.files)">
<a class="btn" *ngIf="serviceType == PolicyComponentServiceType.ADMIN || (serviceType == PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async))" (click)="$event.preventDefault(); selectedFile.click();">{{'POLICY.PRIVATELABELING.BTN' | translate}}</a>
<input #selectedFile style="display: none;" class="file-input" type="file" (change)="onDropLogo(theme, $any($event.target).files)">
<a class="btn" *ngIf="serviceType === PolicyComponentServiceType.ADMIN || (serviceType === PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async))" (click)="$event.preventDefault(); selectedFile.click();">{{'POLICY.PRIVATELABELING.BTN' | translate}}</a>
</label>
</div>
</div>
@ -138,8 +138,8 @@
<label class="file-label">
<i class="icon las la-image"></i>
<span>{{isHoveringOverDarkIcon ? ('POLICY.PRIVATELABELING.RELEASE' | translate): ('POLICY.PRIVATELABELING.DROP' | translate)}}</span>
<input #selectedFileIcon style="display: none;" class="file-input" type="file" (change)="onDropIcon(theme, $event.target.files)">
<a class="btn" *ngIf="serviceType == PolicyComponentServiceType.ADMIN || (serviceType == PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async))" (click)="$event.preventDefault(); selectedFileIcon.click();">{{'POLICY.PRIVATELABELING.BTN' | translate}}</a>
<input #selectedFileIcon style="display: none;" class="file-input" type="file" (change)="onDropIcon(theme, $any($event.target).files)">
<a class="btn" *ngIf="serviceType === PolicyComponentServiceType.ADMIN || (serviceType === PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async))" (click)="$event.preventDefault(); selectedFileIcon.click();">{{'POLICY.PRIVATELABELING.BTN' | translate}}</a>
</label>
</div>
</div>
@ -156,9 +156,7 @@
</mat-panel-title>
</mat-expansion-panel-header>
<!-- <span class="title">{{ theme === Theme.DARK ? ('POLICY.PRIVATELABELING.DARK' | translate) : ('POLICY.PRIVATELABELING.LIGHT' | translate)}}</span> -->
<ng-container *ngIf="theme==Theme.DARK">
<ng-container *ngIf="theme === Theme.DARK">
<div class="colors" *ngIf="data && previewData">
<div class="color">
<cnsl-color [colorType]="ColorType.BACKGROUNDDARK" (previewChanged)="previewData.backgroundColorDark = $event" name="Background Color" [color]="data.backgroundColorDark" [previewColor]="previewData.backgroundColorDark"></cnsl-color>
@ -178,7 +176,7 @@
</div>
</ng-container>
<ng-container *ngIf="theme==Theme.LIGHT">
<ng-container *ngIf="theme === Theme.LIGHT">
<div class="colors" *ngIf="data && previewData">
<div class="color">
<cnsl-color [colorType]="ColorType.BACKGROUNDLIGHT" (previewChanged)="previewData.backgroundColor = $event" name="Background Color" [color]="data.backgroundColor" [previewColor]="previewData.backgroundColor"></cnsl-color>
@ -213,12 +211,12 @@
</mat-expansion-panel-header>
<div class="fonts">
<cnsl-info-section class="info-section">{{'POLICY.PRIVATELABELING.FONTINLOGINONLY' | translate}}</cnsl-info-section>
<div class="font-preview mat-elevation-z3" *ngIf="preview == Preview.PREVIEW && previewData.fontUrl || preview == Preview.CURRENT && data.fontUrl">
<div class="font-preview mat-elevation-z3" *ngIf="preview === Preview.PREVIEW && previewData.fontUrl || preview === Preview.CURRENT && data.fontUrl">
<mat-icon class="icon">text_fields</mat-icon>
<span>ABC • abc • 123</span>
<span class="fill-space"></span>
<button [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async) == false" matTooltip="{{'ACTIONS.REMOVE' | translate}}" mat-icon-button color="warn" (click)="deleteFont()"><mat-icon>remove_circle</mat-icon></button>
<button [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async) === false" matTooltip="{{'ACTIONS.REMOVE' | translate}}" mat-icon-button color="warn" (click)="deleteFont()"><mat-icon>remove_circle</mat-icon></button>
</div>
<div class="dropzone" cnslDropzone (hovered)="toggleHoverFont($event)"
@ -227,8 +225,8 @@
<label class="file-label">
<i class="icon las la-file"></i>
<span >{{isHoveringOverFont ? ('POLICY.PRIVATELABELING.RELEASEFONT' | translate): ('POLICY.PRIVATELABELING.DROPFONT' | translate)}}</span>
<input #selectedFontFile style="display: none;" class="file-input" type="file" (change)="onDropFont($event.target.files)">
<a class="btn" *ngIf="serviceType == PolicyComponentServiceType.ADMIN || (serviceType == PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async))" (click)="selectedFontFile.click()">{{'POLICY.PRIVATELABELING.BTN' | translate}}</a>
<input #selectedFontFile style="display: none;" class="file-input" type="file" (change)="onDropFont($any($event.target).files)">
<a class="btn" *ngIf="serviceType === PolicyComponentServiceType.ADMIN || (serviceType === PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async))" (click)="selectedFontFile.click()">{{'POLICY.PRIVATELABELING.BTN' | translate}}</a>
</label>
</div>
</div>
@ -246,25 +244,25 @@
<div class="adv-container" *ngIf="previewData">
<ng-container
*ngIf="serviceType == PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async) == false">
<cnsl-info-section [featureLink]="['/org/features']" class="info" type="WARN"
*ngIf="serviceType === PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async) === false">
<cnsl-info-section [featureLink]="['/org/features']" class="info" [type]="InfoSectionType.WARN"
>
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'label_policy.private_label'})"></span>
</cnsl-info-section>
</ng-container>
<mat-slide-toggle class="toggle" color="primary" ngDefaultControl [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async) == false"
<mat-slide-toggle class="toggle" color="primary" ngDefaultControl [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['label_policy.private_label'] | hasFeature | async) === false"
[(ngModel)]="previewData.hideLoginNameSuffix" (change)="savePolicy()">
{{'POLICY.DATA.HIDELOGINNAMESUFFIX' | translate}}
</mat-slide-toggle>
<ng-container
*ngIf="serviceType == PolicyComponentServiceType.MGMT && (['label_policy.watermark'] | hasFeature | async) == false">
<cnsl-info-section [featureLink]="['/org/features']" class="info" type="WARN">
*ngIf="serviceType === PolicyComponentServiceType.MGMT && (['label_policy.watermark'] | hasFeature | async) === false">
<cnsl-info-section [featureLink]="['/org/features']" class="info" type]="InfoSectionType.WARN">
<span [innerHTML]="'FEATURES.NOTAVAILABLE' | translate: ({value: 'label_policy.watermark'})"></span>
</cnsl-info-section>
</ng-container>
<mat-slide-toggle class="toggle" color="primary" ngDefaultControl [disabled]="serviceType == PolicyComponentServiceType.MGMT && (['label_policy.watermark'] | hasFeature | async) == false"
<mat-slide-toggle class="toggle" color="primary" ngDefaultControl [disabled]="serviceType === PolicyComponentServiceType.MGMT && (['label_policy.watermark'] | hasFeature | async) === false"
[(ngModel)]="previewData.disableWatermark" (change)="savePolicy()">
{{'POLICY.DATA.DISABLEWATERMARK' | translate}}
</mat-slide-toggle>
@ -275,8 +273,8 @@
<div class="preview-wrapper">
<!-- <cnsl-preview class="prev" label="CURRENT CONFIG" [policy]="data"></cnsl-preview> -->
<div class="col">
<button color="primary" mat-raised-button class="preview-changer" (click)="preview = preview == Preview.PREVIEW ? Preview.CURRENT : Preview.PREVIEW" matTooltip="{{'POLICY.PRIVATELABELING.CHANGEVIEW' | translate}}" [ngClass]="{'active': preview === Preview.PREVIEW}" >
<span><span [ngClass]="{'strong': preview == Preview.PREVIEW}">P</span> / <span [ngClass]="{'strong': preview == Preview.CURRENT}">C</span></span>
<button color="primary" mat-raised-button class="preview-changer" (click)="preview = preview === Preview.PREVIEW ? Preview.CURRENT : Preview.PREVIEW" matTooltip="{{'POLICY.PRIVATELABELING.CHANGEVIEW' | translate}}" [ngClass]="{'active': preview === Preview.PREVIEW}" >
<span><span [ngClass]="{'strong': preview === Preview.PREVIEW}">P</span> / <span [ngClass]="{'strong': preview === Preview.CURRENT}">C</span></span>
</button>
<cnsl-preview *ngIf="preview === Preview.CURRENT" [refresh]="refreshPreview" [images]="images" [preview]="preview" [theme]="theme" class="prev" label="CURRENT" [policy]="data"></cnsl-preview>
@ -285,5 +283,5 @@
</div>
</div>
<app-policy-grid class="grid" [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></app-policy-grid>
<cnsl-policy-grid class="grid" [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></cnsl-policy-grid>
</div>

View File

@ -25,6 +25,7 @@ import { StorageKey, StorageLocation, StorageService } from 'src/app/services/st
import { ThemeService } from 'src/app/services/theme.service';
import { ToastService } from 'src/app/services/toast.service';
import { InfoSectionType } from '../../info-section/info-section.component';
import { GridPolicy, PRIVATELABEL_POLICY } from '../../policy-grid/policies';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
@ -51,7 +52,7 @@ export enum ColorType {
const MAX_ALLOWED_SIZE = 0.5 * 1024 * 1024;
@Component({
selector: 'app-private-labeling-policy',
selector: 'cnsl-private-labeling-policy',
templateUrl: './private-labeling-policy.component.html',
styleUrls: ['./private-labeling-policy.component.scss'],
})
@ -88,6 +89,7 @@ export class PrivateLabelingPolicyComponent implements OnDestroy {
public loadingImages: boolean = false;
private org!: Org.AsObject;
public currentPolicy: GridPolicy = PRIVATELABEL_POLICY;
public InfoSectionType: any = InfoSectionType;
constructor(
private authService: GrpcAuthService,
private route: ActivatedRoute,
@ -164,7 +166,8 @@ export class PrivateLabelingPolicyComponent implements OnDestroy {
}
}
public onDropFont(filelist: FileList): Promise<any> | void {
public onDropFont(filelist: FileList | null): Promise<any> | void {
if (filelist) {
const file = filelist.item(0);
if (file) {
const formData = new FormData();
@ -177,6 +180,7 @@ export class PrivateLabelingPolicyComponent implements OnDestroy {
}
}
}
}
public deleteFont(): Promise<any> {
const handler = (prom: Promise<any>) => prom.then(() => {

View File

@ -8,8 +8,8 @@
<div class="row-lyt">
<ng-container *ngFor="let policy of filteredPolicies">
<ng-template appHasRole
[appHasRole]="type == PolicyComponentServiceType.ADMIN ? policy.iamWithRole : type == PolicyComponentServiceType.MGMT ? policy.orgWithRole : []">
<ng-template cnslHasRole
[hasRole]="type === PolicyComponentServiceType.ADMIN ? policy.iamWithRole : type === PolicyComponentServiceType.MGMT ? policy.orgWithRole : []">
<div class="p-item card">
<div class="avatar {{policy.color}}">
<mat-icon *ngIf="policy.svgIcon" class="icon" [svgIcon]="policy.svgIcon"></mat-icon>
@ -28,7 +28,7 @@
</div>
<div class="btn-wrapper">
<button
[routerLink]="type == PolicyComponentServiceType.ADMIN ? policy.iamRouterLink : type == PolicyComponentServiceType.MGMT ? policy.orgRouterLink : null"
[routerLink]="type === PolicyComponentServiceType.ADMIN ? policy.iamRouterLink : type === PolicyComponentServiceType.MGMT ? policy.orgRouterLink : null"
mat-stroked-button>{{'POLICY.BTN_EDIT' | translate}}</button>
</div>
</div>

View File

@ -4,7 +4,7 @@ import { PolicyComponentServiceType, PolicyComponentType } from 'src/app/modules
import { GridPolicy, POLICIES } from './policies';
@Component({
selector: 'app-policy-grid',
selector: 'cnsl-policy-grid',
templateUrl: './policy-grid.component.html',
styleUrls: ['./policy-grid.component.scss'],
})

View File

@ -24,13 +24,11 @@ export class ProjectMembersDataSource extends DataSource<Member.AsObject> {
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
constructor(private mgmtService: ManagementService) {
constructor(private service: ManagementService) {
super();
}
public loadMembers(projectId: string,
projectType: ProjectType,
pageIndex: number, pageSize: number, grantId?: string): void {
public loadMembers(projectId: string, projectType: ProjectType, pageIndex: number, pageSize: number, grantId?: string): void {
const offset = pageIndex * pageSize;
this.loadingSubject.next(true);
@ -40,9 +38,9 @@ export class ProjectMembersDataSource extends DataSource<Member.AsObject> {
Promise<ListProjectGrantMembersResponse.AsObject>
| undefined =
projectType === ProjectType.PROJECTTYPE_OWNED ?
this.mgmtService.listProjectMembers(projectId, pageSize, offset) :
this.service.listProjectMembers(projectId, pageSize, offset) :
projectType === ProjectType.PROJECTTYPE_GRANTED && grantId ?
this.mgmtService.listProjectGrantMembers(projectId,
this.service.listProjectGrantMembers(projectId,
grantId, pageSize, offset) : undefined;
if (promise) {
from(promise).pipe(

View File

@ -1,29 +1,28 @@
<app-detail-layout *ngIf="project"
<cnsl-detail-layout *ngIf="project"
[backRouterLink]="[ '/projects', (projectType === ProjectType.PROJECTTYPE_OWNED) ? $any(project)?.id : (projectType === ProjectType.PROJECTTYPE_GRANTED) ? $any(project)?.projectId: '']"
title="{{projectName}} {{ 'PROJECT.MEMBER.TITLE' | translate }}"
description="{{ 'PROJECT.MEMBER.DESCRIPTION' | translate }}">
<p class="desc">{{'MEMBER.DOCSINFO' | translate}} <a href="https://docs.zitadel.ch/docs/manuals/admin-managers"
target="_blank">ZITADEL Managers</a>.</p>
<app-members-table *ngIf="project" [dataSource]="dataSource" [memberRoleOptions]="memberRoleOptions"
<cnsl-members-table *ngIf="project" [dataSource]="dataSource" [memberRoleOptions]="memberRoleOptions"
(updateRoles)="updateRoles($event.member, $event.change)" [factoryLoadFunc]="changePageFactory"
(changedSelection)="selection = $event" [refreshTrigger]="changePage"
[canWrite]="['project.member.write$', 'project.member.write:'+ (projectType === ProjectType.PROJECTTYPE_OWNED) ? $any(project)?.id : (projectType === ProjectType.PROJECTTYPE_GRANTED) ? $any(project)?.projectId: ''] | hasRole | async"
[canDelete]="['project.member.delete$', 'project.member.delete:'+(projectType === ProjectType.PROJECTTYPE_OWNED) ? $any(project)?.id : (projectType === ProjectType.PROJECTTYPE_GRANTED) ? $any(project)?.projectId: ''] | hasRole | async"
(deleteMember)="removeProjectMember($event)">
<ng-template appHasRole selectactions
[appHasRole]="['project.member.delete:' + (projectType === ProjectType.PROJECTTYPE_OWNED) ? $any(project)?.id : (projectType === ProjectType.PROJECTTYPE_GRANTED) ? $any(project)?.projectId: '', 'project.member.delete']">
<ng-template cnslHasRole selectactions
[hasRole]="['project.member.delete:' + (projectType === ProjectType.PROJECTTYPE_OWNED) ? $any(project)?.id : (projectType === ProjectType.PROJECTTYPE_GRANTED) ? $any(project)?.projectId: '', 'project.member.delete']">
<button (click)="removeProjectMemberSelection()" color="warn"
matTooltip="{{'ORG_DETAIL.TABLE.DELETE' | translate}}" class="del-button" mat-raised-button>
<i class="las la-trash"></i>
{{'ACTIONS.SELECTIONDELETE' | translate}}
</button>
</ng-template>
<ng-template appHasRole writeactions
[appHasRole]="['project.member.write:'+(projectType === ProjectType.PROJECTTYPE_OWNED) ? $any(project)?.id : (projectType === ProjectType.PROJECTTYPE_GRANTED) ? $any(project)?.projectId: '','project.member.write']">
<ng-template cnslHasRole writeactions
[hasRole]="['project.member.write:'+(projectType === ProjectType.PROJECTTYPE_OWNED) ? $any(project)?.id : (projectType === ProjectType.PROJECTTYPE_GRANTED) ? $any(project)?.projectId: '','project.member.write']">
<a color="primary" (click)="openAddMember()" color="primary" mat-raised-button>
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
</a>
</ng-template>
</app-members-table>
</app-detail-layout>
<!-- TODO: check for both project.member and project.grant.member permissions -->
</cnsl-members-table>
</cnsl-detail-layout>

View File

@ -14,7 +14,7 @@ import { CreationType, MemberCreateDialogComponent } from '../add-member-dialog/
import { ProjectMembersDataSource, ProjectType } from './project-members-datasource';
@Component({
selector: 'app-project-members',
selector: 'cnsl-project-members',
templateUrl: './project-members.component.html',
styleUrls: ['./project-members.component.scss'],
})
@ -127,6 +127,8 @@ export class ProjectMembersComponent {
}).catch(error => {
this.toast.showError(error);
});
} else {
return Promise.reject();
}
})).then(() => {
setTimeout(() => {
@ -183,6 +185,8 @@ export class ProjectMembersComponent {
user.id,
roles,
);
} else {
return Promise.reject();
}
})).then(() => {
setTimeout(() => {

View File

@ -15,7 +15,7 @@
{{'ACTIONS.CLOSE' | translate}}
</button>
<button [disabled]="setting == undefined" cdkFocusInitial color="primary" mat-raised-button class="ok-button"
<button [disabled]="setting === undefined" cdkFocusInitial color="primary" mat-raised-button class="ok-button"
(click)="closeDialog(setting)">
{{'ACTIONS.OK' | translate}}
</button>

View File

@ -3,7 +3,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { PrivateLabelingSetting } from 'src/app/proto/generated/zitadel/project_pb';
@Component({
selector: 'app-project-private-labeling-dialog',
selector: 'cnsl-project-private-labeling-dialog',
templateUrl: './project-private-labeling-dialog.component.html',
styleUrls: ['./project-private-labeling-dialog.component.scss'],
})

View File

@ -5,7 +5,7 @@ import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
@Component({
selector: 'app-project-role-detail',
selector: 'cnsl-project-role-detail',
templateUrl: './project-role-detail.component.html',
styleUrls: ['./project-role-detail.component.scss'],
})

View File

@ -1,8 +1,8 @@
<app-refresh-table *ngIf="projectId" (refreshed)="refreshPage()" [dataSize]="dataSource?.totalResult"
<cnsl-refresh-table *ngIf="projectId" (refreshed)="refreshPage()" [dataSize]="dataSource?.totalResult ?? 0"
[emitRefreshOnPreviousRoutes]="['/projects/'+projectId+'/roles/create']" [selection]="selection"
[loading]="dataSource?.loading$ | async" [timestamp]="dataSource?.viewTimestamp">
<ng-template appHasRole [appHasRole]="['project.role.write:' + projectId, 'project.role.write']" actions>
<ng-template cnslHasRole [hasRole]="['project.role.write:' + projectId, 'project.role.write']" actions>
<a *ngIf="actionsVisible" [disabled]="disabled" [routerLink]="[ '/projects', projectId, 'roles', 'create']"
color="primary" mat-raised-button>
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
@ -55,7 +55,7 @@
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let role">
<button
[disabled]="disabled || (['project.role.delete', 'project.role.delete:' + projectId] | hasRole | async) == false"
[disabled]="disabled || (['project.role.delete', 'project.role.delete:' + projectId] | hasRole | async) === false"
mat-icon-button color="warn" matTooltip="{{'ACTIONS.DELETE' | translate}}"
(click)="deleteRole(role)">
<i class="las la-trash"></i>
@ -67,7 +67,7 @@
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<div *ngIf="(dataSource.loading$ | async) == false && !dataSource?.totalResult" class="no-content-row">
<div *ngIf="(dataSource.loading$ | async) === false && !dataSource?.totalResult" class="no-content-row">
<i class="las la-exclamation"></i>
<span>{{'PROJECT.ROLE.EMPTY' | translate}}</span>
</div>
@ -76,4 +76,4 @@
[pageSizeOptions]="[25, 50, 100, 250]">
</cnsl-paginator>
</div>
</app-refresh-table>
</cnsl-refresh-table>

View File

@ -13,7 +13,7 @@ import { ProjectRolesDataSource } from './project-roles-datasource';
@Component({
selector: 'app-project-roles',
selector: 'cnsl-project-roles',
templateUrl: './project-roles.component.html',
styleUrls: ['./project-roles.component.scss'],
})

View File

@ -18,7 +18,7 @@ const rotate = animation([
),
]);
@Component({
selector: 'app-refresh-table',
selector: 'cnsl-refresh-table',
templateUrl: './refresh-table.component.html',
styleUrls: ['./refresh-table.component.scss'],
animations: [
@ -29,10 +29,10 @@ const rotate = animation([
})
export class RefreshTableComponent implements OnInit {
@Input() public selection: SelectionModel<any> = new SelectionModel<any>(true, []);
@Input() public timestamp!: Timestamp.AsObject;
@Input() public timestamp: Timestamp.AsObject | undefined = undefined;
@Input() public dataSize: number = 0;
@Input() public emitRefreshAfterTimeoutInMs: number = 0;
@Input() public loading: boolean = false;
@Input() public loading: boolean | null = false;
@Input() public emitRefreshOnPreviousRoutes: string[] = [];
@Output() public refreshed: EventEmitter<void> = new EventEmitter();
@Input() public hideRefresh: boolean = false;

View File

@ -17,7 +17,7 @@ export enum ProjectAutocompleteType {
}
@Component({
selector: 'app-search-project-autocomplete',
selector: 'cnsl-search-project-autocomplete',
templateUrl: './search-project-autocomplete.component.html',
styleUrls: ['./search-project-autocomplete.component.scss'],
})
@ -95,9 +95,9 @@ export class SearchProjectAutocompleteComponent implements OnDestroy {
this.unsubscribed$.next();
}
public displayFn(project?: any): string | undefined {
public displayFn(project?: any): string {
return (project && project.projectName) ? `${project.projectName}` :
(project && project.name) ? `${project.name}` : undefined;
(project && project.name) ? `${project.name}` : '';
}
public add(event: MatChipInputEvent): void {
@ -111,6 +111,8 @@ export class SearchProjectAutocompleteComponent implements OnDestroy {
return project.projectName === value;
} else if (project?.name) {
return project.name === value;
} else {
return false;
}
});
if (index > -1) {

Some files were not shown because too many files have changed in this diff Show More