mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-07 23:57:42 +00:00
fix(console): LDAP UI optimization for better required field recognition, improve onboarding all done visibility (#5659)
* fix: onboarding all done styles * ldap UI change * rm log * set required marker to formfield, max width of string-list comp * seperate formfields * formarray * clear action * validator * hide pwd field * rm dead code * lint
This commit is contained in:
parent
0ed2906b5d
commit
c420de1533
@ -1,5 +1,14 @@
|
|||||||
|
<ng-template #labelTemplate>
|
||||||
|
<label class="cnsl-label-wrapper" [attr.for]="_control.id" [attr.aria-owns]="_control.id">
|
||||||
|
<ng-content select="cnsl-label"></ng-content>
|
||||||
|
<span *ngIf="_control.required && !hideRequiredMarker" aria-hidden="true" class="cnsl-form-field-required-marker"
|
||||||
|
>*</span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
<div class="cnsl-form-field-wrapper" (click)="_control.onContainerClick && _control.onContainerClick($event)">
|
<div class="cnsl-form-field-wrapper" (click)="_control.onContainerClick && _control.onContainerClick($event)">
|
||||||
<ng-content select="cnsl-label"></ng-content>
|
<ng-template [ngTemplateOutlet]="labelTemplate"></ng-template>
|
||||||
<div class="cnsl-rel" #inputContainer>
|
<div class="cnsl-rel" #inputContainer>
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
<ng-content select="cnslSuffix"></ng-content>
|
<ng-content select="cnslSuffix"></ng-content>
|
||||||
|
@ -51,6 +51,7 @@ interface ValidationError {
|
|||||||
'[class.ng-valid]': '_shouldForward("valid")',
|
'[class.ng-valid]': '_shouldForward("valid")',
|
||||||
'[class.ng-invalid]': '_shouldForward("invalid")',
|
'[class.ng-invalid]': '_shouldForward("invalid")',
|
||||||
'[class.ng-pending]': '_shouldForward("pending")',
|
'[class.ng-pending]': '_shouldForward("pending")',
|
||||||
|
'[class.ng-required]': '_control.required',
|
||||||
'[class.cnsl-form-field-disabled]': '_control.disabled',
|
'[class.cnsl-form-field-disabled]': '_control.disabled',
|
||||||
'[class.cnsl-form-field-autofilled]': '_control.autofilled',
|
'[class.cnsl-form-field-autofilled]': '_control.autofilled',
|
||||||
'[class.cnsl-focused]': '_control.focused',
|
'[class.cnsl-focused]': '_control.focused',
|
||||||
@ -69,6 +70,7 @@ export class CnslFormFieldComponent extends CnslFormFieldBase implements OnDestr
|
|||||||
@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;
|
@Input() public disableValidationErrors = false;
|
||||||
|
@Input() public hideRequiredMarker = false;
|
||||||
|
|
||||||
get _control(): MatFormFieldControl<any> {
|
get _control(): MatFormFieldControl<any> {
|
||||||
return this._explicitFormFieldControl || this._controlNonStatic || this._controlStatic;
|
return this._explicitFormFieldControl || this._controlNonStatic || this._controlStatic;
|
||||||
|
@ -24,6 +24,12 @@ export function requiredValidator(c: AbstractControl): ValidationErrors | null {
|
|||||||
return i18nErr(Validators.required(c), 'ERRORS.REQUIRED');
|
return i18nErr(Validators.required(c), 'ERRORS.REQUIRED');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function minArrayLengthValidator(minArrLength: number): ValidatorFn {
|
||||||
|
return (c: AbstractControl): ValidationErrors | null => {
|
||||||
|
return arrayLengthValidator(c, minArrLength, 'ERRORS.ATLEASTONE');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function emailValidator(c: AbstractControl): ValidationErrors | null {
|
export function emailValidator(c: AbstractControl): ValidationErrors | null {
|
||||||
return i18nErr(Validators.email(c), 'ERRORS.NOTANEMAIL');
|
return i18nErr(Validators.email(c), 'ERRORS.NOTANEMAIL');
|
||||||
}
|
}
|
||||||
@ -56,6 +62,12 @@ function regexpValidator(c: AbstractControl, regexp: RegExp, i18nKey: string): V
|
|||||||
return !c.value || regexp.test(c.value) ? null : i18nErr({ invalid: true }, i18nKey, { regexp: regexp });
|
return !c.value || regexp.test(c.value) ? null : i18nErr({ invalid: true }, i18nKey, { regexp: regexp });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function arrayLengthValidator(c: AbstractControl, length: number, i18nKey: string): ValidationErrors | null {
|
||||||
|
const arr: string[] = c.value;
|
||||||
|
const invalidStrings: string[] = arr.filter((val: string) => val.trim() === '');
|
||||||
|
return arr && invalidStrings.length === 0 && arr.length >= length ? null : i18nErr({ invalid: true }, i18nKey);
|
||||||
|
}
|
||||||
|
|
||||||
function i18nErr(err: ValidationErrors | null | undefined, i18nKey: string, params?: any): ValidationErrors | null {
|
function i18nErr(err: ValidationErrors | null | undefined, i18nKey: string, params?: any): ValidationErrors | null {
|
||||||
if (err === null) {
|
if (err === null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -9,23 +9,31 @@
|
|||||||
$foreground: map-get($theme, foreground);
|
$foreground: map-get($theme, foreground);
|
||||||
$secondary-text: map-get($foreground, secondary-text);
|
$secondary-text: map-get($foreground, secondary-text);
|
||||||
|
|
||||||
.cnsl-label {
|
.cnsl-label-wrapper {
|
||||||
display: block;
|
display: flex;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: $secondary-text;
|
color: $secondary-text;
|
||||||
transition: color 0.2s ease;
|
transition: color 0.2s ease;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
|
.cnsl-label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cnsl-form-field-required-marker {
|
||||||
|
margin-left: 1px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cnsl-form-field-disabled {
|
.cnsl-form-field-disabled {
|
||||||
.cnsl-label {
|
.cnsl-label-wrapper {
|
||||||
color: if($is-dark-theme, #ffffff80, #00000061);
|
color: if($is-dark-theme, #ffffff80, #00000061);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cnsl-form-field-invalid {
|
.cnsl-form-field-invalid {
|
||||||
.cnsl-label {
|
.cnsl-label-wrapper {
|
||||||
color: $warn-color;
|
color: $warn-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,6 +198,12 @@
|
|||||||
.state-circle {
|
.state-circle {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.action-card {
|
||||||
|
.action-content {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,54 +1,65 @@
|
|||||||
<form [formGroup]="form" class="attribute-form">
|
<form [formGroup]="form" class="attribute-form">
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'IDP.LDAPIDATTRIBUTE' | translate }}*</cnsl-label>
|
<cnsl-label>{{ 'IDP.LDAPIDATTRIBUTE' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="idAttribute" />
|
<input cnslInput formControlName="idAttribute" required />
|
||||||
</cnsl-form-field>
|
|
||||||
<cnsl-form-field class="formfield">
|
|
||||||
<cnsl-label>{{ 'IDP.AVATARURLATTRIBUTE' | translate }}</cnsl-label>
|
|
||||||
<input cnslInput formControlName="avatarUrlAttribute" />
|
|
||||||
</cnsl-form-field>
|
|
||||||
<cnsl-form-field class="formfield">
|
|
||||||
<cnsl-label>{{ 'IDP.DISPLAYNAMEATTRIBUTE' | translate }}</cnsl-label>
|
|
||||||
<input cnslInput formControlName="displayNameAttribute" />
|
|
||||||
</cnsl-form-field>
|
|
||||||
<cnsl-form-field class="formfield">
|
|
||||||
<cnsl-label>{{ 'IDP.EMAILATTRIBUTEATTRIBUTE' | translate }}</cnsl-label>
|
|
||||||
<input cnslInput formControlName="emailAttribute" />
|
|
||||||
</cnsl-form-field>
|
|
||||||
<cnsl-form-field class="formfield">
|
|
||||||
<cnsl-label>{{ 'IDP.EMAILVERIFIEDATTRIBUTE' | translate }}</cnsl-label>
|
|
||||||
<input cnslInput formControlName="emailVerifiedAttribute" />
|
|
||||||
</cnsl-form-field>
|
|
||||||
<cnsl-form-field class="formfield">
|
|
||||||
<cnsl-label>{{ 'IDP.FIRSTNAMEATTRIBUTE' | translate }}</cnsl-label>
|
|
||||||
<input cnslInput formControlName="firstNameAttribute" />
|
|
||||||
</cnsl-form-field>
|
|
||||||
<cnsl-form-field class="formfield">
|
|
||||||
<cnsl-label>{{ 'IDP.LASTNAMEATTRIBUTE' | translate }}</cnsl-label>
|
|
||||||
<input cnslInput formControlName="lastNameAttribute" />
|
|
||||||
</cnsl-form-field>
|
|
||||||
<cnsl-form-field class="formfield">
|
|
||||||
<cnsl-label>{{ 'IDP.NICKNAMEATTRIBUTE' | translate }}</cnsl-label>
|
|
||||||
<input cnslInput formControlName="nickNameAttribute" />
|
|
||||||
</cnsl-form-field>
|
|
||||||
<cnsl-form-field class="formfield">
|
|
||||||
<cnsl-label>{{ 'IDP.PHONEATTRIBUTE' | translate }}</cnsl-label>
|
|
||||||
<input cnslInput formControlName="phoneAttribute" />
|
|
||||||
</cnsl-form-field>
|
|
||||||
<cnsl-form-field class="formfield">
|
|
||||||
<cnsl-label>{{ 'IDP.PHONEVERIFIEDATTRIBUTE' | translate }}</cnsl-label>
|
|
||||||
<input cnslInput formControlName="phoneVerifiedAttribute" />
|
|
||||||
</cnsl-form-field>
|
|
||||||
<cnsl-form-field class="formfield">
|
|
||||||
<cnsl-label>{{ 'IDP.PREFERREDLANGUAGEATTRIBUTE' | translate }}</cnsl-label>
|
|
||||||
<input cnslInput formControlName="preferredLanguageAttribute" />
|
|
||||||
</cnsl-form-field>
|
|
||||||
<cnsl-form-field class="formfield">
|
|
||||||
<cnsl-label>{{ 'IDP.PREFERREDUSERNAMEATTRIBUTE' | translate }}</cnsl-label>
|
|
||||||
<input cnslInput formControlName="preferredUsernameAttribute" />
|
|
||||||
</cnsl-form-field>
|
|
||||||
<cnsl-form-field class="formfield">
|
|
||||||
<cnsl-label>{{ 'IDP.PROFILEATTRIBUTE' | translate }}</cnsl-label>
|
|
||||||
<input cnslInput formControlName="profileAttribute" />
|
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
|
<div class="attribute-more-row">
|
||||||
|
<span>{{ 'ACTIONS.MORE' | translate }}</span>
|
||||||
|
<button (click)="showMore = !showMore" type="button" mat-icon-button>
|
||||||
|
<mat-icon *ngIf="showMore">keyboard_arrow_up</mat-icon>
|
||||||
|
<mat-icon *ngIf="!showMore">keyboard_arrow_down</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="showMore">
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{ 'IDP.AVATARURLATTRIBUTE' | translate }}</cnsl-label>
|
||||||
|
<input cnslInput formControlName="avatarUrlAttribute" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{ 'IDP.DISPLAYNAMEATTRIBUTE' | translate }}</cnsl-label>
|
||||||
|
<input cnslInput formControlName="displayNameAttribute" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{ 'IDP.EMAILATTRIBUTEATTRIBUTE' | translate }}</cnsl-label>
|
||||||
|
<input cnslInput formControlName="emailAttribute" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{ 'IDP.EMAILVERIFIEDATTRIBUTE' | translate }}</cnsl-label>
|
||||||
|
<input cnslInput formControlName="emailVerifiedAttribute" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{ 'IDP.FIRSTNAMEATTRIBUTE' | translate }}</cnsl-label>
|
||||||
|
<input cnslInput formControlName="firstNameAttribute" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{ 'IDP.LASTNAMEATTRIBUTE' | translate }}</cnsl-label>
|
||||||
|
<input cnslInput formControlName="lastNameAttribute" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{ 'IDP.NICKNAMEATTRIBUTE' | translate }}</cnsl-label>
|
||||||
|
<input cnslInput formControlName="nickNameAttribute" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{ 'IDP.PHONEATTRIBUTE' | translate }}</cnsl-label>
|
||||||
|
<input cnslInput formControlName="phoneAttribute" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{ 'IDP.PHONEVERIFIEDATTRIBUTE' | translate }}</cnsl-label>
|
||||||
|
<input cnslInput formControlName="phoneVerifiedAttribute" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{ 'IDP.PREFERREDLANGUAGEATTRIBUTE' | translate }}</cnsl-label>
|
||||||
|
<input cnslInput formControlName="preferredLanguageAttribute" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{ 'IDP.PREFERREDUSERNAMEATTRIBUTE' | translate }}</cnsl-label>
|
||||||
|
<input cnslInput formControlName="preferredUsernameAttribute" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
<cnsl-form-field class="formfield">
|
||||||
|
<cnsl-label>{{ 'IDP.PROFILEATTRIBUTE' | translate }}</cnsl-label>
|
||||||
|
<input cnslInput formControlName="profileAttribute" />
|
||||||
|
</cnsl-form-field>
|
||||||
|
</ng-container>
|
||||||
</form>
|
</form>
|
||||||
|
@ -4,3 +4,8 @@
|
|||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
padding-bottom: 1rem;
|
padding-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.attribute-more-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
@ -29,6 +29,7 @@ export class LDAPAttributesComponent implements OnChanges, OnDestroy {
|
|||||||
profileAttribute: new FormControl('', []),
|
profileAttribute: new FormControl('', []),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public showMore: boolean = false;
|
||||||
constructor() {
|
constructor() {
|
||||||
this.form.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => {
|
this.form.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((value) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
|
@ -17,12 +17,13 @@
|
|||||||
<div class="identity-provider-content">
|
<div class="identity-provider-content">
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'IDP.NAME' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'IDP.NAME' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="name" />
|
<input cnslInput formControlName="name" required />
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
<h2 class="subheader">{{ 'IDP.LDAPCONNECTION' | translate }}</h2>
|
<h2 class="subheader">{{ 'IDP.LDAPCONNECTION' | translate }}</h2>
|
||||||
|
|
||||||
<cnsl-string-list
|
<cnsl-string-list
|
||||||
|
class="string-list-component-wrapper"
|
||||||
title="{{ 'IDP.SERVERS' | translate }}"
|
title="{{ 'IDP.SERVERS' | translate }}"
|
||||||
formControlName="serversList"
|
formControlName="serversList"
|
||||||
[required]="true"
|
[required]="true"
|
||||||
@ -30,13 +31,13 @@
|
|||||||
|
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'IDP.BASEDN' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'IDP.BASEDN' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="baseDn" />
|
<input cnslInput formControlName="baseDn" required />
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
<div [ngClass]="{ 'identity-provider-2-col': !provider }">
|
<div [ngClass]="{ 'identity-provider-2-col': !provider }">
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'IDP.BINDDN' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'IDP.BINDDN' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="bindDn" />
|
<input cnslInput formControlName="bindDn" required />
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
<mat-checkbox
|
<mat-checkbox
|
||||||
@ -46,14 +47,14 @@
|
|||||||
[ngModelOptions]="{ standalone: true }"
|
[ngModelOptions]="{ standalone: true }"
|
||||||
>{{ 'IDP.UPDATEBINDPASSWORD' | translate }}</mat-checkbox
|
>{{ 'IDP.UPDATEBINDPASSWORD' | translate }}</mat-checkbox
|
||||||
>
|
>
|
||||||
<cnsl-form-field *ngIf="!provider || (provider && updateBindPassword)" class="formfield">
|
<cnsl-form-field class="formfield pwd" [ngClass]="{ show: !provider || (provider && updateBindPassword) }">
|
||||||
<cnsl-label>{{ 'IDP.BINDPASSWORD' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'IDP.BINDPASSWORD' | translate }}</cnsl-label>
|
||||||
<input
|
<input
|
||||||
cnslInput
|
cnslInput
|
||||||
name="bindpassword"
|
|
||||||
formControlName="bindPassword"
|
formControlName="bindPassword"
|
||||||
type="password"
|
type="password"
|
||||||
autocomplete="new-password"
|
autocomplete="new-password"
|
||||||
|
[required]="!provider"
|
||||||
/>
|
/>
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
</div>
|
</div>
|
||||||
@ -62,16 +63,18 @@
|
|||||||
|
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
<cnsl-label>{{ 'IDP.USERBASE' | translate }}</cnsl-label>
|
<cnsl-label>{{ 'IDP.USERBASE' | translate }}</cnsl-label>
|
||||||
<input cnslInput formControlName="userBase" />
|
<input cnslInput formControlName="userBase" required />
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
|
|
||||||
<cnsl-string-list
|
<cnsl-string-list
|
||||||
|
class="string-list-component-wrapper"
|
||||||
title="{{ 'IDP.USERFILTERS' | translate }}"
|
title="{{ 'IDP.USERFILTERS' | translate }}"
|
||||||
formControlName="userFiltersList"
|
formControlName="userFiltersList"
|
||||||
[required]="true"
|
[required]="true"
|
||||||
></cnsl-string-list>
|
></cnsl-string-list>
|
||||||
|
|
||||||
<cnsl-string-list
|
<cnsl-string-list
|
||||||
|
class="string-list-component-wrapper"
|
||||||
title="{{ 'IDP.USEROBJECTCLASSES' | translate }}"
|
title="{{ 'IDP.USEROBJECTCLASSES' | translate }}"
|
||||||
formControlName="userObjectClassesList"
|
formControlName="userObjectClassesList"
|
||||||
[required]="true"
|
[required]="true"
|
||||||
@ -79,22 +82,11 @@
|
|||||||
|
|
||||||
<div class="identity-provider-optional-h-wrapper">
|
<div class="identity-provider-optional-h-wrapper">
|
||||||
<h2>{{ 'IDP.LDAPATTRIBUTES' | translate }}</h2>
|
<h2>{{ 'IDP.LDAPATTRIBUTES' | translate }}</h2>
|
||||||
|
|
||||||
<button (click)="showAttributes = !showAttributes" type="button" mat-icon-button>
|
|
||||||
<mat-icon *ngIf="showAttributes">keyboard_arrow_up</mat-icon>
|
|
||||||
<mat-icon *ngIf="!showAttributes">keyboard_arrow_down</mat-icon>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<span *ngIf="!provider?.config?.ldap?.attributes?.idAttribute" class="state error">{{
|
|
||||||
'IDP.REQUIRED' | translate
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="showAttributes">
|
|
||||||
<cnsl-ldap-attributes
|
|
||||||
[initialAttributes]="provider?.config?.ldap?.attributes"
|
|
||||||
(attributesChanged)="attributes = $event"
|
|
||||||
></cnsl-ldap-attributes>
|
|
||||||
</div>
|
</div>
|
||||||
|
<cnsl-ldap-attributes
|
||||||
|
[initialAttributes]="provider?.config?.ldap?.attributes"
|
||||||
|
(attributesChanged)="attributes = $event"
|
||||||
|
></cnsl-ldap-attributes>
|
||||||
|
|
||||||
<div class="identity-provider-optional-h-wrapper">
|
<div class="identity-provider-optional-h-wrapper">
|
||||||
<h2>{{ 'IDP.OPTIONAL' | translate }}</h2>
|
<h2>{{ 'IDP.OPTIONAL' | translate }}</h2>
|
||||||
@ -123,7 +115,7 @@
|
|||||||
color="primary"
|
color="primary"
|
||||||
mat-raised-button
|
mat-raised-button
|
||||||
class="continue-button"
|
class="continue-button"
|
||||||
[disabled]="form.invalid || attributes.toObject().idAttribute === '' || form.disabled"
|
[disabled]="!form.valid || !attributes.toObject().idAttribute || form.disabled"
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
<span *ngIf="id">{{ 'ACTIONS.SAVE' | translate }}</span>
|
<span *ngIf="id">{{ 'ACTIONS.SAVE' | translate }}</span>
|
||||||
|
@ -20,7 +20,7 @@ import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/
|
|||||||
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 { minArrayLengthValidator, requiredValidator } from '../../form-field/validators/validators';
|
||||||
|
|
||||||
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
import { PolicyComponentServiceType } from '../../policies/policy-component-types.enum';
|
||||||
|
|
||||||
@ -30,7 +30,6 @@ import { PolicyComponentServiceType } from '../../policies/policy-component-type
|
|||||||
})
|
})
|
||||||
export class ProviderLDAPComponent {
|
export class ProviderLDAPComponent {
|
||||||
public updateBindPassword: boolean = false;
|
public updateBindPassword: boolean = false;
|
||||||
public showAttributes: boolean = false;
|
|
||||||
public showOptional: boolean = false;
|
public showOptional: boolean = false;
|
||||||
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
|
public options: Options = new Options().setIsCreationAllowed(true).setIsLinkingAllowed(true);
|
||||||
public attributes: LDAPAttributes = new LDAPAttributes();
|
public attributes: LDAPAttributes = new LDAPAttributes();
|
||||||
@ -54,15 +53,15 @@ export class ProviderLDAPComponent {
|
|||||||
) {
|
) {
|
||||||
this.form = new FormGroup({
|
this.form = new FormGroup({
|
||||||
name: new FormControl('', [requiredValidator]),
|
name: new FormControl('', [requiredValidator]),
|
||||||
serversList: new FormControl('', [requiredValidator]),
|
serversList: new FormControl<string[]>([''], [minArrayLengthValidator(1)]),
|
||||||
baseDn: new FormControl('', [requiredValidator]),
|
baseDn: new FormControl('', [requiredValidator]),
|
||||||
bindDn: new FormControl('', [requiredValidator]),
|
bindDn: new FormControl('', [requiredValidator]),
|
||||||
bindPassword: new FormControl('', [requiredValidator]),
|
bindPassword: new FormControl('', [requiredValidator]),
|
||||||
userBase: new FormControl('', [requiredValidator]),
|
userBase: new FormControl('', [requiredValidator]),
|
||||||
userFiltersList: new FormControl('', [requiredValidator]),
|
userFiltersList: new FormControl<string[]>([''], [minArrayLengthValidator(1)]),
|
||||||
userObjectClassesList: new FormControl('', [requiredValidator]),
|
userObjectClassesList: new FormControl<string[]>([''], [minArrayLengthValidator(1)]),
|
||||||
timeout: new FormControl<number>(0),
|
timeout: new FormControl<number>(0),
|
||||||
startTls: new FormControl(false),
|
startTls: new FormControl<boolean>(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.authService
|
this.authService
|
||||||
@ -112,6 +111,7 @@ export class ProviderLDAPComponent {
|
|||||||
if (this.id) {
|
if (this.id) {
|
||||||
this.getData(this.id);
|
this.getData(this.id);
|
||||||
this.bindPassword?.setValidators([]);
|
this.bindPassword?.setValidators([]);
|
||||||
|
this.bindPassword?.updateValueAndValidity();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -125,12 +125,25 @@ export class ProviderLDAPComponent {
|
|||||||
this.service
|
this.service
|
||||||
.getProviderByID(req)
|
.getProviderByID(req)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
this.provider = resp.idp;
|
if (resp.idp) {
|
||||||
this.loading = false;
|
this.provider = resp.idp;
|
||||||
if (this.provider?.config?.ldap) {
|
this.loading = false;
|
||||||
this.form.patchValue(this.provider.config.ldap);
|
|
||||||
this.name?.setValue(this.provider.name);
|
this.name?.setValue(this.provider.name);
|
||||||
this.timeout?.setValue(this.provider.config.ldap.timeout?.seconds);
|
|
||||||
|
const config = this.provider?.config?.ldap;
|
||||||
|
if (config) {
|
||||||
|
this.serversList?.setValue(config.serversList);
|
||||||
|
this.startTls?.setValue(config.startTls);
|
||||||
|
this.baseDn?.setValue(config.baseDn);
|
||||||
|
this.bindDn?.setValue(config.bindDn);
|
||||||
|
this.userBase?.setValue(config.userBase);
|
||||||
|
this.userObjectClassesList?.setValue(config.userObjectClassesList);
|
||||||
|
this.userFiltersList?.setValue(config.userFiltersList);
|
||||||
|
if (this.provider?.config?.ldap?.timeout?.seconds) {
|
||||||
|
this.timeout?.setValue(this.provider?.config?.ldap?.timeout?.seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
@use '@angular/material' as mat;
|
||||||
|
|
||||||
@mixin identity-provider-theme($theme) {
|
@mixin identity-provider-theme($theme) {
|
||||||
$is-dark-theme: map-get($theme, is-dark);
|
$is-dark-theme: map-get($theme, is-dark);
|
||||||
|
$background: map-get($theme, background);
|
||||||
|
|
||||||
.identity-provider-desc {
|
.identity-provider-desc {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@ -44,6 +47,14 @@
|
|||||||
display: block;
|
display: block;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
|
|
||||||
|
&.pwd {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pwd.show {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.name-hint {
|
.name-hint {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
@ -63,6 +74,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.string-list-component-wrapper {
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
.identity-provider-content {
|
.identity-provider-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -1,30 +1,43 @@
|
|||||||
<form class="string-list-form" (ngSubmit)="add(redInput)">
|
<div class="form-array-list">
|
||||||
<cnsl-form-field class="formfield">
|
<div class="form-field-list">
|
||||||
<cnsl-label>{{ title }}</cnsl-label>
|
<div class="list-header-wrapper">
|
||||||
<input #redInput cnslInput [formControl]="control" />
|
<p class="list-header cnsl-secondary-text">{{ title }}*</p>
|
||||||
</cnsl-form-field>
|
<button
|
||||||
<button
|
class="add-element-btn"
|
||||||
matTooltip="{{ 'ACTIONS.ADD' | translate }}"
|
matTooltip="{{ 'ACTIONS.ADD' | translate }}"
|
||||||
type="submit"
|
type="button"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
[disabled]="control.invalid || control.disabled"
|
(click)="addArrayEntry()"
|
||||||
>
|
>
|
||||||
<mat-icon>add</mat-icon>
|
<mat-icon>add</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</div>
|
||||||
|
<ng-container *ngFor="let formControl of formArray.controls; index as i">
|
||||||
|
<div class="element-row">
|
||||||
|
<cnsl-form-field class="formfield" [hideRequiredMarker]="true">
|
||||||
|
<input cnslInput title="{{ 'IDP.SERVERS' | translate }}" [formControl]="$any(formControl)" required />
|
||||||
|
</cnsl-form-field>
|
||||||
|
|
||||||
<div class="string-list">
|
<button
|
||||||
<div *ngFor="let str of value" class="value-line">
|
class="add-element-btn"
|
||||||
<span>{{ str }}</span>
|
[disabled]="i === 0 && formArray.controls.length === 1 && formControl.value === ''"
|
||||||
<span class="fill-space"></span>
|
[matTooltip]="
|
||||||
<button
|
i === 0 && formArray.controls.length === 1 ? ('ACTIONS.CLEAR' | translate) : ('ACTIONS.REMOVE' | translate)
|
||||||
type="button"
|
"
|
||||||
matTooltip="{{ 'ACTIONS.DELETE' | translate }}"
|
type="button"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
(click)="remove(str)"
|
color="warn"
|
||||||
class="icon-button"
|
(click)="i === 0 && formArray.controls.length === 1 ? clearEntryAtIndex(i) : removeEntryAtIndex(i)"
|
||||||
>
|
>
|
||||||
<mat-icon class="icon">cancel</mat-icon>
|
<i *ngIf="i === 0 && formArray.controls.length === 1; else removeIcon" class="las la-times-circle"></i>
|
||||||
</button>
|
<ng-template #removeIcon>
|
||||||
|
<i class="las la-minus-circle"></i>
|
||||||
|
</ng-template>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
<span class="control-error" *ngIf="control.touched && control.errors && control.errors['errorsatleastone']">{{
|
||||||
|
control.errors['errorsatleastone'].i18nKey | translate
|
||||||
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,56 +5,50 @@
|
|||||||
$background: map-get($theme, background);
|
$background: map-get($theme, background);
|
||||||
$is-dark-theme: map-get($theme, is-dark);
|
$is-dark-theme: map-get($theme, is-dark);
|
||||||
$warn: map-get($theme, warn);
|
$warn: map-get($theme, warn);
|
||||||
$warn-color: map-get($warn, 500);
|
$warncolor: map-get($warn, 500);
|
||||||
$button-text-color: map-get($foreground, text);
|
|
||||||
$button-disabled-text-color: map-get($foreground, disabled-button);
|
|
||||||
$divider-color: map-get($foreground, dividers);
|
|
||||||
$secondary-text: map-get($foreground, secondary-text);
|
|
||||||
|
|
||||||
.string-list {
|
.form-array-list {
|
||||||
width: 100%;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
|
background: if($is-dark-theme, #00000020, mat.get-color-from-palette($background, cards));
|
||||||
|
margin-left: -1rem;
|
||||||
|
margin-right: -1rem;
|
||||||
|
padding: 0 1rem 0.5rem 1rem;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
|
||||||
.value-line {
|
.list-header-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 0.5rem 0;
|
margin: 0.5rem -0.5rem 0 0;
|
||||||
padding: 0 0 0 0.75rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: map-get($background, infosection);
|
|
||||||
|
|
||||||
.fill-space {
|
.list-header {
|
||||||
flex: 1;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.icon-button {
|
.form-field-list {
|
||||||
height: 30px;
|
flex: 1;
|
||||||
line-height: 30px;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
.icon {
|
.element-row {
|
||||||
font-size: 1rem;
|
display: flex;
|
||||||
margin-bottom: 3px;
|
align-items: center;
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:hover) {
|
.formfield {
|
||||||
color: $secondary-text;
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.control-error {
|
||||||
|
font-size: 12px;
|
||||||
|
color: $warncolor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-element-btn {
|
||||||
|
margin-bottom: 0rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.string-list-form {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-end;
|
|
||||||
min-width: 320px;
|
|
||||||
|
|
||||||
.formfield {
|
|
||||||
width: 500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin-bottom: 0.9rem;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component, forwardRef, Input, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
import { Component, forwardRef, Input, OnDestroy, ViewChildren, ViewEncapsulation } from '@angular/core';
|
||||||
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
|
import { ControlValueAccessor, FormArray, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
import { Observable, Subject, takeUntil } from 'rxjs';
|
import { distinctUntilChanged, Subject, takeUntil } from 'rxjs';
|
||||||
import { requiredValidator } from '../form-field/validators/validators';
|
import { minArrayLengthValidator, requiredValidator } from '../form-field/validators/validators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cnsl-string-list',
|
selector: 'cnsl-string-list',
|
||||||
@ -16,22 +16,23 @@ import { requiredValidator } from '../form-field/validators/validators';
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class StringListComponent implements ControlValueAccessor, OnInit, OnDestroy {
|
export class StringListComponent implements ControlValueAccessor, OnDestroy {
|
||||||
@Input() title: string = '';
|
@Input() title: string = '';
|
||||||
@Input() required: boolean = false;
|
@Input() required: boolean = false;
|
||||||
@Input() public getValues: Observable<void> = new Observable(); // adds formfieldinput to array on emission
|
|
||||||
|
|
||||||
@Input() public control: FormControl = new FormControl<string>({ value: '', disabled: true });
|
@Input() public control: FormControl = new FormControl<string[]>({ value: [], disabled: true });
|
||||||
|
|
||||||
private destroy$: Subject<void> = new Subject();
|
private destroy$: Subject<void> = new Subject();
|
||||||
@ViewChild('redInput') input!: any;
|
@ViewChildren('stringInput') input!: any[];
|
||||||
private val: string[] = [];
|
public val: string[] = [];
|
||||||
|
|
||||||
ngOnInit(): void {
|
public formArray: FormArray = new FormArray([new FormControl('', [requiredValidator])]);
|
||||||
this.getValues.pipe(takeUntil(this.destroy$)).subscribe(() => {
|
|
||||||
this.add(this.input.nativeElement);
|
constructor() {
|
||||||
|
this.control.setValidators([minArrayLengthValidator(1)]);
|
||||||
|
this.formArray.valueChanges.pipe(takeUntil(this.destroy$), distinctUntilChanged()).subscribe((value) => {
|
||||||
|
this.value = value;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.required ? this.control.setValidators([requiredValidator]) : this.control.setValidators([]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
@ -50,12 +51,24 @@ export class StringListComponent implements ControlValueAccessor, OnInit, OnDest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addArrayEntry() {
|
||||||
|
this.formArray.push(new FormControl('', [requiredValidator]));
|
||||||
|
}
|
||||||
|
|
||||||
|
removeEntryAtIndex(index: number) {
|
||||||
|
this.formArray.removeAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearEntryAtIndex(index: number) {
|
||||||
|
this.formArray.controls[index].setValue('');
|
||||||
|
}
|
||||||
get value() {
|
get value() {
|
||||||
return this.val;
|
return this.val;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeValue(value: string[]) {
|
writeValue(value: string[]) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
value.map((v, i) => this.formArray.setControl(i, new FormControl(v, [requiredValidator])));
|
||||||
}
|
}
|
||||||
|
|
||||||
registerOnChange(fn: any) {
|
registerOnChange(fn: any) {
|
||||||
@ -73,28 +86,4 @@ export class StringListComponent implements ControlValueAccessor, OnInit, OnDest
|
|||||||
this.control.enable();
|
this.control.enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public add(input: any): void {
|
|
||||||
if (this.control.valid) {
|
|
||||||
const trimmed = input.value.trim();
|
|
||||||
if (trimmed) {
|
|
||||||
this.val ? this.val.push(input.value) : (this.val = [input.value]);
|
|
||||||
this.onChange(this.val);
|
|
||||||
this.onTouch(this.val);
|
|
||||||
}
|
|
||||||
if (input) {
|
|
||||||
input.value = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public remove(str: string): void {
|
|
||||||
const index = this.value.indexOf(str);
|
|
||||||
|
|
||||||
if (index >= 0) {
|
|
||||||
this.value.splice(index, 1);
|
|
||||||
this.onChange(this.value);
|
|
||||||
this.onTouch(this.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { NgModule } from '@angular/core';
|
|||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatLegacyButtonModule } from '@angular/material/legacy-button';
|
import { MatLegacyButtonModule } from '@angular/material/legacy-button';
|
||||||
|
import { MatLegacyChipsModule } from '@angular/material/legacy-chips';
|
||||||
import { MatLegacyTooltipModule } from '@angular/material/legacy-tooltip';
|
import { MatLegacyTooltipModule } from '@angular/material/legacy-tooltip';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { InputModule } from '../input/input.module';
|
import { InputModule } from '../input/input.module';
|
||||||
@ -15,6 +16,7 @@ import { StringListComponent } from './string-list.component';
|
|||||||
InputModule,
|
InputModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
|
MatLegacyChipsModule,
|
||||||
TranslateModule,
|
TranslateModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
MatLegacyTooltipModule,
|
MatLegacyTooltipModule,
|
||||||
|
@ -10,11 +10,11 @@
|
|||||||
<form *ngIf="userForm" [formGroup]="userForm" (ngSubmit)="createUser()" class="machine-create-form">
|
<form *ngIf="userForm" [formGroup]="userForm" (ngSubmit)="createUser()" class="machine-create-form">
|
||||||
<div class="machine-create-content">
|
<div class="machine-create-content">
|
||||||
<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 />
|
||||||
</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 />
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field class="formfield">
|
<cnsl-form-field class="formfield">
|
||||||
|
@ -13,11 +13,11 @@
|
|||||||
|
|
||||||
<div class="user-create-grid">
|
<div class="user-create-grid">
|
||||||
<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 />
|
||||||
</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>
|
||||||
<input
|
<input
|
||||||
cnslInput
|
cnslInput
|
||||||
formControlName="userName"
|
formControlName="userName"
|
||||||
@ -28,11 +28,11 @@
|
|||||||
</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 />
|
||||||
</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 />
|
||||||
</cnsl-form-field>
|
</cnsl-form-field>
|
||||||
<cnsl-form-field>
|
<cnsl-form-field>
|
||||||
|
@ -247,6 +247,7 @@
|
|||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "Bitte fülle dieses Feld aus.",
|
"REQUIRED": "Bitte fülle dieses Feld aus.",
|
||||||
|
"ATLEASTONE": "Geben Sie mindestens einen Wert an.",
|
||||||
"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."
|
||||||
|
@ -248,6 +248,7 @@
|
|||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "Please fill in this field.",
|
"REQUIRED": "Please fill in this field.",
|
||||||
|
"ATLEASTONE": "Provide at least one value.",
|
||||||
"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."
|
||||||
|
@ -248,6 +248,7 @@
|
|||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "Por favor rellena este campo.",
|
"REQUIRED": "Por favor rellena este campo.",
|
||||||
|
"ATLEASTONE": "Proporcione al menos un valor.",
|
||||||
"TOKENINVALID": {
|
"TOKENINVALID": {
|
||||||
"TITLE": "Tu token de autorización token ha caducado.",
|
"TITLE": "Tu token de autorización token ha caducado.",
|
||||||
"DESCRIPTION": "Haz clic en el botón más abajo para iniciar sesión otra vez."
|
"DESCRIPTION": "Haz clic en el botón más abajo para iniciar sesión otra vez."
|
||||||
|
@ -247,6 +247,7 @@
|
|||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "Remplis ce champ s'il te plaît.",
|
"REQUIRED": "Remplis ce champ s'il te plaît.",
|
||||||
|
"ATLEASTONE": "Indiquez au moins une valeur.",
|
||||||
"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."
|
||||||
|
@ -247,6 +247,7 @@
|
|||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "Compilare questo campo.",
|
"REQUIRED": "Compilare questo campo.",
|
||||||
|
"ATLEASTONE": "Inserisci almeno un valore.",
|
||||||
"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."
|
||||||
|
@ -248,6 +248,7 @@
|
|||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "一部の必須項目が不足しています。",
|
"REQUIRED": "一部の必須項目が不足しています。",
|
||||||
|
"ATLEASTONE": "少なくとも 1 つの値を指定してください。",
|
||||||
"TOKENINVALID": {
|
"TOKENINVALID": {
|
||||||
"TITLE": "トークンが期限切れになりました。",
|
"TITLE": "トークンが期限切れになりました。",
|
||||||
"DESCRIPTION": "下のボタンをクリックして、もう一度ログインする。"
|
"DESCRIPTION": "下のボタンをクリックして、もう一度ログインする。"
|
||||||
|
@ -247,6 +247,7 @@
|
|||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "Proszę wypełnić to pole.",
|
"REQUIRED": "Proszę wypełnić to pole.",
|
||||||
|
"ATLEASTONE": "Podaj co najmniej jedną wartość.",
|
||||||
"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ć."
|
||||||
|
@ -247,6 +247,7 @@
|
|||||||
},
|
},
|
||||||
"ERRORS": {
|
"ERRORS": {
|
||||||
"REQUIRED": "请填写此栏",
|
"REQUIRED": "请填写此栏",
|
||||||
|
"ATLEASTONE": "P至少提供一个值。",
|
||||||
"TOKENINVALID": {
|
"TOKENINVALID": {
|
||||||
"TITLE": "您的授权令牌已过期。",
|
"TITLE": "您的授权令牌已过期。",
|
||||||
"DESCRIPTION": "点击下方按钮再次登录。"
|
"DESCRIPTION": "点击下方按钮再次登录。"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user