mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 23:17:23 +00:00
fix(console): better error messages (#5409)
* fix(console): better error messages * fix: fix i18n error labels * rollout cnsl-i18n-errors * move errors to form-field * fix: form control errors * rollout validators * translate * replace variables * lint * self review * fix confirm validation * use help observable * fix validation errors * cleanup * custom validator for idp templates * lint * validate on blur * remove element --------- Co-authored-by: Max Peintner <max@caos.ch>
This commit is contained in:
parent
e00cc187fa
commit
93e1fe0056
@ -83,4 +83,4 @@
|
|||||||
"protractor": "~7.0.0",
|
"protractor": "~7.0.0",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
<div class="cnsl-form-field-wrapper" (click)="_control.onContainerClick && _control.onContainerClick($event)">
|
||||||
|
<ng-content select="cnsl-label"></ng-content>
|
||||||
|
<div class="cnsl-rel" #inputContainer>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
<ng-content select="cnslSuffix"></ng-content>
|
||||||
|
</div>
|
||||||
|
<ng-container *ngIf="help$ && help$ | async as help">
|
||||||
|
<div [ngSwitch]="help.type" class="cnsl-form-field-subscript-wrapper">
|
||||||
|
<div *ngSwitchCase="'hints'" class="cnsl-form-field-hint-wrapper" [@transitionMessages]="_subscriptAnimationState">
|
||||||
|
<ng-content select="cnsl-hint"></ng-content>
|
||||||
|
</div>
|
||||||
|
<div *ngSwitchCase="'errors'" class="cnsl-form-field-error-wrapper" [@transitionMessages]="_subscriptAnimationState">
|
||||||
|
<span cnslError *ngFor="let err of help.validationErrors">
|
||||||
|
{{ err.i18nKey | translate : err.params }}
|
||||||
|
</span>
|
||||||
|
<ng-content select="cnsl-error"></ng-content>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
@ -10,6 +10,7 @@ import {
|
|||||||
HostListener,
|
HostListener,
|
||||||
Inject,
|
Inject,
|
||||||
InjectionToken,
|
InjectionToken,
|
||||||
|
Input,
|
||||||
OnDestroy,
|
OnDestroy,
|
||||||
QueryList,
|
QueryList,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
@ -17,11 +18,10 @@ import {
|
|||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { NgControl } from '@angular/forms';
|
import { NgControl } from '@angular/forms';
|
||||||
import { MatLegacyFormFieldControl as MatFormFieldControl } from '@angular/material/legacy-form-field';
|
import { MatLegacyFormFieldControl as MatFormFieldControl } from '@angular/material/legacy-form-field';
|
||||||
import { Subject } from 'rxjs';
|
import { combineLatest, map, Observable, of, startWith, Subject, takeUntil } from 'rxjs';
|
||||||
import { startWith, takeUntil } from 'rxjs/operators';
|
|
||||||
|
|
||||||
|
import { CnslErrorDirective, CNSL_ERROR } from '../error/error.directive';
|
||||||
import { cnslFormFieldAnimations } from './animations';
|
import { cnslFormFieldAnimations } from './animations';
|
||||||
import { CnslErrorDirective, CNSL_ERROR } from './error.directive';
|
|
||||||
|
|
||||||
export const CNSL_FORM_FIELD = new InjectionToken<CnslFormFieldComponent>('CnslFormFieldComponent');
|
export const CNSL_FORM_FIELD = new InjectionToken<CnslFormFieldComponent>('CnslFormFieldComponent');
|
||||||
|
|
||||||
@ -29,6 +29,15 @@ class CnslFormFieldBase {
|
|||||||
constructor(public _elementRef: ElementRef) {}
|
constructor(public _elementRef: ElementRef) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Help {
|
||||||
|
type: 'hints' | 'errors';
|
||||||
|
validationErrors?: Array<ValidationError>;
|
||||||
|
}
|
||||||
|
interface ValidationError {
|
||||||
|
i18nKey: string;
|
||||||
|
params: any;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cnsl-form-field',
|
selector: 'cnsl-form-field',
|
||||||
templateUrl: './form-field.component.html',
|
templateUrl: './form-field.component.html',
|
||||||
@ -59,19 +68,24 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
|
|||||||
@ViewChild('inputContainer') _inputContainerRef!: ElementRef;
|
@ViewChild('inputContainer') _inputContainerRef!: ElementRef;
|
||||||
@ContentChild(MatFormFieldControl) _controlNonStatic!: MatFormFieldControl<any>;
|
@ContentChild(MatFormFieldControl) _controlNonStatic!: MatFormFieldControl<any>;
|
||||||
@ContentChild(MatFormFieldControl, { static: true }) _controlStatic!: MatFormFieldControl<any>;
|
@ContentChild(MatFormFieldControl, { static: true }) _controlStatic!: MatFormFieldControl<any>;
|
||||||
|
@Input() public disableValidationErrors = false;
|
||||||
|
|
||||||
get _control(): MatFormFieldControl<any> {
|
get _control(): MatFormFieldControl<any> {
|
||||||
return this._explicitFormFieldControl || this._controlNonStatic || this._controlStatic;
|
return this._explicitFormFieldControl || this._controlNonStatic || this._controlStatic;
|
||||||
}
|
}
|
||||||
set _control(value: MatFormFieldControl<any>) {
|
set _control(value: MatFormFieldControl<any>) {
|
||||||
this._explicitFormFieldControl = value;
|
this._explicitFormFieldControl = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _explicitFormFieldControl!: MatFormFieldControl<any>;
|
private _explicitFormFieldControl!: MatFormFieldControl<any>;
|
||||||
readonly stateChanges: Subject<void> = new Subject<void>();
|
readonly stateChanges: Subject<void> = new Subject<void>();
|
||||||
|
public help$?: Observable<Help>;
|
||||||
|
|
||||||
_subscriptAnimationState: string = '';
|
_subscriptAnimationState: string = '';
|
||||||
|
|
||||||
@ContentChildren(CNSL_ERROR as any, { descendants: true }) _errorChildren!: QueryList<CnslErrorDirective>;
|
@ContentChildren(CNSL_ERROR as any, { descendants: true }) _errorChildren!: QueryList<CnslErrorDirective>;
|
||||||
|
|
||||||
|
// TODO: Remove?
|
||||||
@HostListener('blur', ['false'])
|
@HostListener('blur', ['false'])
|
||||||
_focusChanged(isFocused: boolean): void {
|
_focusChanged(isFocused: boolean): void {
|
||||||
if (isFocused !== this.focused && !isFocused) {
|
if (isFocused !== this.focused && !isFocused) {
|
||||||
@ -91,8 +105,6 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ngAfterViewInit(): void {
|
public ngAfterViewInit(): void {
|
||||||
// Avoid animations on load.
|
|
||||||
this._subscriptAnimationState = 'enter';
|
|
||||||
this._changeDetectorRef.detectChanges();
|
this._changeDetectorRef.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,25 +115,21 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
|
|||||||
|
|
||||||
public ngAfterContentInit(): void {
|
public ngAfterContentInit(): void {
|
||||||
this._validateControlChild();
|
this._validateControlChild();
|
||||||
|
this.mapHelp();
|
||||||
|
|
||||||
const control = this._control;
|
const control = this._control;
|
||||||
control.stateChanges.pipe(startWith(null)).subscribe(() => {
|
control.stateChanges.pipe(startWith(null), takeUntil(this._destroyed)).subscribe(() => {
|
||||||
this._syncDescribedByIds();
|
this._syncDescribedByIds();
|
||||||
this._changeDetectorRef.markForCheck();
|
this._changeDetectorRef.markForCheck();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Run change detection if the value changes.
|
// Run change detection if the value changes.
|
||||||
|
// TODO: Is that not redundant (see immediately above)?
|
||||||
if (control.ngControl && control.ngControl.valueChanges) {
|
if (control.ngControl && control.ngControl.valueChanges) {
|
||||||
control.ngControl.valueChanges
|
control.ngControl.valueChanges
|
||||||
.pipe(takeUntil(this._destroyed))
|
.pipe(takeUntil(this._destroyed))
|
||||||
.subscribe(() => this._changeDetectorRef.markForCheck());
|
.subscribe(() => this._changeDetectorRef.markForCheck());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the aria-described by when the number of errors changes.
|
|
||||||
this._errorChildren.changes.pipe(startWith(null)).subscribe(() => {
|
|
||||||
this._syncDescribedByIds();
|
|
||||||
this._changeDetectorRef.markForCheck();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Throws an error if the form field's control is missing. */
|
/** Throws an error if the form field's control is missing. */
|
||||||
@ -147,14 +155,68 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private mapHelp(): void {
|
||||||
|
const validationErrors$: Observable<Array<ValidationError>> = this.disableValidationErrors
|
||||||
|
? of([])
|
||||||
|
: this._control.stateChanges?.pipe(
|
||||||
|
map(() => this.currentValidationErrors()),
|
||||||
|
startWith([]),
|
||||||
|
) || of([]);
|
||||||
|
|
||||||
|
const childrenErrors$: Observable<boolean> = this._errorChildren.changes.pipe(
|
||||||
|
map(() => {
|
||||||
|
return this._errorChildren.length > 0;
|
||||||
|
}),
|
||||||
|
startWith(false),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.help$ = combineLatest([validationErrors$, childrenErrors$]).pipe(
|
||||||
|
map((combined) => {
|
||||||
|
return combined[0].length >= 1
|
||||||
|
? <Help>{
|
||||||
|
type: 'errors',
|
||||||
|
validationErrors: combined[0],
|
||||||
|
}
|
||||||
|
: combined[1]
|
||||||
|
? <Help>{
|
||||||
|
type: 'errors',
|
||||||
|
}
|
||||||
|
: <Help>{
|
||||||
|
type: 'hints',
|
||||||
|
validationErrors: undefined,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
this._changeDetectorRef.markForCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
private currentValidationErrors(): Array<ValidationError> {
|
||||||
|
return (
|
||||||
|
Object.entries(this._control.ngControl?.control?.errors || [])
|
||||||
|
?.filter(this.filterErrorsProperties)
|
||||||
|
.map(this.mapToValidationError)
|
||||||
|
.filter(this.distinctFilter) || []
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private filterErrorsProperties(kv: [string, any]): boolean {
|
||||||
|
return typeof kv[1] == 'object' && (kv[1] as { valid: boolean }).valid === false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private mapToValidationError(kv: [string, any]): ValidationError {
|
||||||
|
return {
|
||||||
|
i18nKey: 'ERRORS.INVALID_FORMAT',
|
||||||
|
...(kv[1] as ValidationError | any),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private distinctFilter(_: ValidationError, index: number, arr: Array<ValidationError>): boolean {
|
||||||
|
return arr.findIndex((item) => item.i18nKey) === index;
|
||||||
|
}
|
||||||
|
|
||||||
/** Determines whether a class from the NgControl should be forwarded to the host element. */
|
/** Determines whether a class from the NgControl should be forwarded to the host element. */
|
||||||
_shouldForward(prop: keyof NgControl): boolean {
|
_shouldForward(prop: keyof NgControl): boolean {
|
||||||
const ngControl: any = this._control ? this._control.ngControl : null;
|
const ngControl: any = this._control ? this._control.ngControl : null;
|
||||||
return ngControl && ngControl[prop];
|
return ngControl && ngControl[prop];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Determines whether to display hints or errors. */
|
|
||||||
_getDisplayedMessages(): 'error' | 'hint' {
|
|
||||||
return this._errorChildren && this._errorChildren.length > 0 ? 'error' : 'hint';
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,15 +0,0 @@
|
|||||||
<div class="cnsl-form-field-wrapper" (click)="_control.onContainerClick && _control.onContainerClick($event)">
|
|
||||||
<ng-content select="cnsl-label"></ng-content>
|
|
||||||
<div class="cnsl-rel" #inputContainer>
|
|
||||||
<ng-content></ng-content>
|
|
||||||
<ng-content select="cnslSuffix"></ng-content>
|
|
||||||
</div>
|
|
||||||
<div class="cnsl-form-field-subscript-wrapper" [ngSwitch]="_getDisplayedMessages()">
|
|
||||||
<div *ngSwitchCase="'error'" class="cnsl-form-field-error-wrapper" [@transitionMessages]="_subscriptAnimationState">
|
|
||||||
<ng-content select="cnsl-error"></ng-content>
|
|
||||||
</div>
|
|
||||||
<div *ngSwitchCase="'hint'" class="cnsl-form-field-hint-wrapper" [@transitionMessages]="_subscriptAnimationState">
|
|
||||||
<ng-content select="cnsl-hint"></ng-content>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,15 +1,16 @@
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { MatRippleModule } from '@angular/material/core';
|
import { MatRippleModule } from '@angular/material/core';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { LabelModule } from 'src/app/modules/label/label.module';
|
import { LabelModule } from 'src/app/modules/label/label.module';
|
||||||
|
|
||||||
import { LabelComponent } from '../label/label.component';
|
import { LabelComponent } from '../label/label.component';
|
||||||
import { CnslErrorDirective } from './error.directive';
|
import { CnslErrorDirective } from './error/error.directive';
|
||||||
import { CnslFormFieldComponent } from './form-field.component';
|
import { CnslFormFieldComponent } from './field/form-field.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [CnslFormFieldComponent, CnslErrorDirective],
|
declarations: [CnslFormFieldComponent, CnslErrorDirective],
|
||||||
imports: [CommonModule, MatRippleModule, LabelModule],
|
imports: [CommonModule, MatRippleModule, LabelModule, TranslateModule],
|
||||||
exports: [CnslFormFieldComponent, LabelComponent, CnslErrorDirective],
|
exports: [CnslFormFieldComponent, LabelComponent, CnslErrorDirective],
|
||||||
})
|
})
|
||||||
export class FormFieldModule {}
|
export class FormFieldModule {}
|
||||||
|
73
console/src/app/modules/form-field/validators/validators.ts
Normal file
73
console/src/app/modules/form-field/validators/validators.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { AbstractControl, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
export function containsSymbolValidator(c: AbstractControl): ValidationErrors | null {
|
||||||
|
return regexpValidator(c, /[^a-z0-9]/gi, 'ERRORS.SYMBOLERROR');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function containsNumberValidator(c: AbstractControl): ValidationErrors | null {
|
||||||
|
return regexpValidator(c, /[0-9]/g, 'ERRORS.NUMBERERROR');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function containsUpperCaseValidator(c: AbstractControl): ValidationErrors | null {
|
||||||
|
return regexpValidator(c, /[A-Z]/g, 'ERRORS.UPPERCASEMISSING');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function containsLowerCaseValidator(c: AbstractControl): ValidationErrors | null {
|
||||||
|
return regexpValidator(c, /[a-z]/g, 'ERRORS.LOWERCASEMISSING');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function phoneValidator(c: AbstractControl): ValidationErrors | null {
|
||||||
|
return regexpValidator(c, /^($|(\+|00)[0-9 ]+$)/, 'ERRORS.PHONE');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function requiredValidator(c: AbstractControl): ValidationErrors | null {
|
||||||
|
return i18nErr(Validators.required(c), 'ERRORS.REQUIRED');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function emailValidator(c: AbstractControl): ValidationErrors | null {
|
||||||
|
return i18nErr(Validators.email(c), 'ERRORS.NOTANEMAIL');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function minLengthValidator(minLength: number): ValidatorFn {
|
||||||
|
return (c: AbstractControl): ValidationErrors | null => {
|
||||||
|
return i18nErr(Validators.minLength(minLength)(c), 'ERRORS.MINLENGTH', { requiredLength: minLength });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function passwordConfirmValidator(passwordControlName: string = 'password') {
|
||||||
|
return (c: AbstractControl): ValidationErrors | null => {
|
||||||
|
if (!c.parent || !c) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const pwd = c.parent.get(passwordControlName);
|
||||||
|
const cpwd = c;
|
||||||
|
|
||||||
|
if (!pwd || !cpwd) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (pwd.value !== cpwd.value) {
|
||||||
|
return i18nErr(undefined, 'ERRORS.PWNOTEQUAL');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function regexpValidator(c: AbstractControl, regexp: RegExp, i18nKey: string): ValidationErrors | null {
|
||||||
|
return !c.value || regexp.test(c.value) ? null : i18nErr({ invalid: true }, i18nKey, { regexp: regexp });
|
||||||
|
}
|
||||||
|
|
||||||
|
function i18nErr(err: ValidationErrors | null | undefined, i18nKey: string, params?: any): ValidationErrors | null {
|
||||||
|
if (err === null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
...err,
|
||||||
|
invalid: true,
|
||||||
|
[i18nKey.toLowerCase().replaceAll('.', '')]: {
|
||||||
|
valid: false,
|
||||||
|
i18nKey: i18nKey,
|
||||||
|
params: params,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -28,23 +28,23 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="val" *ngIf="this.policy.hasSymbol">
|
<div class="val" *ngIf="this.policy.hasSymbol">
|
||||||
<i *ngIf="password?.errors?.symbolValidator" class="las la-times red"></i>
|
<i *ngIf="password?.pristine || password?.errors?.errorssymbolerror" class="las la-times red"></i>
|
||||||
<i *ngIf="!password?.errors?.symbolValidator" class="las la-check green"></i>
|
<i *ngIf="password?.dirty && !password?.errors?.errorssymbolerror" class="las la-check green"></i>
|
||||||
<span class="cnsl-secondary-text"> {{ 'USER.VALIDATION.SYMBOLERROR' | translate }}</span>
|
<span class="cnsl-secondary-text"> {{ 'ERRORS.SYMBOLERROR' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="val" *ngIf="this.policy.hasNumber">
|
<div class="val" *ngIf="this.policy.hasNumber">
|
||||||
<i *ngIf="password?.errors?.numberValidator" class="las la-times red"></i>
|
<i *ngIf="password?.pristine || password?.errors?.errorsnumbererror" class="las la-times red"></i>
|
||||||
<i *ngIf="!password?.errors?.numberValidator" class="las la-check green"></i>
|
<i *ngIf="password?.dirty && !password?.errors?.errorsnumbererror" class="las la-check green"></i>
|
||||||
<span class="cnsl-secondary-text"> {{ 'USER.VALIDATION.NUMBERERROR' | translate }}</span>
|
<span class="cnsl-secondary-text"> {{ 'ERRORS.NUMBERERROR' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="val" *ngIf="this.policy.hasUppercase">
|
<div class="val" *ngIf="this.policy.hasUppercase">
|
||||||
<i *ngIf="password?.errors?.upperCaseValidator" class="las la-times red"></i>
|
<i *ngIf="password?.pristine || password?.errors?.errorsuppercasemissing" class="las la-times red"></i>
|
||||||
<i *ngIf="!password?.errors?.upperCaseValidator" class="las la-check green"></i>
|
<i *ngIf="password?.dirty && !password?.errors?.errorsuppercasemissing" class="las la-check green"></i>
|
||||||
<span class="cnsl-secondary-text"> {{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}</span>
|
<span class="cnsl-secondary-text"> {{ 'ERRORS.UPPERCASEMISSING' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="val" *ngIf="this.policy.hasLowercase">
|
<div class="val" *ngIf="this.policy.hasLowercase">
|
||||||
<i *ngIf="password?.errors?.lowerCaseValidator" class="las la-times red"></i>
|
<i *ngIf="password?.pristine || password?.errors?.errorslowercasemissing" class="las la-times red"></i>
|
||||||
<i *ngIf="!password?.errors?.lowerCaseValidator" class="las la-check green"></i>
|
<i *ngIf="password?.dirty && !password?.errors?.errorslowercasemissing" class="las la-check green"></i>
|
||||||
<span class="cnsl-secondary-text">{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}</span>
|
<span class="cnsl-secondary-text">{{ 'ERRORS.LOWERCASEMISSING' | translate }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, Injector, Input, OnInit, Type } from '@angular/core';
|
import { Component, Injector, Input, OnInit, Type } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||||
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
||||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||||
import { take } from 'rxjs';
|
import { take } from 'rxjs';
|
||||||
@ -18,6 +18,7 @@ import { AdminService } from 'src/app/services/admin.service';
|
|||||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
import { requiredValidator } from '../../form-field/validators/validators';
|
||||||
|
|
||||||
import { InfoSectionType } from '../../info-section/info-section.component';
|
import { InfoSectionType } from '../../info-section/info-section.component';
|
||||||
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
||||||
@ -45,11 +46,11 @@ export class LoginPolicyComponent implements OnInit {
|
|||||||
public InfoSectionType: any = InfoSectionType;
|
public InfoSectionType: any = InfoSectionType;
|
||||||
public PasswordlessType: any = PasswordlessType;
|
public PasswordlessType: any = PasswordlessType;
|
||||||
public lifetimeForm: UntypedFormGroup = this.fb.group({
|
public lifetimeForm: UntypedFormGroup = this.fb.group({
|
||||||
passwordCheckLifetime: [{ disabled: true }, [Validators.required]],
|
passwordCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||||
externalLoginCheckLifetime: [{ disabled: true }, [Validators.required]],
|
externalLoginCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||||
mfaInitSkipLifetime: [{ disabled: true }, [Validators.required]],
|
mfaInitSkipLifetime: [{ disabled: true }, [requiredValidator]],
|
||||||
secondFactorCheckLifetime: [{ disabled: true }, [Validators.required]],
|
secondFactorCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||||
multiFactorCheckLifetime: [{ disabled: true }, [Validators.required]],
|
multiFactorCheckLifetime: [{ disabled: true }, [requiredValidator]],
|
||||||
});
|
});
|
||||||
constructor(
|
constructor(
|
||||||
private toast: ToastService,
|
private toast: ToastService,
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||||
import {
|
import {
|
||||||
MatLegacyDialog as MatDialog,
|
MatLegacyDialog as MatDialog,
|
||||||
MatLegacyDialogRef as MatDialogRef,
|
MatLegacyDialogRef as MatDialogRef,
|
||||||
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
||||||
} from '@angular/material/legacy-dialog';
|
} from '@angular/material/legacy-dialog';
|
||||||
|
import { requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||||
import {
|
import {
|
||||||
AddSMSProviderTwilioRequest,
|
AddSMSProviderTwilioRequest,
|
||||||
UpdateSMSProviderTwilioRequest,
|
UpdateSMSProviderTwilioRequest,
|
||||||
@ -44,15 +45,15 @@ export class DialogAddSMSProviderComponent {
|
|||||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||||
) {
|
) {
|
||||||
this.twilioForm = this.fb.group({
|
this.twilioForm = this.fb.group({
|
||||||
sid: ['', [Validators.required]],
|
sid: ['', [requiredValidator]],
|
||||||
senderNumber: ['', [Validators.required]],
|
senderNumber: ['', [requiredValidator]],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.smsProviders = data.smsProviders;
|
this.smsProviders = data.smsProviders;
|
||||||
if (!!this.twilio) {
|
if (!!this.twilio) {
|
||||||
this.twilioForm.patchValue(this.twilio);
|
this.twilioForm.patchValue(this.twilio);
|
||||||
} else {
|
} else {
|
||||||
this.twilioForm.addControl('token', new FormControl('', Validators.required));
|
this.twilioForm.addControl('token', new FormControl('', requiredValidator));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||||
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
||||||
import { take } from 'rxjs';
|
import { take } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
@ -15,6 +15,7 @@ import { DebugNotificationProvider, SMSProvider, SMSProviderConfigState } from '
|
|||||||
import { AdminService } from 'src/app/services/admin.service';
|
import { AdminService } from 'src/app/services/admin.service';
|
||||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
import { requiredValidator } from '../../form-field/validators/validators';
|
||||||
|
|
||||||
import { InfoSectionType } from '../../info-section/info-section.component';
|
import { InfoSectionType } from '../../info-section/info-section.component';
|
||||||
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
|
||||||
@ -55,11 +56,11 @@ export class NotificationSettingsComponent implements OnInit {
|
|||||||
private authService: GrpcAuthService,
|
private authService: GrpcAuthService,
|
||||||
) {
|
) {
|
||||||
this.form = this.fb.group({
|
this.form = this.fb.group({
|
||||||
senderAddress: [{ disabled: true, value: '' }, [Validators.required]],
|
senderAddress: [{ disabled: true, value: '' }, [requiredValidator]],
|
||||||
senderName: [{ disabled: true, value: '' }, [Validators.required]],
|
senderName: [{ disabled: true, value: '' }, [requiredValidator]],
|
||||||
tls: [{ disabled: true, value: true }, [Validators.required]],
|
tls: [{ disabled: true, value: true }, [requiredValidator]],
|
||||||
hostAndPort: [{ disabled: true, value: '' }, [Validators.required]],
|
hostAndPort: [{ disabled: true, value: '' }, [requiredValidator]],
|
||||||
user: [{ disabled: true, value: '' }, [Validators.required]],
|
user: [{ disabled: true, value: '' }, [requiredValidator]],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||||
import { take } from 'rxjs';
|
import { take } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
@ -12,6 +12,7 @@ import { OIDCSettings } from 'src/app/proto/generated/zitadel/settings_pb';
|
|||||||
import { AdminService } from 'src/app/services/admin.service';
|
import { AdminService } from 'src/app/services/admin.service';
|
||||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
import { requiredValidator } from '../../form-field/validators/validators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cnsl-oidc-configuration',
|
selector: 'cnsl-oidc-configuration',
|
||||||
@ -31,10 +32,10 @@ export class OIDCConfigurationComponent implements OnInit {
|
|||||||
private authService: GrpcAuthService,
|
private authService: GrpcAuthService,
|
||||||
) {
|
) {
|
||||||
this.form = this.fb.group({
|
this.form = this.fb.group({
|
||||||
accessTokenLifetime: [{ disabled: true }, [Validators.required]],
|
accessTokenLifetime: [{ disabled: true }, [requiredValidator]],
|
||||||
idTokenLifetime: [{ disabled: true }, [Validators.required]],
|
idTokenLifetime: [{ disabled: true }, [requiredValidator]],
|
||||||
refreshTokenExpiration: [{ disabled: true }, [Validators.required]],
|
refreshTokenExpiration: [{ disabled: true }, [requiredValidator]],
|
||||||
refreshTokenIdleExpiration: [{ disabled: true }, [Validators.required]],
|
refreshTokenIdleExpiration: [{ disabled: true }, [requiredValidator]],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||||
import {
|
import {
|
||||||
MatLegacyDialogRef as MatDialogRef,
|
MatLegacyDialogRef as MatDialogRef,
|
||||||
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
||||||
} from '@angular/material/legacy-dialog';
|
} from '@angular/material/legacy-dialog';
|
||||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||||
|
import { requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||||
import { UpdateSecretGeneratorRequest } from 'src/app/proto/generated/zitadel/admin_pb';
|
import { UpdateSecretGeneratorRequest } from 'src/app/proto/generated/zitadel/admin_pb';
|
||||||
import { SecretGeneratorType } from 'src/app/proto/generated/zitadel/settings_pb';
|
import { SecretGeneratorType } from 'src/app/proto/generated/zitadel/settings_pb';
|
||||||
|
|
||||||
@ -33,13 +34,13 @@ export class DialogAddSecretGeneratorComponent {
|
|||||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||||
) {
|
) {
|
||||||
this.specsForm = this.fb.group({
|
this.specsForm = this.fb.group({
|
||||||
generatorType: [SecretGeneratorType.SECRET_GENERATOR_TYPE_APP_SECRET, [Validators.required]],
|
generatorType: [SecretGeneratorType.SECRET_GENERATOR_TYPE_APP_SECRET, [requiredValidator]],
|
||||||
expiry: [1, [Validators.required]],
|
expiry: [1, [requiredValidator]],
|
||||||
includeDigits: [true, [Validators.required]],
|
includeDigits: [true, [requiredValidator]],
|
||||||
includeLowerLetters: [true, [Validators.required]],
|
includeLowerLetters: [true, [requiredValidator]],
|
||||||
includeSymbols: [true, [Validators.required]],
|
includeSymbols: [true, [requiredValidator]],
|
||||||
includeUpperLetters: [true, [Validators.required]],
|
includeUpperLetters: [true, [requiredValidator]],
|
||||||
length: [6, [Validators.required]],
|
length: [6, [requiredValidator]],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.generatorType?.setValue(data.type);
|
this.generatorType?.setValue(data.type);
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||||
import {
|
import {
|
||||||
MatLegacyDialogRef as MatDialogRef,
|
MatLegacyDialogRef as MatDialogRef,
|
||||||
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
||||||
} from '@angular/material/legacy-dialog';
|
} from '@angular/material/legacy-dialog';
|
||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
import { requiredValidator } from '../form-field/validators/validators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cnsl-project-role-detail-dialog',
|
selector: 'cnsl-project-role-detail-dialog',
|
||||||
@ -24,7 +25,7 @@ export class ProjectRoleDetailDialogComponent {
|
|||||||
) {
|
) {
|
||||||
this.projectId = data.projectId;
|
this.projectId = data.projectId;
|
||||||
this.formGroup = new UntypedFormGroup({
|
this.formGroup = new UntypedFormGroup({
|
||||||
key: new UntypedFormControl({ value: '', disabled: true }, [Validators.required]),
|
key: new UntypedFormControl({ value: '', disabled: true }, [requiredValidator]),
|
||||||
displayName: new UntypedFormControl(''),
|
displayName: new UntypedFormControl(''),
|
||||||
group: new UntypedFormControl(''),
|
group: new UntypedFormControl(''),
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, Injector, Type } from '@angular/core';
|
import { Component, Injector, Type } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||||
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { take } from 'rxjs';
|
import { take } from 'rxjs';
|
||||||
@ -20,6 +20,7 @@ import { AdminService } from 'src/app/services/admin.service';
|
|||||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
import { requiredValidator } from '../../form-field/validators/validators';
|
||||||
|
|
||||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||||
|
|
||||||
@ -51,12 +52,12 @@ export class ProviderGithubESComponent {
|
|||||||
breadcrumbService: BreadcrumbService,
|
breadcrumbService: BreadcrumbService,
|
||||||
) {
|
) {
|
||||||
this.form = new UntypedFormGroup({
|
this.form = new UntypedFormGroup({
|
||||||
name: new UntypedFormControl('', [Validators.required]),
|
name: new UntypedFormControl('', [requiredValidator]),
|
||||||
clientId: new UntypedFormControl('', [Validators.required]),
|
clientId: new UntypedFormControl('', [requiredValidator]),
|
||||||
clientSecret: new UntypedFormControl('', [Validators.required]),
|
clientSecret: new UntypedFormControl('', [requiredValidator]),
|
||||||
authorizationEndpoint: new UntypedFormControl('', [Validators.required]),
|
authorizationEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||||
tokenEndpoint: new UntypedFormControl('', [Validators.required]),
|
tokenEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||||
userEndpoint: new UntypedFormControl('', [Validators.required]),
|
userEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||||
scopesList: new UntypedFormControl(['openid', 'profile', 'email'], []),
|
scopesList: new UntypedFormControl(['openid', 'profile', 'email'], []),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, Injector, Type } from '@angular/core';
|
import { Component, Injector, Type } from '@angular/core';
|
||||||
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
|
||||||
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { take } from 'rxjs';
|
import { take } from 'rxjs';
|
||||||
@ -20,6 +20,7 @@ import { AdminService } from 'src/app/services/admin.service';
|
|||||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
import { requiredValidator } from '../../form-field/validators/validators';
|
||||||
|
|
||||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||||
|
|
||||||
@ -53,8 +54,8 @@ export class ProviderGithubComponent {
|
|||||||
) {
|
) {
|
||||||
this.form = new FormGroup({
|
this.form = new FormGroup({
|
||||||
name: new FormControl('', []),
|
name: new FormControl('', []),
|
||||||
clientId: new FormControl('', [Validators.required]),
|
clientId: new FormControl('', [requiredValidator]),
|
||||||
clientSecret: new FormControl('', [Validators.required]),
|
clientSecret: new FormControl('', [requiredValidator]),
|
||||||
scopesList: new FormControl(['openid', 'profile', 'email'], []),
|
scopesList: new FormControl(['openid', 'profile', 'email'], []),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, Injector, Type } from '@angular/core';
|
import { Component, Injector, Type } from '@angular/core';
|
||||||
import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
|
||||||
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { take } from 'rxjs';
|
import { take } from 'rxjs';
|
||||||
@ -20,6 +20,7 @@ import { AdminService } from 'src/app/services/admin.service';
|
|||||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
import { requiredValidator } from '../../form-field/validators/validators';
|
||||||
|
|
||||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||||
|
|
||||||
@ -53,8 +54,8 @@ export class ProviderGoogleComponent {
|
|||||||
) {
|
) {
|
||||||
this.form = new FormGroup({
|
this.form = new FormGroup({
|
||||||
name: new FormControl('', []),
|
name: new FormControl('', []),
|
||||||
clientId: new FormControl('', [Validators.required]),
|
clientId: new FormControl('', [requiredValidator]),
|
||||||
clientSecret: new FormControl('', [Validators.required]),
|
clientSecret: new FormControl('', [requiredValidator]),
|
||||||
scopesList: new FormControl(['openid', 'profile', 'email'], []),
|
scopesList: new FormControl(['openid', 'profile', 'email'], []),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, Injector, Type } from '@angular/core';
|
import { Component, Injector, Type } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
import {
|
import {
|
||||||
@ -19,6 +19,7 @@ import { AdminService } from 'src/app/services/admin.service';
|
|||||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
import { requiredValidator } from '../../form-field/validators/validators';
|
||||||
|
|
||||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||||
|
|
||||||
@ -82,11 +83,11 @@ export class ProviderJWTComponent {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.form = new UntypedFormGroup({
|
this.form = new UntypedFormGroup({
|
||||||
name: new UntypedFormControl('', [Validators.required]),
|
name: new UntypedFormControl('', [requiredValidator]),
|
||||||
headerName: new UntypedFormControl('', [Validators.required]),
|
headerName: new UntypedFormControl('', [requiredValidator]),
|
||||||
issuer: new UntypedFormControl('', [Validators.required]),
|
issuer: new UntypedFormControl('', [requiredValidator]),
|
||||||
jwtEndpoint: new UntypedFormControl('', [Validators.required]),
|
jwtEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||||
keysEndpoint: new UntypedFormControl('', [Validators.required]),
|
keysEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, Injector, Type } from '@angular/core';
|
import { Component, Injector, Type } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||||
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { take } from 'rxjs';
|
import { take } from 'rxjs';
|
||||||
@ -20,6 +20,7 @@ import { AdminService } from 'src/app/services/admin.service';
|
|||||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
import { requiredValidator } from '../../form-field/validators/validators';
|
||||||
|
|
||||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||||
|
|
||||||
@ -52,13 +53,13 @@ export class ProviderOAuthComponent {
|
|||||||
breadcrumbService: BreadcrumbService,
|
breadcrumbService: BreadcrumbService,
|
||||||
) {
|
) {
|
||||||
this.form = new UntypedFormGroup({
|
this.form = new UntypedFormGroup({
|
||||||
name: new UntypedFormControl('', [Validators.required]),
|
name: new UntypedFormControl('', [requiredValidator]),
|
||||||
clientId: new UntypedFormControl('', [Validators.required]),
|
clientId: new UntypedFormControl('', [requiredValidator]),
|
||||||
clientSecret: new UntypedFormControl('', [Validators.required]),
|
clientSecret: new UntypedFormControl('', [requiredValidator]),
|
||||||
authorizationEndpoint: new UntypedFormControl('', [Validators.required]),
|
authorizationEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||||
tokenEndpoint: new UntypedFormControl('', [Validators.required]),
|
tokenEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||||
userEndpoint: new UntypedFormControl('', [Validators.required]),
|
userEndpoint: new UntypedFormControl('', [requiredValidator]),
|
||||||
idAttribute: new UntypedFormControl('', [Validators.required]),
|
idAttribute: new UntypedFormControl('', [requiredValidator]),
|
||||||
scopesList: new UntypedFormControl(['openid', 'profile', 'email'], []),
|
scopesList: new UntypedFormControl(['openid', 'profile', 'email'], []),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, Injector, Type } from '@angular/core';
|
import { Component, Injector, Type } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||||
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
import { MatLegacyChipInputEvent as MatChipInputEvent } from '@angular/material/legacy-chips';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { take } from 'rxjs';
|
import { take } from 'rxjs';
|
||||||
@ -20,6 +20,7 @@ import { AdminService } from 'src/app/services/admin.service';
|
|||||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
import { requiredValidator } from '../../form-field/validators/validators';
|
||||||
|
|
||||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||||
|
|
||||||
@ -51,10 +52,10 @@ export class ProviderOIDCComponent {
|
|||||||
breadcrumbService: BreadcrumbService,
|
breadcrumbService: BreadcrumbService,
|
||||||
) {
|
) {
|
||||||
this.oidcFormGroup = new UntypedFormGroup({
|
this.oidcFormGroup = new UntypedFormGroup({
|
||||||
name: new UntypedFormControl('', [Validators.required]),
|
name: new UntypedFormControl('', [requiredValidator]),
|
||||||
clientId: new UntypedFormControl('', [Validators.required]),
|
clientId: new UntypedFormControl('', [requiredValidator]),
|
||||||
clientSecret: new UntypedFormControl('', [Validators.required]),
|
clientSecret: new UntypedFormControl('', [requiredValidator]),
|
||||||
issuer: new UntypedFormControl('', [Validators.required]),
|
issuer: new UntypedFormControl('', [requiredValidator]),
|
||||||
scopesList: new UntypedFormControl(['openid', 'profile', 'email'], []),
|
scopesList: new UntypedFormControl(['openid', 'profile', 'email'], []),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||||
import {
|
import {
|
||||||
MatLegacyDialogRef as MatDialogRef,
|
MatLegacyDialogRef as MatDialogRef,
|
||||||
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
||||||
} from '@angular/material/legacy-dialog';
|
} from '@angular/material/legacy-dialog';
|
||||||
|
import { requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||||
import { Action, FlowType, TriggerType } from 'src/app/proto/generated/zitadel/action_pb';
|
import { Action, FlowType, TriggerType } from 'src/app/proto/generated/zitadel/action_pb';
|
||||||
import { SetTriggerActionsRequest } from 'src/app/proto/generated/zitadel/management_pb';
|
import { SetTriggerActionsRequest } from 'src/app/proto/generated/zitadel/management_pb';
|
||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
@ -34,8 +35,8 @@ export class AddFlowDialogComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.form = this.fb.group({
|
this.form = this.fb.group({
|
||||||
triggerType: [data.triggerType ? data.triggerType : '', [Validators.required]],
|
triggerType: [data.triggerType ? data.triggerType : '', [requiredValidator]],
|
||||||
actionIdsList: [data.actions ? (data.actions as Action.AsObject[]).map((a) => a.id) : [], [Validators.required]],
|
actionIdsList: [data.actions ? (data.actions as Action.AsObject[]).map((a) => a.id) : [], [requiredValidator]],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getActionIds();
|
this.getActionIds();
|
||||||
|
@ -57,37 +57,22 @@
|
|||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.PROFILE.USERNAME' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.USERNAME' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="userName" required />
|
<input cnslInput formControlName="userName" required />
|
||||||
<span cnslError *ngIf="userName?.invalid && userName?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.PROFILE.EMAIL' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.EMAIL' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="email" required />
|
<input cnslInput formControlName="email" required />
|
||||||
<span cnslError *ngIf="email?.invalid && email?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="firstName" required />
|
<input cnslInput formControlName="firstName" required />
|
||||||
<span cnslError *ngIf="firstName?.invalid && firstName?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.PROFILE.LASTNAME' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.LASTNAME' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="lastName" required />
|
<input cnslInput formControlName="lastName" required />
|
||||||
<span cnslError *ngIf="lastName?.invalid && lastName?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.PROFILE.NICKNAME' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.NICKNAME' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="nickName" />
|
<input cnslInput formControlName="nickName" />
|
||||||
<span cnslError *ngIf="nickName?.invalid && nickName?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
<p class="section cnsl-secondary-text">{{ 'USER.CREATE.GENDERLANGSECTION' | translate }}</p>
|
<p class="section cnsl-secondary-text">{{ 'USER.CREATE.GENDERLANGSECTION' | translate }}</p>
|
||||||
@ -99,9 +84,6 @@
|
|||||||
{{ 'GENDERS.' + gender | translate }}
|
{{ 'GENDERS.' + gender | translate }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
<span cnslError *ngIf="gender?.invalid && gender?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}</cnsl-label>
|
||||||
@ -109,9 +91,6 @@
|
|||||||
<mat-option *ngFor="let language of languages" [value]="language">
|
<mat-option *ngFor="let language of languages" [value]="language">
|
||||||
{{ 'LANGUAGES.' + language | translate }}
|
{{ 'LANGUAGES.' + language | translate }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
<span cnslError *ngIf="preferredLanguage?.invalid && preferredLanguage?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
@ -148,10 +127,6 @@
|
|||||||
<cnsl-form-field class="pwd" *ngIf="password">
|
<cnsl-form-field class="pwd" *ngIf="password">
|
||||||
<cnsl-label>{{ 'USER.PASSWORD.NEW' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PASSWORD.NEW' | translate }}</cnsl-label>
|
||||||
<input cnslInput autocomplete="off" name="firstpassword" formControlName="password" type="password" />
|
<input cnslInput autocomplete="off" name="firstpassword" formControlName="password" type="password" />
|
||||||
|
|
||||||
<span cnslError *ngIf="password?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="pwd" *ngIf="confirmPassword">
|
<cnsl-form-field class="pwd" *ngIf="confirmPassword">
|
||||||
<cnsl-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</cnsl-label>
|
||||||
@ -162,13 +137,6 @@
|
|||||||
formControlName="confirmPassword"
|
formControlName="confirmPassword"
|
||||||
type="password"
|
type="password"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span cnslError *ngIf="confirmPassword?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
<span cnslError *ngIf="confirmPassword?.errors?.notequal">
|
|
||||||
{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
</form>
|
</form>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -4,7 +4,15 @@ import { Component } from '@angular/core';
|
|||||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, ValidatorFn, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, ValidatorFn, Validators } from '@angular/forms';
|
||||||
import { MatLegacySlideToggleChange as MatSlideToggleChange } from '@angular/material/legacy-slide-toggle';
|
import { MatLegacySlideToggleChange as MatSlideToggleChange } from '@angular/material/legacy-slide-toggle';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from 'src/app/pages/validators';
|
import {
|
||||||
|
containsLowerCaseValidator,
|
||||||
|
containsNumberValidator,
|
||||||
|
containsSymbolValidator,
|
||||||
|
containsUpperCaseValidator,
|
||||||
|
minLengthValidator,
|
||||||
|
passwordConfirmValidator,
|
||||||
|
requiredValidator,
|
||||||
|
} from 'src/app/modules/form-field/validators/validators';
|
||||||
import { SetUpOrgRequest } from 'src/app/proto/generated/zitadel/admin_pb';
|
import { SetUpOrgRequest } from 'src/app/proto/generated/zitadel/admin_pb';
|
||||||
import { PasswordComplexityPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
import { PasswordComplexityPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||||
import { Gender } from 'src/app/proto/generated/zitadel/user_pb';
|
import { Gender } from 'src/app/proto/generated/zitadel/user_pb';
|
||||||
@ -13,26 +21,6 @@ import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/
|
|||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
|
||||||
function passwordConfirmValidator(c: AbstractControl): any {
|
|
||||||
if (!c.parent || !c) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const pwd = c.parent.get('password');
|
|
||||||
const cpwd = c.parent.get('confirmPassword');
|
|
||||||
|
|
||||||
if (!pwd || !cpwd) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pwd.value !== cpwd.value) {
|
|
||||||
return {
|
|
||||||
invalid: true,
|
|
||||||
notequal: {
|
|
||||||
valid: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cnsl-org-create',
|
selector: 'cnsl-org-create',
|
||||||
templateUrl: './org-create.component.html',
|
templateUrl: './org-create.component.html',
|
||||||
@ -49,7 +37,7 @@ function passwordConfirmValidator(c: AbstractControl): any {
|
|||||||
})
|
})
|
||||||
export class OrgCreateComponent {
|
export class OrgCreateComponent {
|
||||||
public orgForm: UntypedFormGroup = this.fb.group({
|
public orgForm: UntypedFormGroup = this.fb.group({
|
||||||
name: ['', [Validators.required]],
|
name: ['', [requiredValidator]],
|
||||||
domain: [''],
|
domain: [''],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -133,10 +121,10 @@ export class OrgCreateComponent {
|
|||||||
|
|
||||||
private initForm(): void {
|
private initForm(): void {
|
||||||
this.userForm = this.fb.group({
|
this.userForm = this.fb.group({
|
||||||
userName: ['', [Validators.required]],
|
userName: ['', [requiredValidator]],
|
||||||
firstName: ['', [Validators.required]],
|
firstName: ['', [requiredValidator]],
|
||||||
lastName: ['', [Validators.required]],
|
lastName: ['', [requiredValidator]],
|
||||||
email: ['', [Validators.required]],
|
email: ['', [requiredValidator]],
|
||||||
isVerified: [false, []],
|
isVerified: [false, []],
|
||||||
gender: [''],
|
gender: [''],
|
||||||
nickName: [''],
|
nickName: [''],
|
||||||
@ -145,7 +133,7 @@ export class OrgCreateComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public initPwdValidators(): void {
|
public initPwdValidators(): void {
|
||||||
const validators: Validators[] = [Validators.required];
|
const validators: Validators[] = [requiredValidator];
|
||||||
|
|
||||||
if (this.usePassword) {
|
if (this.usePassword) {
|
||||||
this.mgmtService.getDefaultPasswordComplexityPolicy().then((data) => {
|
this.mgmtService.getDefaultPasswordComplexityPolicy().then((data) => {
|
||||||
@ -153,23 +141,23 @@ export class OrgCreateComponent {
|
|||||||
this.policy = data.policy;
|
this.policy = data.policy;
|
||||||
|
|
||||||
if (this.policy.minLength) {
|
if (this.policy.minLength) {
|
||||||
validators.push(Validators.minLength(this.policy.minLength));
|
validators.push(minLengthValidator(this.policy.minLength));
|
||||||
}
|
}
|
||||||
if (this.policy.hasLowercase) {
|
if (this.policy.hasLowercase) {
|
||||||
validators.push(lowerCaseValidator);
|
validators.push(containsLowerCaseValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasUppercase) {
|
if (this.policy.hasUppercase) {
|
||||||
validators.push(upperCaseValidator);
|
validators.push(containsUpperCaseValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasNumber) {
|
if (this.policy.hasNumber) {
|
||||||
validators.push(numberValidator);
|
validators.push(containsNumberValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasSymbol) {
|
if (this.policy.hasSymbol) {
|
||||||
validators.push(symbolValidator);
|
validators.push(containsSymbolValidator);
|
||||||
}
|
}
|
||||||
|
|
||||||
const pwdValidators = [...validators] as ValidatorFn[];
|
const pwdValidators = [...validators] as ValidatorFn[];
|
||||||
const confirmPwdValidators = [...validators, passwordConfirmValidator] as ValidatorFn[];
|
const confirmPwdValidators = [requiredValidator, passwordConfirmValidator()] as ValidatorFn[];
|
||||||
this.pwdForm = this.fb.group({
|
this.pwdForm = this.fb.group({
|
||||||
password: ['', pwdValidators],
|
password: ['', pwdValidators],
|
||||||
confirmPassword: ['', confirmPwdValidators],
|
confirmPassword: ['', confirmPwdValidators],
|
||||||
@ -189,13 +177,13 @@ export class OrgCreateComponent {
|
|||||||
this.createSteps = 1;
|
this.createSteps = 1;
|
||||||
|
|
||||||
this.orgForm = this.fb.group({
|
this.orgForm = this.fb.group({
|
||||||
name: ['', [Validators.required]],
|
name: ['', [requiredValidator]],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.createSteps = 2;
|
this.createSteps = 2;
|
||||||
|
|
||||||
this.orgForm = this.fb.group({
|
this.orgForm = this.fb.group({
|
||||||
name: ['', [Validators.required]],
|
name: ['', [requiredValidator]],
|
||||||
domain: [''],
|
domain: [''],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,6 @@
|
|||||||
<cnsl-form-field class="name-formfield">
|
<cnsl-form-field class="name-formfield">
|
||||||
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'APP.NAME' | translate }}</cnsl-label>
|
||||||
<input cnslInput cdkFocusInitial formControlName="name" />
|
<input cnslInput cdkFocusInitial formControlName="name" />
|
||||||
<span cnslError *ngIf="name?.errors?.required">{{ 'PROJECT.APP.NAMEREQUIRED' | translate }}</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
<p class="step-title">{{ 'APP.TYPETITLE' | translate }}</p>
|
<p class="step-title">{{ 'APP.TYPETITLE' | translate }}</p>
|
||||||
|
@ -2,13 +2,14 @@ import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
|
|||||||
import { StepperSelectionEvent } from '@angular/cdk/stepper';
|
import { StepperSelectionEvent } from '@angular/cdk/stepper';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||||
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
||||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||||
import { Buffer } from 'buffer';
|
import { Buffer } from 'buffer';
|
||||||
import { Subject, Subscription } from 'rxjs';
|
import { Subject, Subscription } from 'rxjs';
|
||||||
import { debounceTime, takeUntil } from 'rxjs/operators';
|
import { debounceTime, takeUntil } from 'rxjs/operators';
|
||||||
import { RadioItemAuthType } from 'src/app/modules/app-radio/app-auth-method-radio/app-auth-method-radio.component';
|
import { RadioItemAuthType } from 'src/app/modules/app-radio/app-auth-method-radio/app-auth-method-radio.component';
|
||||||
|
import { requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||||
import {
|
import {
|
||||||
APIAuthMethodType,
|
APIAuthMethodType,
|
||||||
OIDCAppType,
|
OIDCAppType,
|
||||||
@ -127,8 +128,8 @@ export class AppCreateComponent implements OnInit, OnDestroy {
|
|||||||
private breadcrumbService: BreadcrumbService,
|
private breadcrumbService: BreadcrumbService,
|
||||||
) {
|
) {
|
||||||
this.form = this.fb.group({
|
this.form = this.fb.group({
|
||||||
name: ['', [Validators.required]],
|
name: ['', [requiredValidator]],
|
||||||
appType: ['', [Validators.required]],
|
appType: ['', [requiredValidator]],
|
||||||
// apptype OIDC
|
// apptype OIDC
|
||||||
responseTypesList: ['', []],
|
responseTypesList: ['', []],
|
||||||
grantTypesList: ['', []],
|
grantTypesList: ['', []],
|
||||||
@ -140,8 +141,8 @@ export class AppCreateComponent implements OnInit, OnDestroy {
|
|||||||
this.initForm();
|
this.initForm();
|
||||||
|
|
||||||
this.firstFormGroup = this.fb.group({
|
this.firstFormGroup = this.fb.group({
|
||||||
name: ['', [Validators.required]],
|
name: ['', [requiredValidator]],
|
||||||
appType: [WEB_TYPE, [Validators.required]],
|
appType: [WEB_TYPE, [requiredValidator]],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.samlConfigForm = this.fb.group({
|
this.samlConfigForm = this.fb.group({
|
||||||
@ -192,7 +193,7 @@ export class AppCreateComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.secondFormGroup = this.fb.group({
|
this.secondFormGroup = this.fb.group({
|
||||||
authMethod: [this.authMethods[0].key, [Validators.required]],
|
authMethod: [this.authMethods[0].key, [requiredValidator]],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.secondFormGroup.valueChanges.subscribe((form) => {
|
this.secondFormGroup.valueChanges.subscribe((form) => {
|
||||||
@ -276,8 +277,8 @@ export class AppCreateComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
public setDevFormValidators(): void {
|
public setDevFormValidators(): void {
|
||||||
if (this.isDevOIDC) {
|
if (this.isDevOIDC) {
|
||||||
const grantTypesControl = new UntypedFormControl('', [Validators.required]);
|
const grantTypesControl = new UntypedFormControl('', [requiredValidator]);
|
||||||
const responseTypesControl = new UntypedFormControl('', [Validators.required]);
|
const responseTypesControl = new UntypedFormControl('', [requiredValidator]);
|
||||||
|
|
||||||
this.form.addControl('grantTypesList', grantTypesControl);
|
this.form.addControl('grantTypesList', grantTypesControl);
|
||||||
this.form.addControl('responseTypesList', responseTypesControl);
|
this.form.addControl('responseTypesList', responseTypesControl);
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { animate, animateChild, query, stagger, style, transition, trigger } from '@angular/animations';
|
import { animate, animateChild, query, stagger, style, transition, trigger } from '@angular/animations';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
import { requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||||
import { BulkAddProjectRolesRequest } from 'src/app/proto/generated/zitadel/management_pb';
|
import { BulkAddProjectRolesRequest } from 'src/app/proto/generated/zitadel/management_pb';
|
||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
@ -32,7 +33,7 @@ export class ProjectRoleCreateComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
public formArray!: UntypedFormArray;
|
public formArray!: UntypedFormArray;
|
||||||
public formGroup: UntypedFormGroup = this.fb.group({
|
public formGroup: UntypedFormGroup = this.fb.group({
|
||||||
key: new UntypedFormControl('', [Validators.required]),
|
key: new UntypedFormControl('', [requiredValidator]),
|
||||||
displayName: new UntypedFormControl(''),
|
displayName: new UntypedFormControl(''),
|
||||||
group: new UntypedFormControl(''),
|
group: new UntypedFormControl(''),
|
||||||
});
|
});
|
||||||
@ -50,7 +51,7 @@ export class ProjectRoleCreateComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
public addEntry(): void {
|
public addEntry(): void {
|
||||||
const newGroup = this.fb.group({
|
const newGroup = this.fb.group({
|
||||||
key: new UntypedFormControl('', [Validators.required]),
|
key: new UntypedFormControl('', [requiredValidator]),
|
||||||
displayName: new UntypedFormControl(''),
|
displayName: new UntypedFormControl(''),
|
||||||
group: new UntypedFormControl(''),
|
group: new UntypedFormControl(''),
|
||||||
});
|
});
|
||||||
|
@ -12,19 +12,10 @@
|
|||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.MACHINE.USERNAME' | translate }}*</cnsl-label>
|
<cnsl-label>{{ 'USER.MACHINE.USERNAME' | translate }}*</cnsl-label>
|
||||||
<input cnslInput formControlName="userName" required />
|
<input cnslInput formControlName="userName" required />
|
||||||
<span cnslError *ngIf="userName?.invalid && userName?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
<span cnslError *ngIf="userName?.invalid && userName?.errors?.noEmailValidator">
|
|
||||||
{{ 'USER.VALIDATION.NOEMAIL' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.MACHINE.NAME' | translate }}*</cnsl-label>
|
<cnsl-label>{{ 'USER.MACHINE.NAME' | translate }}*</cnsl-label>
|
||||||
<input cnslInput formControlName="name" required />
|
<input cnslInput formControlName="name" required />
|
||||||
<span cnslError *ngIf="name?.invalid && name?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.MACHINE.DESCRIPTION' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.MACHINE.DESCRIPTION' | translate }}</cnsl-label>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, OnDestroy } from '@angular/core';
|
import { Component, OnDestroy } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
import { minLengthValidator, requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||||
import { AddMachineUserRequest } from 'src/app/proto/generated/zitadel/management_pb';
|
import { AddMachineUserRequest } from 'src/app/proto/generated/zitadel/management_pb';
|
||||||
import { AccessTokenType } from 'src/app/proto/generated/zitadel/user_pb';
|
import { AccessTokenType } from 'src/app/proto/generated/zitadel/user_pb';
|
||||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||||
@ -45,8 +46,8 @@ export class UserCreateMachineComponent implements OnDestroy {
|
|||||||
|
|
||||||
private initForm(): void {
|
private initForm(): void {
|
||||||
this.userForm = this.fb.group({
|
this.userForm = this.fb.group({
|
||||||
userName: ['', [Validators.required, Validators.minLength(2)]],
|
userName: ['', [requiredValidator, minLengthValidator(2)]],
|
||||||
name: ['', [Validators.required]],
|
name: ['', [requiredValidator]],
|
||||||
description: ['', []],
|
description: ['', []],
|
||||||
accessTokenType: [AccessTokenType.ACCESS_TOKEN_TYPE_BEARER, []],
|
accessTokenType: [AccessTokenType.ACCESS_TOKEN_TYPE_BEARER, []],
|
||||||
});
|
});
|
||||||
|
@ -15,12 +15,6 @@
|
|||||||
<cnsl-form-field>
|
<cnsl-form-field>
|
||||||
<cnsl-label>{{ 'USER.PROFILE.EMAIL' | translate }}*</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.EMAIL' | translate }}*</cnsl-label>
|
||||||
<input cnslInput matRipple formControlName="email" required />
|
<input cnslInput matRipple formControlName="email" required />
|
||||||
<span cnslError *ngIf="email?.invalid && !email?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.NOTANEMAIL' | translate }}
|
|
||||||
</span>
|
|
||||||
<span cnslError *ngIf="email?.invalid && email?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field>
|
<cnsl-form-field>
|
||||||
<cnsl-label>{{ 'USER.PROFILE.USERNAME' | translate }}*</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.USERNAME' | translate }}*</cnsl-label>
|
||||||
@ -31,35 +25,19 @@
|
|||||||
[ngStyle]="{ 'padding-right': suffixPadding ? suffixPadding : '10px' }"
|
[ngStyle]="{ 'padding-right': suffixPadding ? suffixPadding : '10px' }"
|
||||||
/>
|
/>
|
||||||
<span #suffix *ngIf="envSuffix" cnslSuffix>{{ envSuffix }}</span>
|
<span #suffix *ngIf="envSuffix" cnslSuffix>{{ envSuffix }}</span>
|
||||||
|
|
||||||
<span cnslError *ngIf="userName?.invalid && userName?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
<span cnslError *ngIf="userName?.invalid && userName?.errors?.noEmailValidator">
|
|
||||||
{{ 'USER.VALIDATION.NOEMAIL' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
<cnsl-form-field>
|
<cnsl-form-field>
|
||||||
<cnsl-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}*</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}*</cnsl-label>
|
||||||
<input cnslInput formControlName="firstName" required />
|
<input cnslInput formControlName="firstName" required />
|
||||||
<span cnslError *ngIf="firstName?.invalid && firstName?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field>
|
<cnsl-form-field>
|
||||||
<cnsl-label>{{ 'USER.PROFILE.LASTNAME' | translate }}*</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.LASTNAME' | translate }}*</cnsl-label>
|
||||||
<input cnslInput formControlName="lastName" required />
|
<input cnslInput formControlName="lastName" required />
|
||||||
<span cnslError *ngIf="lastName?.invalid && lastName?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field>
|
<cnsl-form-field>
|
||||||
<cnsl-label>{{ 'USER.PROFILE.NICKNAME' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.NICKNAME' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="nickName" />
|
<input cnslInput formControlName="nickName" />
|
||||||
<span cnslError *ngIf="nickName?.invalid && nickName?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -84,10 +62,6 @@
|
|||||||
<cnsl-form-field *ngIf="password">
|
<cnsl-form-field *ngIf="password">
|
||||||
<cnsl-label>{{ 'USER.PASSWORD.NEWINITIAL' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PASSWORD.NEWINITIAL' | translate }}</cnsl-label>
|
||||||
<input cnslInput autocomplete="off" name="firstpassword" formControlName="password" type="password" />
|
<input cnslInput autocomplete="off" name="firstpassword" formControlName="password" type="password" />
|
||||||
|
|
||||||
<span cnslError *ngIf="password?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field *ngIf="confirmPassword">
|
<cnsl-form-field *ngIf="confirmPassword">
|
||||||
<cnsl-label>{{ 'USER.PASSWORD.CONFIRMINITIAL' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PASSWORD.CONFIRMINITIAL' | translate }}</cnsl-label>
|
||||||
@ -98,13 +72,6 @@
|
|||||||
formControlName="confirmPassword"
|
formControlName="confirmPassword"
|
||||||
type="password"
|
type="password"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span cnslError *ngIf="confirmPassword?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
<span cnslError *ngIf="confirmPassword?.errors?.notequal">
|
|
||||||
{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@ -120,9 +87,6 @@
|
|||||||
{{ 'GENDERS.' + gender | translate }}
|
{{ 'GENDERS.' + gender | translate }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
<span cnslError *ngIf="gender?.invalid && gender?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field>
|
<cnsl-form-field>
|
||||||
<cnsl-label>{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}</cnsl-label>
|
||||||
@ -130,9 +94,6 @@
|
|||||||
<mat-option *ngFor="let language of languages" [value]="language">
|
<mat-option *ngFor="let language of languages" [value]="language">
|
||||||
{{ 'LANGUAGES.' + language | translate }}
|
{{ 'LANGUAGES.' + language | translate }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
<span cnslError *ngIf="preferredLanguage?.invalid && preferredLanguage?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
</div>
|
</div>
|
||||||
@ -154,9 +115,6 @@
|
|||||||
<cnsl-form-field>
|
<cnsl-form-field>
|
||||||
<cnsl-label>{{ 'USER.PROFILE.PHONE' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PROFILE.PHONE' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="phone" matTooltip="{{ 'USER.PROFILE.PHONE_HINT' | translate }}" />
|
<input cnslInput formControlName="phone" matTooltip="{{ 'USER.PROFILE.PHONE_HINT' | translate }}" />
|
||||||
<span cnslError *ngIf="phone?.invalid && phone?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,27 +13,17 @@ import { ToastService } from 'src/app/services/toast.service';
|
|||||||
|
|
||||||
import { CountryCallingCodesService, CountryPhoneCode } from 'src/app/services/country-calling-codes.service';
|
import { CountryCallingCodesService, CountryPhoneCode } from 'src/app/services/country-calling-codes.service';
|
||||||
import { formatPhone } from 'src/app/utils/formatPhone';
|
import { formatPhone } from 'src/app/utils/formatPhone';
|
||||||
import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from '../../validators';
|
import {
|
||||||
|
containsLowerCaseValidator,
|
||||||
function passwordConfirmValidator(c: AbstractControl): any {
|
containsNumberValidator,
|
||||||
if (!c.parent || !c) {
|
containsSymbolValidator,
|
||||||
return;
|
containsUpperCaseValidator,
|
||||||
}
|
emailValidator,
|
||||||
const pwd = c.parent.get('password');
|
minLengthValidator,
|
||||||
const cpwd = c.parent.get('confirmPassword');
|
passwordConfirmValidator,
|
||||||
|
phoneValidator,
|
||||||
if (!pwd || !cpwd) {
|
requiredValidator,
|
||||||
return;
|
} from '../../../modules/form-field/validators/validators';
|
||||||
}
|
|
||||||
if (pwd.value !== cpwd.value) {
|
|
||||||
return {
|
|
||||||
invalid: true,
|
|
||||||
notequal: {
|
|
||||||
valid: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cnsl-user-create',
|
selector: 'cnsl-user-create',
|
||||||
@ -113,40 +103,40 @@ export class UserCreateComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
private initForm(): void {
|
private initForm(): void {
|
||||||
this.userForm = this.fb.group({
|
this.userForm = this.fb.group({
|
||||||
email: ['', [Validators.required, Validators.email]],
|
email: ['', [requiredValidator, emailValidator]],
|
||||||
userName: ['', [Validators.required, Validators.minLength(2)]],
|
userName: ['', [requiredValidator, minLengthValidator(2)]],
|
||||||
firstName: ['', Validators.required],
|
firstName: ['', requiredValidator],
|
||||||
lastName: ['', Validators.required],
|
lastName: ['', requiredValidator],
|
||||||
nickName: [''],
|
nickName: [''],
|
||||||
gender: [],
|
gender: [],
|
||||||
preferredLanguage: [''],
|
preferredLanguage: [''],
|
||||||
phone: [''],
|
phone: ['', phoneValidator],
|
||||||
isVerified: [false, []],
|
isVerified: [false, []],
|
||||||
});
|
});
|
||||||
|
|
||||||
const validators: Validators[] = [Validators.required];
|
const validators: Validators[] = [requiredValidator];
|
||||||
|
|
||||||
this.mgmtService.getPasswordComplexityPolicy().then((data) => {
|
this.mgmtService.getPasswordComplexityPolicy().then((data) => {
|
||||||
if (data.policy) {
|
if (data.policy) {
|
||||||
this.policy = data.policy;
|
this.policy = data.policy;
|
||||||
|
|
||||||
if (this.policy.minLength) {
|
if (this.policy.minLength) {
|
||||||
validators.push(Validators.minLength(this.policy.minLength));
|
validators.push(minLengthValidator(this.policy.minLength));
|
||||||
}
|
}
|
||||||
if (this.policy.hasLowercase) {
|
if (this.policy.hasLowercase) {
|
||||||
validators.push(lowerCaseValidator);
|
validators.push(containsLowerCaseValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasUppercase) {
|
if (this.policy.hasUppercase) {
|
||||||
validators.push(upperCaseValidator);
|
validators.push(containsUpperCaseValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasNumber) {
|
if (this.policy.hasNumber) {
|
||||||
validators.push(numberValidator);
|
validators.push(containsNumberValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasSymbol) {
|
if (this.policy.hasSymbol) {
|
||||||
validators.push(symbolValidator);
|
validators.push(containsSymbolValidator);
|
||||||
}
|
}
|
||||||
const pwdValidators = [...validators] as ValidatorFn[];
|
const pwdValidators = [...validators] as ValidatorFn[];
|
||||||
const confirmPwdValidators = [...validators, passwordConfirmValidator] as ValidatorFn[];
|
const confirmPwdValidators = [requiredValidator, passwordConfirmValidator()] as ValidatorFn[];
|
||||||
|
|
||||||
this.pwdForm = this.fb.group({
|
this.pwdForm = this.fb.group({
|
||||||
password: ['', pwdValidators],
|
password: ['', pwdValidators],
|
||||||
@ -203,14 +193,13 @@ export class UserCreateComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
public setCountryCallingCode(): void {
|
public setCountryCallingCode(): void {
|
||||||
let value = (this.phone?.value as string) || '';
|
let value = (this.phone?.value as string) || '';
|
||||||
this.phone?.setValue('+' + this.selected?.countryCallingCode + ' ' + value.replace(/\+[0-9]*\s/, ''));
|
this.countryPhoneCodes.forEach((code) => (value = value.replace(`+${code.countryCallingCode}`, '')));
|
||||||
|
value = value.trim();
|
||||||
|
this.phone?.setValue('+' + this.selected?.countryCallingCode + ' ' + value);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
// Set default selected country for phone numbers
|
|
||||||
const defaultCountryCallingCode = 'CH';
|
|
||||||
this.countryPhoneCodes = this.countryCallingCodesService.getCountryCallingCodes();
|
this.countryPhoneCodes = this.countryCallingCodesService.getCountryCallingCodes();
|
||||||
this.selected = this.countryPhoneCodes.find((code) => code.countryCode === defaultCountryCallingCode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import { MediaMatcher } from '@angular/cdk/layout';
|
import { MediaMatcher } from '@angular/cdk/layout';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, EventEmitter, OnDestroy } from '@angular/core';
|
import { Component, EventEmitter, OnDestroy } from '@angular/core';
|
||||||
|
import { Validators } from '@angular/forms';
|
||||||
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
||||||
import { ActivatedRoute, Params } from '@angular/router';
|
import { ActivatedRoute, Params } from '@angular/router';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { Buffer } from 'buffer';
|
import { Buffer } from 'buffer';
|
||||||
import { Subscription, take } from 'rxjs';
|
import { Subscription, take } from 'rxjs';
|
||||||
import { ChangeType } from 'src/app/modules/changes/changes.component';
|
import { ChangeType } from 'src/app/modules/changes/changes.component';
|
||||||
|
import { phoneValidator, requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||||
import { MetadataDialogComponent } from 'src/app/modules/metadata/metadata-dialog/metadata-dialog.component';
|
import { MetadataDialogComponent } from 'src/app/modules/metadata/metadata-dialog/metadata-dialog.component';
|
||||||
import { PolicyComponentServiceType } from 'src/app/modules/policies/policy-component-types.enum';
|
import { PolicyComponentServiceType } from 'src/app/modules/policies/policy-component-types.enum';
|
||||||
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
|
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
|
||||||
@ -304,6 +306,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
|||||||
descriptionKey: 'USER.LOGINMETHODS.PHONE.EDITDESC',
|
descriptionKey: 'USER.LOGINMETHODS.PHONE.EDITDESC',
|
||||||
value: this.user?.human?.phone?.phone,
|
value: this.user?.human?.phone?.phone,
|
||||||
type: type,
|
type: type,
|
||||||
|
validator: Validators.compose([phoneValidator, requiredValidator]),
|
||||||
},
|
},
|
||||||
width: '400px',
|
width: '400px',
|
||||||
});
|
});
|
||||||
|
@ -3,40 +3,39 @@
|
|||||||
</h1>
|
</h1>
|
||||||
<p class="desc cnsl-secondary-text">{{ data.descriptionKey | translate }}</p>
|
<p class="desc cnsl-secondary-text">{{ data.descriptionKey | translate }}</p>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
<div class="phone-grid">
|
<form [formGroup]="dialogForm" (ngSubmit)="closeDialogWithValue()">
|
||||||
<cnsl-form-field *ngIf="isPhone">
|
<div class="phone-grid">
|
||||||
<cnsl-label>{{ 'USER.PROFILE.COUNTRY' | translate }}</cnsl-label>
|
<cnsl-form-field *ngIf="isPhone">
|
||||||
<mat-select [(value)]="selected" (selectionChange)="setCountryCallingCode()">
|
<cnsl-label>{{ 'USER.PROFILE.COUNTRY' | translate }}</cnsl-label>
|
||||||
<mat-select-trigger> <span class="fi fi-{{ selected?.countryCode | lowercase }}"></span></mat-select-trigger>
|
<mat-select [(value)]="selected" (selectionChange)="setCountryCallingCode()">
|
||||||
<mat-option *ngFor="let country of countryPhoneCodes" [value]="country">
|
<mat-select-trigger> <span class="fi fi-{{ selected?.countryCode | lowercase }}"></span></mat-select-trigger>
|
||||||
<span class="fi fi-{{ country.countryCode | lowercase }}"></span>
|
<mat-option *ngFor="let country of countryPhoneCodes" [value]="country">
|
||||||
<span class="phone-country-name">{{ country.countryName }}</span>
|
<span class="fi fi-{{ country.countryCode | lowercase }}"></span>
|
||||||
<span class="phone-country-code">+{{ country.countryCallingCode }}</span>
|
<span class="phone-country-name">{{ country.countryName }}</span>
|
||||||
</mat-option>
|
<span class="phone-country-code">+{{ country.countryCallingCode }}</span>
|
||||||
</mat-select>
|
</mat-option>
|
||||||
</cnsl-form-field>
|
</mat-select>
|
||||||
<cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-label>{{ data.labelKey | translate }}</cnsl-label>
|
<cnsl-form-field>
|
||||||
<input
|
<cnsl-label>{{ data.labelKey | translate }}</cnsl-label>
|
||||||
cnslInput
|
<input
|
||||||
[formControl]="valueControl"
|
cnslInput
|
||||||
matTooltip="{{ 'USER.PROFILE.PHONE_HINT' | translate }}"
|
[formControlName]="controlKey"
|
||||||
[matTooltipDisabled]="!isPhone"
|
matTooltip="{{ 'USER.PROFILE.PHONE_HINT' | translate }}"
|
||||||
/>
|
[matTooltipDisabled]="!isPhone"
|
||||||
<span cnslError *ngIf="valueControl?.invalid && valueControl?.errors?.required">
|
/>
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
</cnsl-form-field>
|
||||||
</span>
|
</div>
|
||||||
</cnsl-form-field>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ng-container *ngIf="data.type === EditDialogType.EMAIL && data.isVerifiedTextKey">
|
<ng-container *ngIf="data.type === EditDialogType.EMAIL && data.isVerifiedTextKey">
|
||||||
<mat-checkbox class="verified-checkbox" [(ngModel)]="isVerified">
|
<mat-checkbox class="verified-checkbox" [(ngModel)]="isVerified">
|
||||||
{{ data.isVerifiedTextKey | translate }}
|
{{ data.isVerifiedTextKey | translate }}
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
<cnsl-info-section class="full-width desc">
|
<cnsl-info-section class="full-width desc">
|
||||||
<span>{{ data.isVerifiedTextDescKey | translate }}</span>
|
<span>{{ data.isVerifiedTextDescKey | translate }}</span>
|
||||||
</cnsl-info-section>
|
</cnsl-info-section>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div mat-dialog-actions class="action">
|
<div mat-dialog-actions class="action">
|
||||||
<button mat-stroked-button class="ok-button" (click)="closeDialog()">
|
<button mat-stroked-button class="ok-button" (click)="closeDialog()">
|
||||||
@ -44,7 +43,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
[disabled]="valueControl.invalid"
|
[disabled]="dialogForm.invalid"
|
||||||
cdkFocusInitial
|
cdkFocusInitial
|
||||||
color="primary"
|
color="primary"
|
||||||
mat-raised-button
|
mat-raised-button
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
|
import { KeyValuePipe } from '@angular/common';
|
||||||
import { Component, Inject, OnInit } from '@angular/core';
|
import { Component, Inject, OnInit } from '@angular/core';
|
||||||
import { UntypedFormControl, Validators } from '@angular/forms';
|
import { FormGroup, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
|
||||||
import {
|
import {
|
||||||
MatLegacyDialogRef as MatDialogRef,
|
MatLegacyDialogRef as MatDialogRef,
|
||||||
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
|
||||||
} from '@angular/material/legacy-dialog';
|
} from '@angular/material/legacy-dialog';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||||
import { CountryCallingCodesService, CountryPhoneCode } from 'src/app/services/country-calling-codes.service';
|
import { CountryCallingCodesService, CountryPhoneCode } from 'src/app/services/country-calling-codes.service';
|
||||||
import { formatPhone } from 'src/app/utils/formatPhone';
|
import { formatPhone } from 'src/app/utils/formatPhone';
|
||||||
|
|
||||||
@ -13,15 +16,16 @@ export enum EditDialogType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cnsl-edit-email-dialog',
|
selector: 'cnsl-edit-dialog',
|
||||||
templateUrl: './edit-dialog.component.html',
|
templateUrl: './edit-dialog.component.html',
|
||||||
styleUrls: ['./edit-dialog.component.scss'],
|
styleUrls: ['./edit-dialog.component.scss'],
|
||||||
})
|
})
|
||||||
export class EditDialogComponent implements OnInit {
|
export class EditDialogComponent implements OnInit {
|
||||||
|
public controlKey = 'editingField';
|
||||||
public isPhone: boolean = false;
|
public isPhone: boolean = false;
|
||||||
public isVerified: boolean = false;
|
public isVerified: boolean = false;
|
||||||
public phoneCountry: string = 'CH';
|
public phoneCountry: string = 'CH';
|
||||||
public valueControl: UntypedFormControl = new UntypedFormControl(['', [Validators.required]]);
|
public dialogForm!: UntypedFormGroup;
|
||||||
public EditDialogType: any = EditDialogType;
|
public EditDialogType: any = EditDialogType;
|
||||||
public selected: CountryPhoneCode | undefined;
|
public selected: CountryPhoneCode | undefined;
|
||||||
public countryPhoneCodes: CountryPhoneCode[] = [];
|
public countryPhoneCodes: CountryPhoneCode[] = [];
|
||||||
@ -29,25 +33,33 @@ export class EditDialogComponent implements OnInit {
|
|||||||
public dialogRef: MatDialogRef<EditDialogComponent>,
|
public dialogRef: MatDialogRef<EditDialogComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||||
private countryCallingCodesService: CountryCallingCodesService,
|
private countryCallingCodesService: CountryCallingCodesService,
|
||||||
|
private translateSvc: TranslateService,
|
||||||
|
private kvPipe: KeyValuePipe,
|
||||||
) {
|
) {
|
||||||
this.valueControl.setValue(data.value);
|
|
||||||
if (data.type === EditDialogType.PHONE) {
|
if (data.type === EditDialogType.PHONE) {
|
||||||
this.isPhone = true;
|
this.isPhone = true;
|
||||||
}
|
}
|
||||||
|
this.dialogForm = new FormGroup({
|
||||||
|
[this.controlKey]: new UntypedFormControl(data.value, data.validator || requiredValidator),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public setCountryCallingCode(): void {
|
public setCountryCallingCode(): void {
|
||||||
let value = (this.valueControl?.value as string) || '';
|
console.log(this);
|
||||||
this.valueControl?.setValue('+' + this.selected?.countryCallingCode + ' ' + value.replace(/\+[0-9]*\s/, ''));
|
let value = (this.dialogForm.controls[this.controlKey]?.value as string) || '';
|
||||||
|
this.countryPhoneCodes.forEach((code) => (value = value.replace(`+${code.countryCallingCode}`, '')));
|
||||||
|
value = value.trim();
|
||||||
|
this.dialogForm.controls[this.controlKey]?.setValue('+' + this.selected?.countryCallingCode + ' ' + value);
|
||||||
|
console.log(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
if (this.isPhone) {
|
if (this.isPhone) {
|
||||||
// Get country phone codes and set selected flag to guessed country or default country
|
// Get country phone codes and set selected flag to guessed country or default country
|
||||||
this.countryPhoneCodes = this.countryCallingCodesService.getCountryCallingCodes();
|
this.countryPhoneCodes = this.countryCallingCodesService.getCountryCallingCodes();
|
||||||
const phoneNumber = formatPhone(this.valueControl?.value);
|
const phoneNumber = formatPhone(this.dialogForm.controls[this.controlKey]?.value);
|
||||||
this.selected = this.countryPhoneCodes.find((code) => code.countryCode === phoneNumber.country);
|
this.selected = this.countryPhoneCodes.find((code) => code.countryCode === phoneNumber.country);
|
||||||
this.valueControl.setValue(phoneNumber.phone);
|
this.dialogForm.controls[this.controlKey].setValue(phoneNumber.phone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +68,10 @@ export class EditDialogComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
closeDialogWithValue(): void {
|
closeDialogWithValue(): void {
|
||||||
this.dialogRef.close({ value: this.valueControl.value, isVerified: this.isVerified });
|
this.dialogRef.close({ value: this.dialogForm.controls[this.controlKey].value, isVerified: this.isVerified });
|
||||||
|
}
|
||||||
|
|
||||||
|
public get ctrl() {
|
||||||
|
return this.dialogForm.get(this.controlKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,10 @@
|
|||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.MACHINE.USERNAME' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.MACHINE.USERNAME' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="userName" required />
|
<input cnslInput formControlName="userName" required />
|
||||||
<span cnslError *ngIf="userName?.invalid && userName?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
<span cnslError *ngIf="userName?.invalid && userName?.errors?.noEmailValidator">
|
|
||||||
{{ 'USER.VALIDATION.NOEMAIL' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.MACHINE.NAME' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.MACHINE.NAME' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="name" required />
|
<input cnslInput formControlName="name" required />
|
||||||
<span cnslError *ngIf="name?.invalid && name?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.MACHINE.DESCRIPTION' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.MACHINE.DESCRIPTION' | translate }}</cnsl-label>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
import { requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||||
import { AccessTokenType, Human, Machine } from 'src/app/proto/generated/zitadel/user_pb';
|
import { AccessTokenType, Human, Machine } from 'src/app/proto/generated/zitadel/user_pb';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -25,10 +26,10 @@ export class DetailFormMachineComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(private fb: UntypedFormBuilder) {
|
constructor(private fb: UntypedFormBuilder) {
|
||||||
this.machineForm = this.fb.group({
|
this.machineForm = this.fb.group({
|
||||||
userName: [{ value: '', disabled: true }, [Validators.required]],
|
userName: [{ value: '', disabled: true }, [requiredValidator]],
|
||||||
name: [{ value: '', disabled: this.disabled }, Validators.required],
|
name: [{ value: '', disabled: this.disabled }, requiredValidator],
|
||||||
description: [{ value: '', disabled: this.disabled }],
|
description: [{ value: '', disabled: this.disabled }],
|
||||||
accessTokenType: [AccessTokenType.ACCESS_TOKEN_TYPE_BEARER, [Validators.required]],
|
accessTokenType: [AccessTokenType.ACCESS_TOKEN_TYPE_BEARER, [requiredValidator]],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { Component, EventEmitter, Input, OnChanges, OnDestroy, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, OnChanges, OnDestroy, Output } from '@angular/core';
|
||||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||||
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
import { requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||||
import { Gender, Human, Profile } from 'src/app/proto/generated/zitadel/user_pb';
|
import { Gender, Human, Profile } from 'src/app/proto/generated/zitadel/user_pb';
|
||||||
|
|
||||||
import { ProfilePictureComponent } from './profile-picture/profile-picture.component';
|
import { ProfilePictureComponent } from './profile-picture/profile-picture.component';
|
||||||
@ -30,11 +31,11 @@ export class DetailFormComponent implements OnDestroy, OnChanges {
|
|||||||
|
|
||||||
constructor(private fb: UntypedFormBuilder, private dialog: MatDialog) {
|
constructor(private fb: UntypedFormBuilder, private dialog: MatDialog) {
|
||||||
this.profileForm = this.fb.group({
|
this.profileForm = this.fb.group({
|
||||||
userName: [{ value: '', disabled: true }, [Validators.required]],
|
userName: [{ value: '', disabled: true }, [requiredValidator]],
|
||||||
firstName: [{ value: '', disabled: this.disabled }, Validators.required],
|
firstName: [{ value: '', disabled: this.disabled }, requiredValidator],
|
||||||
lastName: [{ value: '', disabled: this.disabled }, Validators.required],
|
lastName: [{ value: '', disabled: this.disabled }, requiredValidator],
|
||||||
nickName: [{ value: '', disabled: this.disabled }],
|
nickName: [{ value: '', disabled: this.disabled }],
|
||||||
displayName: [{ value: '', disabled: this.disabled }, Validators.required],
|
displayName: [{ value: '', disabled: this.disabled }, requiredValidator],
|
||||||
gender: [{ value: 0, disabled: this.disabled }],
|
gender: [{ value: 0, disabled: this.disabled }],
|
||||||
preferredLanguage: [{ value: '', disabled: this.disabled }],
|
preferredLanguage: [{ value: '', disabled: this.disabled }],
|
||||||
});
|
});
|
||||||
@ -42,11 +43,11 @@ export class DetailFormComponent implements OnDestroy, OnChanges {
|
|||||||
|
|
||||||
public ngOnChanges(): void {
|
public ngOnChanges(): void {
|
||||||
this.profileForm = this.fb.group({
|
this.profileForm = this.fb.group({
|
||||||
userName: [{ value: '', disabled: true }, [Validators.required]],
|
userName: [{ value: '', disabled: true }, [requiredValidator]],
|
||||||
firstName: [{ value: '', disabled: this.disabled }, Validators.required],
|
firstName: [{ value: '', disabled: this.disabled }, requiredValidator],
|
||||||
lastName: [{ value: '', disabled: this.disabled }, Validators.required],
|
lastName: [{ value: '', disabled: this.disabled }, requiredValidator],
|
||||||
nickName: [{ value: '', disabled: this.disabled }],
|
nickName: [{ value: '', disabled: this.disabled }],
|
||||||
displayName: [{ value: '', disabled: this.disabled }, Validators.required],
|
displayName: [{ value: '', disabled: this.disabled }, requiredValidator],
|
||||||
gender: [{ value: 0, disabled: this.disabled }],
|
gender: [{ value: 0, disabled: this.disabled }],
|
||||||
preferredLanguage: [{ value: '', disabled: this.disabled }],
|
preferredLanguage: [{ value: '', disabled: this.disabled }],
|
||||||
});
|
});
|
||||||
|
@ -17,17 +17,10 @@
|
|||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.PASSWORD.NEW' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PASSWORD.NEW' | translate }}</cnsl-label>
|
||||||
<input cnslInput autocomplete="off" name="password" formControlName="password" type="password" />
|
<input cnslInput autocomplete="off" name="password" formControlName="password" type="password" />
|
||||||
|
|
||||||
<span cnslError *ngIf="password?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</cnsl-label>
|
||||||
<input cnslInput autocomplete="off" name="passwordRepeat" formControlName="confirmPassword" type="password" />
|
<input cnslInput autocomplete="off" name="passwordRepeat" formControlName="confirmPassword" type="password" />
|
||||||
<span cnslError *ngIf="confirmPassword?.errors?.notequal">
|
|
||||||
{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -58,9 +51,6 @@
|
|||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.PASSWORD.OLD' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PASSWORD.OLD' | translate }}</cnsl-label>
|
||||||
<input cnslInput autocomplete="off" name="password" type="password" formControlName="currentPassword" />
|
<input cnslInput autocomplete="off" name="password" type="password" formControlName="currentPassword" />
|
||||||
<span cnslError *ngIf="currentPassword?.errors?.required">
|
|
||||||
{{ 'USER.PASSWORD.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
<div class="validation between" *ngIf="this.policy">
|
<div class="validation between" *ngIf="this.policy">
|
||||||
@ -71,10 +61,6 @@
|
|||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.PASSWORD.NEW' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PASSWORD.NEW' | translate }}</cnsl-label>
|
||||||
<input cnslInput autocomplete="off" name="new password" type="password" formControlName="newPassword" />
|
<input cnslInput autocomplete="off" name="new password" type="password" formControlName="newPassword" />
|
||||||
|
|
||||||
<span cnslError *ngIf="newPassword?.errors?.required">
|
|
||||||
{{ 'USER.VALIDATION.REQUIRED' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</cnsl-label>
|
||||||
@ -85,9 +71,6 @@
|
|||||||
type="password"
|
type="password"
|
||||||
formControlName="confirmPassword"
|
formControlName="confirmPassword"
|
||||||
/>
|
/>
|
||||||
<span cnslError *ngIf="confirmPassword?.errors?.notequal">
|
|
||||||
{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
|
|
||||||
</span>
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,28 +2,21 @@ import { Component, OnDestroy } from '@angular/core';
|
|||||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { Subject, Subscription, take, takeUntil } from 'rxjs';
|
import { Subject, Subscription, take, takeUntil } from 'rxjs';
|
||||||
import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidator } from 'src/app/pages/validators';
|
import {
|
||||||
|
containsLowerCaseValidator,
|
||||||
|
containsNumberValidator,
|
||||||
|
containsSymbolValidator,
|
||||||
|
containsUpperCaseValidator,
|
||||||
|
minLengthValidator,
|
||||||
|
passwordConfirmValidator,
|
||||||
|
requiredValidator,
|
||||||
|
} from 'src/app/modules/form-field/validators/validators';
|
||||||
import { PasswordComplexityPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
import { PasswordComplexityPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||||
import { ToastService } from 'src/app/services/toast.service';
|
import { ToastService } from 'src/app/services/toast.service';
|
||||||
|
|
||||||
function passwordConfirmValidator(c: AbstractControl): any {
|
|
||||||
if (!c.parent || !c) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const pwd = c.parent.get('password');
|
|
||||||
const cpwd = c.parent.get('confirmPassword');
|
|
||||||
|
|
||||||
if (!pwd || !cpwd) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pwd.value !== cpwd.value) {
|
|
||||||
return { invalid: true, notequal: 'Password is not equal' };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cnsl-password',
|
selector: 'cnsl-password',
|
||||||
templateUrl: './password.component.html',
|
templateUrl: './password.component.html',
|
||||||
@ -76,7 +69,7 @@ export class PasswordComponent implements OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const validators: Validators[] = [Validators.required];
|
const validators: Validators[] = [requiredValidator];
|
||||||
this.authService
|
this.authService
|
||||||
.getMyPasswordComplexityPolicy()
|
.getMyPasswordComplexityPolicy()
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
@ -84,19 +77,19 @@ export class PasswordComponent implements OnDestroy {
|
|||||||
this.policy = resp.policy;
|
this.policy = resp.policy;
|
||||||
}
|
}
|
||||||
if (this.policy.minLength) {
|
if (this.policy.minLength) {
|
||||||
validators.push(Validators.minLength(this.policy.minLength));
|
validators.push(minLengthValidator(this.policy.minLength));
|
||||||
}
|
}
|
||||||
if (this.policy.hasLowercase) {
|
if (this.policy.hasLowercase) {
|
||||||
validators.push(lowerCaseValidator);
|
validators.push(containsLowerCaseValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasUppercase) {
|
if (this.policy.hasUppercase) {
|
||||||
validators.push(upperCaseValidator);
|
validators.push(containsUpperCaseValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasNumber) {
|
if (this.policy.hasNumber) {
|
||||||
validators.push(numberValidator);
|
validators.push(containsNumberValidator);
|
||||||
}
|
}
|
||||||
if (this.policy.hasSymbol) {
|
if (this.policy.hasSymbol) {
|
||||||
validators.push(symbolValidator);
|
validators.push(containsSymbolValidator);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setupForm(validators);
|
this.setupForm(validators);
|
||||||
@ -117,13 +110,13 @@ export class PasswordComponent implements OnDestroy {
|
|||||||
if (this.userId) {
|
if (this.userId) {
|
||||||
this.passwordForm = this.fb.group({
|
this.passwordForm = this.fb.group({
|
||||||
password: ['', validators],
|
password: ['', validators],
|
||||||
confirmPassword: ['', [...validators, passwordConfirmValidator]],
|
confirmPassword: ['', [requiredValidator, passwordConfirmValidator()]],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.passwordForm = this.fb.group({
|
this.passwordForm = this.fb.group({
|
||||||
currentPassword: ['', Validators.required],
|
currentPassword: ['', requiredValidator],
|
||||||
newPassword: ['', validators],
|
newPassword: ['', validators],
|
||||||
confirmPassword: ['', [...validators, passwordConfirmValidator]],
|
confirmPassword: ['', [requiredValidator, passwordConfirmValidator()]],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import { MediaMatcher } from '@angular/cdk/layout';
|
import { MediaMatcher } from '@angular/cdk/layout';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Component, EventEmitter, OnInit } from '@angular/core';
|
import { Component, EventEmitter, OnInit } from '@angular/core';
|
||||||
|
import { Validators } from '@angular/forms';
|
||||||
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
|
||||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { Buffer } from 'buffer';
|
import { Buffer } from 'buffer';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
import { ChangeType } from 'src/app/modules/changes/changes.component';
|
import { ChangeType } from 'src/app/modules/changes/changes.component';
|
||||||
|
import { phoneValidator, requiredValidator } from 'src/app/modules/form-field/validators/validators';
|
||||||
import { InfoSectionType } from 'src/app/modules/info-section/info-section.component';
|
import { InfoSectionType } from 'src/app/modules/info-section/info-section.component';
|
||||||
import { MetadataDialogComponent } from 'src/app/modules/metadata/metadata-dialog/metadata-dialog.component';
|
import { MetadataDialogComponent } from 'src/app/modules/metadata/metadata-dialog/metadata-dialog.component';
|
||||||
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
|
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
|
||||||
@ -461,6 +463,7 @@ export class UserDetailComponent implements OnInit {
|
|||||||
descriptionKey: 'USER.LOGINMETHODS.PHONE.EDITDESC',
|
descriptionKey: 'USER.LOGINMETHODS.PHONE.EDITDESC',
|
||||||
value: this.user.human?.phone?.phone,
|
value: this.user.human?.phone?.phone,
|
||||||
type: EditDialogType.PHONE,
|
type: EditDialogType.PHONE,
|
||||||
|
validator: Validators.compose([phoneValidator, requiredValidator]),
|
||||||
},
|
},
|
||||||
width: '400px',
|
width: '400px',
|
||||||
});
|
});
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
import { UntypedFormControl } from '@angular/forms';
|
|
||||||
|
|
||||||
export function symbolValidator(c: UntypedFormControl): any {
|
|
||||||
const REGEXP: RegExp = /[^a-z0-9]/gi;
|
|
||||||
|
|
||||||
return REGEXP.test(c.value)
|
|
||||||
? null
|
|
||||||
: {
|
|
||||||
invalid: true,
|
|
||||||
symbolValidator: {
|
|
||||||
valid: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function numberValidator(c: UntypedFormControl): any {
|
|
||||||
const REGEXP = /[0-9]/g;
|
|
||||||
|
|
||||||
return REGEXP.test(c.value)
|
|
||||||
? null
|
|
||||||
: {
|
|
||||||
invalid: true,
|
|
||||||
numberValidator: {
|
|
||||||
valid: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function upperCaseValidator(c: UntypedFormControl): any {
|
|
||||||
const REGEXP = /[A-Z]/g;
|
|
||||||
|
|
||||||
return REGEXP.test(c.value)
|
|
||||||
? null
|
|
||||||
: {
|
|
||||||
invalid: true,
|
|
||||||
upperCaseValidator: {
|
|
||||||
valid: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function lowerCaseValidator(c: UntypedFormControl): any {
|
|
||||||
const REGEXP = /[a-z]/g;
|
|
||||||
|
|
||||||
return REGEXP.test(c.value)
|
|
||||||
? null
|
|
||||||
: {
|
|
||||||
invalid: true,
|
|
||||||
lowerCaseValidator: {
|
|
||||||
valid: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
@ -239,11 +239,20 @@
|
|||||||
"NOROWS": "Keine Daten"
|
"NOROWS": "Keine Daten"
|
||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "Bitte fülle alle benötigten Felder aus.",
|
"REQUIRED": "Bitte fülle dieses Feld aus.",
|
||||||
"TOKENINVALID": {
|
"TOKENINVALID": {
|
||||||
"TITLE": "Du bist abgemeldet",
|
"TITLE": "Du bist abgemeldet",
|
||||||
"DESCRIPTION": "Klicke auf \"Einloggen\", um Dich erneut anzumelden."
|
"DESCRIPTION": "Klicke auf \"Einloggen\", um Dich erneut anzumelden."
|
||||||
}
|
},
|
||||||
|
"INVALID_FORMAT": "Das Format is ungültig.",
|
||||||
|
"NOTANEMAIL": "Der eingegebene Wert ist keine E-Mail Adresse.",
|
||||||
|
"MINLENGTH": "Muss mindestens {{requiredLength}} Zeichen lang sein.",
|
||||||
|
"UPPERCASEMISSING": "Muss einen Grossbuchstaben beinhalten.",
|
||||||
|
"LOWERCASEMISSING": "Muss einen Kleinbuchstaben beinhalten.",
|
||||||
|
"SYMBOLERROR": "Muss ein Symbol/Satzzeichen beinhalten.",
|
||||||
|
"NUMBERERROR": "Muss eine Ziffer beinhalten.",
|
||||||
|
"PWNOTEQUAL": "Die Passwörter stimmen nicht überein.",
|
||||||
|
"PHONE": "Die Telefonnummer muss mit 00 oder + starten."
|
||||||
},
|
},
|
||||||
"USER": {
|
"USER": {
|
||||||
"SETTINGS": {
|
"SETTINGS": {
|
||||||
@ -524,8 +533,7 @@
|
|||||||
"SET": "Passwort neu setzen",
|
"SET": "Passwort neu setzen",
|
||||||
"RESENDNOTIFICATION": "Email zum Zurücksetzen senden",
|
"RESENDNOTIFICATION": "Email zum Zurücksetzen senden",
|
||||||
"REQUIRED": "Bitte prüfe, dass alle notwendigen Felder ausgefüllt sind.",
|
"REQUIRED": "Bitte prüfe, dass alle notwendigen Felder ausgefüllt sind.",
|
||||||
"MINLENGTHERROR": "Muss mindestens {{value}} Zeichen lang sein.",
|
"MINLENGTHERROR": "Muss mindestens {{value}} Zeichen lang sein."
|
||||||
"NOTEQUAL": "Die Passwörter stimmen nicht überein."
|
|
||||||
},
|
},
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
"EMAIL": "E-Mail",
|
"EMAIL": "E-Mail",
|
||||||
@ -579,17 +587,6 @@
|
|||||||
"3": "Nach Rolle filtern"
|
"3": "Nach Rolle filtern"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"VALIDATION": {
|
|
||||||
"INVALIDPATTERN": "Das Passwort erfüllt nicht die vorgegebenen Regeln.",
|
|
||||||
"NOTANEMAIL": "Der eingegebene Wert ist keine E-Mail Adresse.",
|
|
||||||
"REQUIRED": "Das Eingabefeld ist leer.",
|
|
||||||
"MINLENGTH": "Das Passwort muss mindestens {{requiredLength}} Zeichen lang sein.",
|
|
||||||
"NOEMAIL": "Benutzername darf keine E-Mail-Adresse sein.",
|
|
||||||
"UPPERCASEMISSING": "Muss einen Grossbuchstaben beinhalten.",
|
|
||||||
"LOWERCASEMISSING": "Muss einen Kleinbuchstaben beinhalten.",
|
|
||||||
"SYMBOLERROR": "Muss ein Symbol/Satzzeichen beinhalten.",
|
|
||||||
"NUMBERERROR": "Muss eine Ziffer beinhalten."
|
|
||||||
},
|
|
||||||
"STATE": {
|
"STATE": {
|
||||||
"0": "Unbekannt",
|
"0": "Unbekannt",
|
||||||
"1": "Aktiv",
|
"1": "Aktiv",
|
||||||
|
@ -240,11 +240,20 @@
|
|||||||
"NOROWS": "No data"
|
"NOROWS": "No data"
|
||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "Some required fields are missing.",
|
"REQUIRED": "Please fill in this field.",
|
||||||
"TOKENINVALID": {
|
"TOKENINVALID": {
|
||||||
"TITLE": "Your authorization token has expired.",
|
"TITLE": "Your authorization token has expired.",
|
||||||
"DESCRIPTION": "Click the button below to log in again."
|
"DESCRIPTION": "Click the button below to log in again."
|
||||||
}
|
},
|
||||||
|
"INVALID_FORMAT": "The formatting is invalid.",
|
||||||
|
"NOTANEMAIL": "The given value is not an e-mail address.",
|
||||||
|
"MINLENGTH": "Must be at least {{requiredLength}} characters long.",
|
||||||
|
"UPPERCASEMISSING": "Must include an uppercase character.",
|
||||||
|
"LOWERCASEMISSING": "Must include a lowercase character.",
|
||||||
|
"SYMBOLERROR": "Must include a symbol or punctuation mark.",
|
||||||
|
"NUMBERERROR": "Must include a digit.",
|
||||||
|
"PWNOTEQUAL": "The passwords provided do not match.",
|
||||||
|
"PHONE": "The phone number must start with 00 or +."
|
||||||
},
|
},
|
||||||
"USER": {
|
"USER": {
|
||||||
"SETTINGS": {
|
"SETTINGS": {
|
||||||
@ -525,8 +534,7 @@
|
|||||||
"SET": "Set New Password",
|
"SET": "Set New Password",
|
||||||
"RESENDNOTIFICATION": "Send Password Reset Link",
|
"RESENDNOTIFICATION": "Send Password Reset Link",
|
||||||
"REQUIRED": "Some required fields are missing.",
|
"REQUIRED": "Some required fields are missing.",
|
||||||
"MINLENGTHERROR": "Has to be at least {{value}} characters long.",
|
"MINLENGTHERROR": "Has to be at least {{value}} characters long."
|
||||||
"NOTEQUAL": "The passwords provided do not match."
|
|
||||||
},
|
},
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
"EMAIL": "E-mail",
|
"EMAIL": "E-mail",
|
||||||
@ -580,17 +588,6 @@
|
|||||||
"3": "filter for rolename"
|
"3": "filter for rolename"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"VALIDATION": {
|
|
||||||
"INVALIDPATTERN": "The password does not fulfil the defined rules.",
|
|
||||||
"NOTANEMAIL": "The given value is not an e-mail address",
|
|
||||||
"REQUIRED": "The input field is empty.",
|
|
||||||
"MINLENGTH": "The password has to be at least {{requiredLength}} characters long.",
|
|
||||||
"NOEMAIL": "The user name cannot be an e-mail address.",
|
|
||||||
"UPPERCASEMISSING": "Must include an uppercase character.",
|
|
||||||
"LOWERCASEMISSING": "Must include a lowercase character.",
|
|
||||||
"SYMBOLERROR": "Must include a symbol or punctuation mark.",
|
|
||||||
"NUMBERERROR": "Must include a digit."
|
|
||||||
},
|
|
||||||
"STATE": {
|
"STATE": {
|
||||||
"0": "Unknown",
|
"0": "Unknown",
|
||||||
"1": "Active",
|
"1": "Active",
|
||||||
|
@ -239,11 +239,20 @@
|
|||||||
"NOROWS": "Pas de données"
|
"NOROWS": "Pas de données"
|
||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "Certains champs obligatoires sont manquants.",
|
"REQUIRED": "Remplis ce champ s'il te plaît.",
|
||||||
"TOKENINVALID": {
|
"TOKENINVALID": {
|
||||||
"TITLE": "Votre jeton d'autorisation a expiré.",
|
"TITLE": "Votre jeton d'autorisation a expiré.",
|
||||||
"DESCRIPTION": "Cliquez sur le bouton ci-dessous pour vous reconnecter."
|
"DESCRIPTION": "Cliquez sur le bouton ci-dessous pour vous reconnecter."
|
||||||
}
|
},
|
||||||
|
"INVALID_FORMAT": "Le format n'est pas valide",
|
||||||
|
"NOTANEMAIL": "La valeur donnée n'est pas une adresse e-mail",
|
||||||
|
"MINLENGTH": "Doit comporter au moins {{length}} caractères.",
|
||||||
|
"UPPERCASEMISSING": "Doit inclure un caractère majuscule.",
|
||||||
|
"LOWERCASEMISSING": "Doit inclure un caractère minuscule.",
|
||||||
|
"SYMBOLERROR": "Doit inclure un symbole ou un signe de ponctuation.",
|
||||||
|
"NUMBERERROR": "Doit inclure un chiffre.",
|
||||||
|
"PWNOTEQUAL": "Les mots de passe fournis ne correspondent pas.",
|
||||||
|
"PHONE": "Le numéro de téléphone doit commencer par 00 ou +."
|
||||||
},
|
},
|
||||||
"USER": {
|
"USER": {
|
||||||
"SETTINGS": {
|
"SETTINGS": {
|
||||||
@ -524,8 +533,7 @@
|
|||||||
"SET": "Définir un nouveau mot de passe",
|
"SET": "Définir un nouveau mot de passe",
|
||||||
"RESENDNOTIFICATION": "Envoyer le lien de réinitialisation du mot de passe",
|
"RESENDNOTIFICATION": "Envoyer le lien de réinitialisation du mot de passe",
|
||||||
"REQUIRED": "Certains champs obligatoires sont manquants.",
|
"REQUIRED": "Certains champs obligatoires sont manquants.",
|
||||||
"MINLENGTHERROR": "Doit comporter au moins {{value}} caractères.",
|
"MINLENGTHERROR": "Doit comporter au moins {{value}} caractères."
|
||||||
"NOTEQUAL": "Les mots de passe fournis ne correspondent pas."
|
|
||||||
},
|
},
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
"EMAIL": "E-mail",
|
"EMAIL": "E-mail",
|
||||||
@ -579,17 +587,6 @@
|
|||||||
"3": "filtre pour nom de rôle"
|
"3": "filtre pour nom de rôle"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"VALIDATION": {
|
|
||||||
"INVALIDPATTERN": "Le mot de passe ne répond pas aux règles définies.",
|
|
||||||
"NOTANEMAIL": "La valeur donnée n'est pas une adresse e-mail",
|
|
||||||
"REQUIRED": "Le champ de saisie est vide.",
|
|
||||||
"MINLENGTH": "Le mot de passe doit comporter au moins{{length}} caractères.",
|
|
||||||
"NOEMAIL": "Le nom d'utilisateur ne peut pas être une adresse électronique.",
|
|
||||||
"UPPERCASEMISSING": "Doit inclure un caractère majuscule.",
|
|
||||||
"LOWERCASEMISSING": "Doit inclure un caractère minuscule.",
|
|
||||||
"SYMBOLERROR": "Doit inclure un symbole ou un signe de ponctuation.",
|
|
||||||
"NUMBERERROR": "Doit inclure un chiffre."
|
|
||||||
},
|
|
||||||
"STATE": {
|
"STATE": {
|
||||||
"0": "Inconnu",
|
"0": "Inconnu",
|
||||||
"1": "Actif",
|
"1": "Actif",
|
||||||
|
@ -239,11 +239,20 @@
|
|||||||
"NOROWS": "Nessun dato"
|
"NOROWS": "Nessun dato"
|
||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "Mancano alcuni campi obbligatori.",
|
"REQUIRED": "Compilare questo campo.",
|
||||||
"TOKENINVALID": {
|
"TOKENINVALID": {
|
||||||
"TITLE": "Il tuo Access Token \u00e8 scaduto.",
|
"TITLE": "Il tuo Access Token \u00e8 scaduto.",
|
||||||
"DESCRIPTION": "Clicca il pulsante per richiedere una nuova sessione."
|
"DESCRIPTION": "Clicca il pulsante per richiedere una nuova sessione."
|
||||||
}
|
},
|
||||||
|
"INVALID_FORMAT": "Il formato non è valido.",
|
||||||
|
"NOTANEMAIL": "Il valore dato non \u00e8 un indirizzo e-mail.",
|
||||||
|
"MINLENGTH": "Deve essere lunga almeno {{requiredLength}} caratteri.",
|
||||||
|
"UPPERCASEMISSING": "Deve includere un carattere maiuscolo.",
|
||||||
|
"LOWERCASEMISSING": "Deve includere un carattere minuscolo.",
|
||||||
|
"SYMBOLERROR": "Deve includere un simbolo o un segno di punteggiatura.",
|
||||||
|
"NUMBERERROR": "Deve includere una cifra.",
|
||||||
|
"PWNOTEQUAL": "Le password fornite non corrispondono.",
|
||||||
|
"PHONE": "Il numero di telefono deve iniziare con 00 o +."
|
||||||
},
|
},
|
||||||
"USER": {
|
"USER": {
|
||||||
"SETTINGS": {
|
"SETTINGS": {
|
||||||
@ -524,8 +533,7 @@
|
|||||||
"SET": "Imposta nuova password",
|
"SET": "Imposta nuova password",
|
||||||
"RESENDNOTIFICATION": "Invia email per la reimpostazione",
|
"RESENDNOTIFICATION": "Invia email per la reimpostazione",
|
||||||
"REQUIRED": "Mancano alcuni campi obbligatori.",
|
"REQUIRED": "Mancano alcuni campi obbligatori.",
|
||||||
"MINLENGTHERROR": "Deve essere lunga almeno {{valore}} caratteri.",
|
"MINLENGTHERROR": "Deve essere lunga almeno {{valore}} caratteri."
|
||||||
"NOTEQUAL": "Le password fornite non corrispondono."
|
|
||||||
},
|
},
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
"EMAIL": "E-mail",
|
"EMAIL": "E-mail",
|
||||||
@ -579,17 +587,6 @@
|
|||||||
"3": "filtro per rolename"
|
"3": "filtro per rolename"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"VALIDATION": {
|
|
||||||
"INVALIDPATTERN": "La password non soddisfa le regole definite.",
|
|
||||||
"NOTANEMAIL": "Il valore dato non \u00e8 un indirizzo e-mail",
|
|
||||||
"REQUIRED": "Il campo di input \u00e8 vuoto.",
|
|
||||||
"MINLENGTH": "Deve essere lunga almeno {{requiredLength}} caratteri.",
|
|
||||||
"NOEMAIL": "Il nome utente non pu\u00f2 essere un indirizzo e-mail.",
|
|
||||||
"UPPERCASEMISSING": "Deve includere un carattere maiuscolo.",
|
|
||||||
"LOWERCASEMISSING": "Deve includere un carattere minuscolo.",
|
|
||||||
"SYMBOLERROR": "Deve includere un simbolo o un segno di punteggiatura.",
|
|
||||||
"NUMBERERROR": "Deve includere una cifra."
|
|
||||||
},
|
|
||||||
"STATE": {
|
"STATE": {
|
||||||
"0": "Sconosciuto",
|
"0": "Sconosciuto",
|
||||||
"1": "Attivo",
|
"1": "Attivo",
|
||||||
|
@ -239,11 +239,20 @@
|
|||||||
"NOROWS": "Brak danych"
|
"NOROWS": "Brak danych"
|
||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "Brakuje niektórych wymaganych pól.",
|
"REQUIRED": "Proszę wypełnić to pole.",
|
||||||
"TOKENINVALID": {
|
"TOKENINVALID": {
|
||||||
"TITLE": "Twój token autoryzacji wygasł.",
|
"TITLE": "Twój token autoryzacji wygasł.",
|
||||||
"DESCRIPTION": "Kliknij przycisk poniżej, aby ponownie się zalogować."
|
"DESCRIPTION": "Kliknij przycisk poniżej, aby ponownie się zalogować."
|
||||||
}
|
},
|
||||||
|
"INVALID_FORMAT": "Format jest nieprawidłowy.",
|
||||||
|
"NOTANEMAIL": "Podana wartość nie jest adresem e-mail.",
|
||||||
|
"MINLENGTH": "Musi mieć co najmniej {{requiredLength}} znaków.",
|
||||||
|
"UPPERCASEMISSING": "Musi zawierać wielką literę.",
|
||||||
|
"LOWERCASEMISSING": "Musi zawierać małą literę.",
|
||||||
|
"SYMBOLERROR": "Musi zawierać symbol lub znak interpunkcyjny.",
|
||||||
|
"NUMBERERROR": "Musi zawierać cyfrę.",
|
||||||
|
"PWNOTEQUAL": "Podane hasła nie są identyczne.",
|
||||||
|
"PHONE": "Numer telefonu musi zaczynać się od 00 lub +."
|
||||||
},
|
},
|
||||||
"USER": {
|
"USER": {
|
||||||
"SETTINGS": {
|
"SETTINGS": {
|
||||||
@ -524,8 +533,7 @@
|
|||||||
"SET": "Ustaw nowe hasło",
|
"SET": "Ustaw nowe hasło",
|
||||||
"RESENDNOTIFICATION": "Wyślij link resetowania hasła",
|
"RESENDNOTIFICATION": "Wyślij link resetowania hasła",
|
||||||
"REQUIRED": "Brakuje niektórych wymaganych pól.",
|
"REQUIRED": "Brakuje niektórych wymaganych pól.",
|
||||||
"MINLENGTHERROR": "Musi mieć co najmniej {{value}} znaków.",
|
"MINLENGTHERROR": "Musi mieć co najmniej {{value}} znaków."
|
||||||
"NOTEQUAL": "Podane hasła nie są identyczne."
|
|
||||||
},
|
},
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
"EMAIL": "E-mail",
|
"EMAIL": "E-mail",
|
||||||
@ -579,17 +587,6 @@
|
|||||||
"3": "filtruj po roli"
|
"3": "filtruj po roli"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"VALIDATION": {
|
|
||||||
"INVALIDPATTERN": "Hasło nie spełnia określonych reguł.",
|
|
||||||
"NOTANEMAIL": "Podana wartość nie jest adresem e-mail",
|
|
||||||
"REQUIRED": "Pole jest puste.",
|
|
||||||
"MINLENGTH": "Hasło musi mieć co najmniej {{requiredLength}} znaków.",
|
|
||||||
"NOEMAIL": "Nazwa użytkownika nie może być adresem e-mail.",
|
|
||||||
"UPPERCASEMISSING": "Musi zawierać wielką literę.",
|
|
||||||
"LOWERCASEMISSING": "Musi zawierać małą literę.",
|
|
||||||
"SYMBOLERROR": "Musi zawierać symbol lub znak interpunkcyjny.",
|
|
||||||
"NUMBERERROR": "Musi zawierać cyfrę."
|
|
||||||
},
|
|
||||||
"STATE": {
|
"STATE": {
|
||||||
"0": "Nieznany",
|
"0": "Nieznany",
|
||||||
"1": "Aktywny",
|
"1": "Aktywny",
|
||||||
|
@ -239,11 +239,20 @@
|
|||||||
"NOROWS": "没有数据"
|
"NOROWS": "没有数据"
|
||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "缺少一些必填字段。",
|
"REQUIRED": "请填写此栏",
|
||||||
"TOKENINVALID": {
|
"TOKENINVALID": {
|
||||||
"TITLE": "您的授权令牌已过期。",
|
"TITLE": "您的授权令牌已过期。",
|
||||||
"DESCRIPTION": "点击下方按钮再次登录。"
|
"DESCRIPTION": "点击下方按钮再次登录。"
|
||||||
}
|
},
|
||||||
|
"INVALID_FORMAT": "格式是无效的。",
|
||||||
|
"NOTANEMAIL": "给定的值不是合法电子邮件地址。",
|
||||||
|
"MINLENGTH": "长度必须至少是{{requiredLength}}字符。",
|
||||||
|
"UPPERCASEMISSING": "密码必须包含大写字符。",
|
||||||
|
"LOWERCASEMISSING": "密码必须包含小写字符。",
|
||||||
|
"SYMBOLERROR": "密码必须包含符号或标点符号。",
|
||||||
|
"NUMBERERROR": "密码必须包含数字。",
|
||||||
|
"PWNOTEQUAL": "提供的密码不匹配。",
|
||||||
|
"PHONE": "电话号码必须以00或+开头。"
|
||||||
},
|
},
|
||||||
"USER": {
|
"USER": {
|
||||||
"SETTINGS": {
|
"SETTINGS": {
|
||||||
@ -524,8 +533,7 @@
|
|||||||
"SET": "设置新密码",
|
"SET": "设置新密码",
|
||||||
"RESENDNOTIFICATION": "发送重置密码链接",
|
"RESENDNOTIFICATION": "发送重置密码链接",
|
||||||
"REQUIRED": "缺少必填字段。",
|
"REQUIRED": "缺少必填字段。",
|
||||||
"MINLENGTHERROR": "密码长度必须至少为 {{value}} 个字符。",
|
"MINLENGTHERROR": "密码长度必须至少为 {{value}} 个字符。"
|
||||||
"NOTEQUAL": "提供的密码不匹配。"
|
|
||||||
},
|
},
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
"EMAIL": "电子邮件",
|
"EMAIL": "电子邮件",
|
||||||
@ -579,17 +587,6 @@
|
|||||||
"3": "过滤角色名称"
|
"3": "过滤角色名称"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"VALIDATION": {
|
|
||||||
"INVALIDPATTERN": "密码不符合定义的规则。",
|
|
||||||
"NOTANEMAIL": "给定的值不是合法电子邮件地址",
|
|
||||||
"REQUIRED": "输入字段为空。",
|
|
||||||
"MINLENGTH": "密码长度必须至少为 {{requiredLength}} 个字符。",
|
|
||||||
"NOEMAIL": "用户名不能是电子邮件地址。",
|
|
||||||
"UPPERCASEMISSING": "密码必须包含大写字符。",
|
|
||||||
"LOWERCASEMISSING": "密码必须包含小写字符。",
|
|
||||||
"SYMBOLERROR": "密码必须包含符号或标点符号。",
|
|
||||||
"NUMBERERROR": "密码必须包含数字。"
|
|
||||||
},
|
|
||||||
"STATE": {
|
"STATE": {
|
||||||
"0": "未知",
|
"0": "未知",
|
||||||
"1": "启用",
|
"1": "启用",
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
@import './styles/color.scss';
|
@import './styles/color.scss';
|
||||||
@import 'src/app/pages/instance/instance.component.scss';
|
@import 'src/app/pages/instance/instance.component.scss';
|
||||||
@import 'src/app/modules/refresh-table/refresh-table.component.scss';
|
@import 'src/app/modules/refresh-table/refresh-table.component.scss';
|
||||||
@import 'src/app/modules/form-field/form-field.component.scss';
|
@import 'src/app/modules/form-field/field/form-field.component.scss';
|
||||||
@import 'src/app/modules/label/label.component.scss';
|
@import 'src/app/modules/label/label.component.scss';
|
||||||
@import 'src/app/modules/meta-layout/meta.scss';
|
@import 'src/app/modules/meta-layout/meta.scss';
|
||||||
@import 'src/app/pages/projects/owned-projects/project-grant-detail/project-grant-illustration/project-grant-illustration.component';
|
@import 'src/app/pages/projects/owned-projects/project-grant-detail/project-grant-illustration/project-grant-illustration.component';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user