fix(console, login): Idp detail and create layout optimization, login - sub formfield link spacing (#3755)

* idp detail, create layout

* fat finger fix

Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
Max Peintner 2022-06-03 09:20:56 +02:00 committed by GitHub
parent 0c14614d02
commit ebb73186b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 389 additions and 307 deletions

View File

@ -26,11 +26,11 @@
<form [formGroup]="oidcFormGroup" (ngSubmit)="addOIDCIdp()"> <form [formGroup]="oidcFormGroup" (ngSubmit)="addOIDCIdp()">
<div class="idp-content"> <div class="idp-content">
<cnsl-form-field appearance="outline" 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" />
</cnsl-form-field> </cnsl-form-field>
<cnsl-form-field appearance="outline" class="formfield"> <cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.ISSUER' | translate }}</cnsl-label> <cnsl-label>{{ 'IDP.ISSUER' | translate }}</cnsl-label>
<input cnslInput formControlName="issuer" /> <input cnslInput formControlName="issuer" />
</cnsl-form-field> </cnsl-form-field>
@ -46,40 +46,53 @@
</cnsl-info-section> </cnsl-info-section>
<div class="idp-content"> <div class="idp-content">
<cnsl-form-field appearance="outline" class="formfield"> <cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.CLIENTID' | translate }}</cnsl-label> <cnsl-label>{{ 'IDP.CLIENTID' | translate }}</cnsl-label>
<input cnslInput formControlName="clientId" /> <input cnslInput formControlName="clientId" />
</cnsl-form-field> </cnsl-form-field>
<cnsl-form-field appearance="outline" class="formfield"> <cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.CLIENTSECRET' | translate }}</cnsl-label> <cnsl-label>{{ 'IDP.CLIENTSECRET' | translate }}</cnsl-label>
<input cnslInput formControlName="clientSecret" /> <input cnslInput formControlName="clientSecret" />
</cnsl-form-field> </cnsl-form-field>
</div> </div>
<div class="idp-content"> <div class="idp-content">
<cnsl-form-field appearance="outline" class="formfield"> <cnsl-card class="scope-card">
<cnsl-label>{{ 'IDP.SCOPESLIST' | translate }}</cnsl-label> <div class="idp-scopes">
<mat-chip-list #chipScopesList aria-label="scope selection" *ngIf="scopesList"> <div class="flex-line">
<mat-chip <cnsl-form-field class="formfield">
class="chip" <cnsl-label>{{ 'IDP.SCOPESLIST' | translate }}</cnsl-label>
*ngFor="let scope of scopesList.value"
selectable="false" <input
removable cnslInput
(removed)="removeScope(scope)" [matChipInputFor]="chipScopesList"
> [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
{{ scope }} <mat-icon matChipRemove>cancel</mat-icon> [matChipInputAddOnBlur]="true"
</mat-chip> (matChipInputTokenEnd)="addScope($event)"
<input />
cnslInput </cnsl-form-field>
[matChipInputFor]="chipScopesList" <button class="scope-add-button" (click)="addScope($any($event))" mat-icon-button>
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" <mat-icon>add</mat-icon>
[matChipInputAddOnBlur]="true" </button>
(matChipInputTokenEnd)="addScope($event)" </div>
/>
</mat-chip-list> <cnsl-form-field class="formfield">
</cnsl-form-field> <mat-chip-list #chipScopesList aria-label="scope selection">
<mat-chip
class="chip"
*ngFor="let scope of scopesList?.value"
selectable="false"
removable
(removed)="removeScope(scope)"
>
{{ scope }} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
</cnsl-form-field>
</div>
</cnsl-card>
</div> </div>
<div class="idp-content"> <div class="idp-content">
<cnsl-form-field class="formfield" appearance="outline"> <cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.IDPDISPLAYNAMMAPPING' | translate }}</cnsl-label> <cnsl-label>{{ 'IDP.IDPDISPLAYNAMMAPPING' | translate }}</cnsl-label>
<mat-select formControlName="idpDisplayNameMapping"> <mat-select formControlName="idpDisplayNameMapping">
<mat-option *ngFor="let field of mappingFields" [value]="field"> <mat-option *ngFor="let field of mappingFields" [value]="field">
@ -87,7 +100,7 @@
</mat-option> </mat-option>
</mat-select> </mat-select>
</cnsl-form-field> </cnsl-form-field>
<cnsl-form-field class="formfield" appearance="outline"> <cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.USERNAMEMAPPING' | translate }}</cnsl-label> <cnsl-label>{{ 'IDP.USERNAMEMAPPING' | translate }}</cnsl-label>
<mat-select formControlName="usernameMapping"> <mat-select formControlName="usernameMapping">
<mat-option *ngFor="let field of mappingFields" [value]="field"> <mat-option *ngFor="let field of mappingFields" [value]="field">
@ -113,15 +126,15 @@
<form [formGroup]="jwtFormGroup" (ngSubmit)="addJWTIdp()"> <form [formGroup]="jwtFormGroup" (ngSubmit)="addJWTIdp()">
<div class="idp-content"> <div class="idp-content">
<cnsl-form-field appearance="outline" class="formfield"> <cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.NAME' | translate }}</cnsl-label> <cnsl-label>{{ 'IDP.NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="jwtName" /> <input cnslInput formControlName="jwtName" />
</cnsl-form-field> </cnsl-form-field>
<cnsl-form-field appearance="outline" class="formfield"> <cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.JWT.HEADERNAME' | translate }}</cnsl-label> <cnsl-label>{{ 'IDP.JWT.HEADERNAME' | translate }}</cnsl-label>
<input cnslInput formControlName="jwtHeaderName" /> <input cnslInput formControlName="jwtHeaderName" />
</cnsl-form-field> </cnsl-form-field>
<cnsl-form-field appearance="outline" class="formfield"> <cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.ISSUER' | translate }}</cnsl-label> <cnsl-label>{{ 'IDP.ISSUER' | translate }}</cnsl-label>
<input cnslInput formControlName="jwtIssuer" /> <input cnslInput formControlName="jwtIssuer" />
</cnsl-form-field> </cnsl-form-field>
@ -137,11 +150,11 @@
</cnsl-info-section> </cnsl-info-section>
<div class="idp-content"> <div class="idp-content">
<cnsl-form-field appearance="outline" class="formfield"> <cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.JWT.JWTENDPOINT' | translate }}</cnsl-label> <cnsl-label>{{ 'IDP.JWT.JWTENDPOINT' | translate }}</cnsl-label>
<input cnslInput formControlName="jwtEndpoint" /> <input cnslInput formControlName="jwtEndpoint" />
</cnsl-form-field> </cnsl-form-field>
<cnsl-form-field appearance="outline" class="formfield"> <cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.JWT.JWTKEYSENDPOINT' | translate }}</cnsl-label> <cnsl-label>{{ 'IDP.JWT.JWTKEYSENDPOINT' | translate }}</cnsl-label>
<input cnslInput formControlName="jwtKeysEndpoint" /> <input cnslInput formControlName="jwtKeysEndpoint" />
</cnsl-form-field> </cnsl-form-field>

View File

@ -13,43 +13,71 @@
.auto-reg-info { .auto-reg-info {
display: block; display: block;
width: 100%; width: 100%;
max-width: 400px;
.auto-reg-desc { .auto-reg-desc {
margin: 0 0 1rem 0; margin: 0 0 1rem 0;
} }
} }
.idp-content { .idp-create-content {
display: flex;
margin: 0 -0.5rem;
flex-wrap: wrap;
.desc {
flex-basis: 100%;
margin: 0 0.5rem;
margin-bottom: 1rem;
}
.formfield { .formfield {
flex: 1; display: block;
margin: 0 0.5rem; max-width: 400px;
.mat-chip-input {
width: 100%;
margin: 0;
}
.chip {
border-radius: 0.5rem;
height: 40px;
}
@media only screen and (max-width: 450px) { @media only screen and (max-width: 450px) {
flex-basis: 100%; max-width: none;
}
}
.idp-content {
.desc {
margin-bottom: 1rem;
}
.scope-card {
max-width: 400px;
display: block;
.idp-scopes {
.flex-line {
display: flex;
align-items: flex-start;
.formfield {
flex: 1;
}
.scope-add-button {
margin-top: 1.75rem;
}
}
}
} }
} }
} }
.idp-create-actions { .idp-create-actions {
display: flex; display: flex;
justify-content: space-between;
margin-top: 1rem; margin-top: 1rem;
button[mat-stroked-button] { button[mat-stroked-button] {
border-radius: 0.5rem; border-radius: 0.5rem;
margin-right: 1rem;
} }
button[mat-raised-button] { button[mat-raised-button] {
border-radius: 0.5rem; border-radius: 0.5rem;
margin-right: 1rem;
} }
} }

View File

@ -171,15 +171,16 @@ export class IdpCreateComponent implements OnInit, OnDestroy {
.then((idp) => { .then((idp) => {
setTimeout(() => { setTimeout(() => {
this.loading = false; this.loading = false;
this.router.navigate([ this.router.navigate(
this.serviceType === PolicyComponentServiceType.MGMT [
? 'org' this.serviceType === PolicyComponentServiceType.MGMT
: this.serviceType === PolicyComponentServiceType.ADMIN ? '/org-settings'
? 'iam' : this.serviceType === PolicyComponentServiceType.ADMIN
: '', ? '/settings'
'policy', : '',
'login', ],
]); { queryParams: { id: 'idp' } },
);
}, 2000); }, 2000);
}) })
.catch((error) => { .catch((error) => {

View File

@ -11,6 +11,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { InputModule } from 'src/app/modules/input/input.module'; import { InputModule } from 'src/app/modules/input/input.module';
import { CardModule } from '../card/card.module';
import { CreateLayoutModule } from '../create-layout/create-layout.module'; import { CreateLayoutModule } from '../create-layout/create-layout.module';
import { InfoSectionModule } from '../info-section/info-section.module'; import { InfoSectionModule } from '../info-section/info-section.module';
import { IdpCreateRoutingModule } from './idp-create-routing.module'; import { IdpCreateRoutingModule } from './idp-create-routing.module';
@ -31,6 +32,7 @@ import { IdpTypeRadioComponent } from './idp-type-radio/idp-type-radio.component
MatSelectModule, MatSelectModule,
MatIconModule, MatIconModule,
MatChipsModule, MatChipsModule,
CardModule,
MatCheckboxModule, MatCheckboxModule,
MatTooltipModule, MatTooltipModule,
TranslateModule, TranslateModule,

View File

@ -129,8 +129,8 @@
<ng-container matColumnDef="type"> <ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef>{{ 'IDP.TYPE' | translate }}</th> <th mat-header-cell *matHeaderCellDef>{{ 'IDP.TYPE' | translate }}</th>
<td class="pointer" [routerLink]="routerLinkForRow(idp)" mat-cell *matCellDef="let idp"> <td class="pointer" [routerLink]="routerLinkForRow(idp)" mat-cell *matCellDef="let idp">
<span class="state" *ngIf="idp?.oidcConfig">{{ 'IDP.OIDC.TITLE' | translate }}</span> <span class="state" *ngIf="idp?.oidcConfig">{{ 'IDP.TYPES.1' | translate }}</span>
<span class="state" *ngIf="idp?.jwtConfig">{{ 'IDP.JWT.TITLE' | translate }}</span> <span class="state" *ngIf="idp?.jwtConfig">{{ 'IDP.TYPES.3' | translate }}</span>
</td> </td>
</ng-container> </ng-container>

View File

@ -1,6 +1,6 @@
<cnsl-top-view <cnsl-top-view
title="{{ 'IDP.DETAIL.TITLE' | translate }}" title="{{ idp?.name ? idp.name : ('IDP.DETAIL.TITLE' | translate) }}"
[sub]="idp?.oidcConfig ? ('IDP.OIDC.TITLE' | translate) : idp?.jwtConfig ? ('IDP.JWT.TITLE' | translate) : ''" [sub]="idp?.oidcConfig ? ('IDP.TYPES.1' | translate) : idp?.jwtConfig ? ('IDP.TYPES.3' | translate) : ''"
[isActive]="idp?.state === IDPState.IDP_STATE_ACTIVE" [isActive]="idp?.state === IDPState.IDP_STATE_ACTIVE"
[isInactive]="idp?.state === IDPState.IDP_STATE_INACTIVE" [isInactive]="idp?.state === IDPState.IDP_STATE_INACTIVE"
[hasContributors]="false" [hasContributors]="false"
@ -34,177 +34,192 @@
</cnsl-top-view> </cnsl-top-view>
<div class="max-width-container"> <div class="max-width-container">
<form class="idp-form" (ngSubmit)="updateIdp()"> <div class="idp-wrapper">
<ng-container [formGroup]="idpForm"> <h2>{{ 'IDP.OIDC.GENERAL' | translate }}</h2>
<div class="idp-content">
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.NAME' | translate }}</cnsl-label>
<input cnslInput formControlName="name" />
</cnsl-form-field>
<cnsl-form-field class="formfield" appearance="outline">
<cnsl-label>{{ 'IDP.STYLE' | translate }}</cnsl-label>
<mat-select formControlName="stylingType">
<mat-option *ngFor="let field of styleFields" [value]="field">
{{ 'IDP.STYLEFIELD.' + field | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
<cnsl-info-section class="auto-reg-info"> <form (ngSubmit)="updateIdp()">
<div> <ng-container [formGroup]="idpForm">
<p class="auto-reg-desc">{{ 'IDP.AUTOREGISTER_DESC' | translate }}</p> <div class="idp-content">
<mat-checkbox formControlName="autoRegister" [disabled]="(canWrite | async) === false"> <cnsl-form-field class="idp-formfield">
{{ 'IDP.AUTOREGISTER' | translate }} <cnsl-label>{{ 'IDP.NAME' | translate }}</cnsl-label>
</mat-checkbox> <input cnslInput formControlName="name" />
</div> </cnsl-form-field>
</cnsl-info-section>
<cnsl-form-field class="idp-formfield">
<cnsl-label>{{ 'IDP.STYLE' | translate }}</cnsl-label>
<mat-select formControlName="stylingType">
<mat-option *ngFor="let field of styleFields" [value]="field">
{{ 'IDP.STYLEFIELD.' + field | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
<cnsl-info-section class="auto-reg-info">
<div>
<p class="auto-reg-desc">{{ 'IDP.AUTOREGISTER_DESC' | translate }}</p>
<mat-checkbox formControlName="autoRegister" [disabled]="(canWrite | async) === false">
{{ 'IDP.AUTOREGISTER' | translate }}
</mat-checkbox>
</div>
</cnsl-info-section>
</div>
</ng-container>
<div class="btn-wrapper">
<button
color="primary"
mat-raised-button
class="continue-button"
[disabled]="idpForm.invalid || (canWrite | async) === false"
type="submit"
>
{{ 'ACTIONS.SAVE' | translate }}
</button>
</div> </div>
</form>
<ng-container *ngIf="idp?.oidcConfig && oidcConfigForm">
<h2>{{ 'IDP.OIDC.TITLE' | translate }}</h2>
<p class="idp-desc cnsl-secondary-text">{{ 'IDP.OIDC.DESCRIPTION' | translate }}</p>
<form (ngSubmit)="updateOidcConfig()">
<ng-container [formGroup]="oidcConfigForm">
<div class="idp-content">
<cnsl-form-field class="idp-formfield">
<cnsl-label>{{ 'IDP.ISSUER' | translate }}</cnsl-label>
<input cnslInput formControlName="issuer" />
</cnsl-form-field>
<cnsl-form-field class="idp-formfield">
<cnsl-label>{{ 'IDP.CLIENTID' | translate }}</cnsl-label>
<input cnslInput formControlName="clientId" />
</cnsl-form-field>
<mat-checkbox
class="idp-desc cnsl-secondary-text"
[(ngModel)]="showIdSecretSection"
[disabled]="(canWrite | async) === false"
[ngModelOptions]="{ standalone: true }"
>
Update Client Secret
</mat-checkbox>
<cnsl-form-field class="idp-formfield" *ngIf="showIdSecretSection">
<cnsl-label>{{ 'IDP.CLIENTSECRET' | translate }}</cnsl-label>
<input cnslInput formControlName="clientSecret" />
</cnsl-form-field>
<cnsl-card class="scope-card">
<div class="scope-card-content">
<div class="flex-line">
<cnsl-form-field class="idp-formfield">
<cnsl-label>{{ 'IDP.SCOPESLIST' | translate }}</cnsl-label>
<input
cnslInput
[matChipInputFor]="chipScopesList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addScope($event)"
/>
</cnsl-form-field>
<button (click)="addScope($any($event))" mat-icon-button>
<mat-icon>add</mat-icon>
</button>
</div>
<cnsl-form-field class="idp-formfield">
<mat-chip-list class="chip-list" #chipScopesList aria-label="scope selection">
<mat-chip
class="chip"
*ngFor="let scope of scopesList?.value"
selectable="false"
removable
(removed)="removeScope(scope)"
[disabled]="(canWrite | async) === false"
>
{{ scope }} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
</cnsl-form-field>
</div>
</cnsl-card>
<cnsl-form-field class="idp-formfield">
<cnsl-label>{{ 'IDP.IDPDISPLAYNAMMAPPING' | translate }}</cnsl-label>
<mat-select formControlName="displayNameMapping">
<mat-option *ngFor="let field of mappingFields" [value]="field">
{{ 'IDP.MAPPINGFIELD.' + field | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
<cnsl-form-field class="idp-formfield">
<cnsl-label>{{ 'IDP.USERNAMEMAPPING' | translate }}</cnsl-label>
<mat-select formControlName="usernameMapping">
<mat-option *ngFor="let field of mappingFields" [value]="field">
{{ 'IDP.MAPPINGFIELD.' + field | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
</div>
</ng-container>
<div class="btn-wrapper">
<button
color="primary"
mat-raised-button
class="continue-button"
[disabled]="oidcConfigForm.invalid || (canWrite | async) === false"
type="submit"
>
{{ 'ACTIONS.SAVE' | translate }}
</button>
</div>
</form>
</ng-container> </ng-container>
<div class="btn-wrapper"> <ng-container *ngIf="idp?.jwtConfig && jwtConfigForm">
<button <h2>{{ 'IDP.JWT.TITLE' | translate }}</h2>
color="primary" <p>{{ 'IDP.JWT.DESCRIPTION' | translate }}</p>
mat-raised-button
class="continue-button"
[disabled]="idpForm.invalid || (canWrite | async) === false"
type="submit"
>
{{ 'ACTIONS.SAVE' | translate }}
</button>
</div>
</form>
<ng-container *ngIf="idp?.oidcConfig && oidcConfigForm"> <form (ngSubmit)="updateJwtConfig()">
<h2>{{ 'IDP.OIDC.TITLE' | translate }}</h2> <ng-container [formGroup]="jwtConfigForm">
<p class="idp-desc cnsl-secondary-text">{{ 'IDP.OIDC.DESCRIPTION' | translate }}</p> <div class="idp-content">
<cnsl-form-field class="idp-formfield">
<form (ngSubmit)="updateOidcConfig()"> <cnsl-label>{{ 'IDP.ISSUER' | translate }}</cnsl-label>
<ng-container [formGroup]="oidcConfigForm"> <input cnslInput formControlName="issuer" />
<div class="idp-content"> </cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.ISSUER' | translate }}</cnsl-label> <cnsl-form-field class="idp-formfield">
<input cnslInput formControlName="issuer" /> <cnsl-label>{{ 'IDP.JWT.HEADERNAME' | translate }}</cnsl-label>
</cnsl-form-field> <input cnslInput formControlName="headerName" />
<cnsl-form-field class="formfield"> </cnsl-form-field>
<cnsl-label>{{ 'IDP.CLIENTID' | translate }}</cnsl-label>
<input cnslInput formControlName="clientId" /> <cnsl-form-field class="idp-formfield">
</cnsl-form-field> <cnsl-label>{{ 'IDP.JWT.JWTENDPOINT' | translate }}</cnsl-label>
<mat-checkbox <input cnslInput formControlName="jwtEndpoint" />
class="idp-desc cnsl-secondary-text" </cnsl-form-field>
[(ngModel)]="showIdSecretSection"
[disabled]="(canWrite | async) === false" <cnsl-form-field class="idp-formfield">
[ngModelOptions]="{ standalone: true }" <cnsl-label>{{ 'IDP.JWT.JWTKEYSENDPOINT' | translate }}</cnsl-label>
> <input cnslInput formControlName="keysEndpoint" />
Update Client Secret
</mat-checkbox>
<cnsl-form-field class="formfield" *ngIf="showIdSecretSection">
<cnsl-label>{{ 'IDP.CLIENTSECRET' | translate }}</cnsl-label>
<input cnslInput formControlName="clientSecret" />
</cnsl-form-field>
<div class="line">
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.SCOPESLIST' | translate }}</cnsl-label>
<input
cnslInput
[matChipInputFor]="chipScopesList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addScope($event)"
/>
</cnsl-form-field> </cnsl-form-field>
<button (click)="addScope($any($event))" mat-icon-button>
<mat-icon>add</mat-icon>
</button>
</div> </div>
<cnsl-form-field class="formfield fullwidth"> </ng-container>
<mat-chip-list class="chip-list" #chipScopesList aria-label="scope selection">
<mat-chip
class="chip"
*ngFor="let scope of scopesList?.value"
selectable="false"
removable
(removed)="removeScope(scope)"
[disabled]="(canWrite | async) === false"
>
{{ scope }} <mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
</cnsl-form-field>
<cnsl-form-field class="formfield" appearance="outline"> <div class="btn-wrapper">
<cnsl-label>{{ 'IDP.IDPDISPLAYNAMMAPPING' | translate }}</cnsl-label> <button
<mat-select formControlName="displayNameMapping"> color="primary"
<mat-option *ngFor="let field of mappingFields" [value]="field"> mat-raised-button
{{ 'IDP.MAPPINGFIELD.' + field | translate }} class="continue-button"
</mat-option> [disabled]="jwtConfigForm.invalid || (canWrite | async) === false"
</mat-select> type="submit"
</cnsl-form-field> >
<cnsl-form-field class="formfield" appearance="outline"> {{ 'ACTIONS.SAVE' | translate }}
<cnsl-label>{{ 'IDP.USERNAMEMAPPING' | translate }}</cnsl-label> </button>
<mat-select formControlName="usernameMapping">
<mat-option *ngFor="let field of mappingFields" [value]="field">
{{ 'IDP.MAPPINGFIELD.' + field | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
</div> </div>
</ng-container> </form>
</ng-container>
<div class="btn-wrapper"> </div>
<button
color="primary"
mat-raised-button
class="continue-button"
[disabled]="oidcConfigForm.invalid || (canWrite | async) === false"
type="submit"
>
{{ 'ACTIONS.SAVE' | translate }}
</button>
</div>
</form>
</ng-container>
<ng-container *ngIf="idp?.jwtConfig && jwtConfigForm">
<h2>{{ 'IDP.JWT.TITLE' | translate }}</h2>
<p>{{ 'IDP.JWT.DESCRIPTION' | translate }}</p>
<form (ngSubmit)="updateJwtConfig()">
<ng-container [formGroup]="jwtConfigForm">
<div class="idp-content">
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.ISSUER' | translate }}</cnsl-label>
<input cnslInput formControlName="issuer" />
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.JWT.HEADERNAME' | translate }}</cnsl-label>
<input cnslInput formControlName="headerName" />
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.JWT.JWTENDPOINT' | translate }}</cnsl-label>
<input cnslInput formControlName="jwtEndpoint" />
</cnsl-form-field>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'IDP.JWT.JWTKEYSENDPOINT' | translate }}</cnsl-label>
<input cnslInput formControlName="keysEndpoint" />
</cnsl-form-field>
</div>
</ng-container>
<div class="btn-wrapper">
<button
color="primary"
mat-raised-button
class="continue-button"
[disabled]="jwtConfigForm.invalid || (canWrite | async) === false"
type="submit"
>
{{ 'ACTIONS.SAVE' | translate }}
</button>
</div>
</form>
</ng-container>
</div> </div>

View File

@ -1,82 +1,85 @@
.idp-form { .idp-wrapper {
padding-top: 1rem; margin-top: 2rem;
}
.idp-desc {
font-size: 14px;
}
.idp-content {
display: flex;
flex-direction: row;
margin: 0 -0.5rem;
flex-wrap: wrap;
.idp-desc { .idp-desc {
flex-basis: 100%; font-size: 14px;
margin: 0 0.5rem;
margin-bottom: 1rem;
} }
.formfield { .idp-content {
flex: 1 1 auto; .idp-desc {
margin: 0 0.5rem; margin-bottom: 1rem;
min-width: 150px;
.chip {
border-radius: 0.5rem;
height: 40px;
} }
&.fullwidth { .idp-formfield {
flex-basis: 100%; display: block;
} max-width: 400px;
@media only screen and (max-width: 450px) { .chip {
flex-basis: 100%; border-radius: 0.5rem;
} height: 40px;
} }
.auto-reg-info { .mat-chip-input {
margin: 0 0.5rem 1rem 0.5rem; width: 100%;
display: block;
width: 100%;
.auto-reg-desc {
margin: 0 0 1rem 0;
}
}
.line {
display: flex;
align-items: flex-end;
width: 100%;
.formfield {
flex: 1;
input {
margin: 0; margin: 0;
} }
@media only screen and (max-width: 450px) {
max-width: none;
}
} }
button { .auto-reg-info {
margin-bottom: 12px; margin: 0 0 1rem 0;
display: block;
width: 100%;
max-width: 400px;
.auto-reg-desc {
margin: 0 0 1rem 0;
}
}
.scope-card {
max-width: 400px;
display: block;
.scope-card-content {
display: block;
.flex-line {
display: flex;
align-items: flex-end;
width: 100%;
.idp-formfield {
flex: 1;
input {
margin: 0;
}
}
button {
margin-bottom: 12px;
}
}
}
} }
} }
}
.btn-wrapper { .btn-wrapper {
display: flex; display: flex;
justify-content: flex-end; margin-top: 1rem;
.continue-button { .continue-button {
margin-bottom: 4rem;
display: block;
@media only screen and (max-width: 450px) {
margin-top: 1rem;
margin-bottom: 2rem; margin-bottom: 2rem;
display: block;
@media only screen and (max-width: 450px) {
margin-top: 1rem;
margin-bottom: 2rem;
}
} }
} }
} }

View File

@ -14,6 +14,7 @@ import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.
import { InputModule } from 'src/app/modules/input/input.module'; import { InputModule } from 'src/app/modules/input/input.module';
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module'; import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
import { CardModule } from '../card/card.module';
import { InfoRowModule } from '../info-row/info-row.module'; import { InfoRowModule } from '../info-row/info-row.module';
import { InfoSectionModule } from '../info-section/info-section.module'; import { InfoSectionModule } from '../info-section/info-section.module';
import { TopViewModule } from '../top-view/top-view.module'; import { TopViewModule } from '../top-view/top-view.module';
@ -37,6 +38,7 @@ import { IdpComponent } from './idp.component';
TopViewModule, TopViewModule,
MatTooltipModule, MatTooltipModule,
MatSelectModule, MatSelectModule,
CardModule,
TranslateModule, TranslateModule,
MatCheckboxModule, MatCheckboxModule,
InfoRowModule, InfoRowModule,

View File

@ -1409,7 +1409,7 @@
}, },
"OWNERTYPES": { "OWNERTYPES": {
"0": "unknown", "0": "unknown",
"1": "System", "1": "Instanz",
"2": "Organisation" "2": "Organisation"
}, },
"TYPES": { "TYPES": {
@ -1462,11 +1462,12 @@
"DELETE_SELECTION_DESCRIPTION": "Sie sind im Begriff mehrere Identity Provider zu löschen. Die dadurch hervorgerufenen Änderungen sind unwiderruflich. Wollen Sie dies wirklich tun?", "DELETE_SELECTION_DESCRIPTION": "Sie sind im Begriff mehrere Identity Provider zu löschen. Die dadurch hervorgerufenen Änderungen sind unwiderruflich. Wollen Sie dies wirklich tun?",
"EMPTY": "Kein IDP vorhanden", "EMPTY": "Kein IDP vorhanden",
"OIDC": { "OIDC": {
"TITLE": "OIDC IDP", "GENERAL": "Generelle Information",
"TITLE": "OIDC Konfiguration",
"DESCRIPTION": "Geben Sie die Daten OIDC Identity Providers ein." "DESCRIPTION": "Geben Sie die Daten OIDC Identity Providers ein."
}, },
"JWT": { "JWT": {
"TITLE": "JWT IDP", "TITLE": "JWT Konfiguration",
"DESCRIPTION": "Geben Sie die Daten JWT Identity Providers ein. ", "DESCRIPTION": "Geben Sie die Daten JWT Identity Providers ein. ",
"HEADERNAME": "Header Name", "HEADERNAME": "Header Name",
"JWTENDPOINT": "JWT Endpoint", "JWTENDPOINT": "JWT Endpoint",

View File

@ -1409,7 +1409,7 @@
}, },
"OWNERTYPES": { "OWNERTYPES": {
"0": "unknown", "0": "unknown",
"1": "System", "1": "Instance",
"2": "Organization" "2": "Organization"
}, },
"TYPES": { "TYPES": {
@ -1462,11 +1462,12 @@
"DELETE_SELECTION_DESCRIPTION": "You are about to delete an identity provider. The resulting changes are irrevocable. Do you really want to do this?", "DELETE_SELECTION_DESCRIPTION": "You are about to delete an identity provider. The resulting changes are irrevocable. Do you really want to do this?",
"EMPTY": "No IPD available", "EMPTY": "No IPD available",
"OIDC": { "OIDC": {
"TITLE": "OIDC IDP", "GENERAL": "General Information",
"TITLE": "OIDC Configuration",
"DESCRIPTION": "Enter the data for the OIDC Identity Provider." "DESCRIPTION": "Enter the data for the OIDC Identity Provider."
}, },
"JWT": { "JWT": {
"TITLE": "JWT IDP", "TITLE": "JWT Configuration",
"DESCRIPTION": "Enter the data for JWT Identity Provider.", "DESCRIPTION": "Enter the data for JWT Identity Provider.",
"HEADERNAME": "Header Name", "HEADERNAME": "Header Name",
"JWTENDPOINT": "JWT Endpoint", "JWTENDPOINT": "JWT Endpoint",

View File

@ -1409,7 +1409,7 @@
}, },
"OWNERTYPES": { "OWNERTYPES": {
"0": "sconosciuto", "0": "sconosciuto",
"1": "Sistema", "1": "Istanza",
"2": "Organizzazione" "2": "Organizzazione"
}, },
"TYPES": { "TYPES": {
@ -1462,11 +1462,12 @@
"DELETE_SELECTION_DESCRIPTION": "Stai per rimuovere un fornitore di identit\u00e0. I cambiamenti risultanti sono irrevocabili. Vuoi davvero farlo?", "DELETE_SELECTION_DESCRIPTION": "Stai per rimuovere un fornitore di identit\u00e0. I cambiamenti risultanti sono irrevocabili. Vuoi davvero farlo?",
"EMPTY": "Nessun IDP disponible", "EMPTY": "Nessun IDP disponible",
"OIDC": { "OIDC": {
"TITLE": "OIDC IDP", "GENERAL": "Informazioni generali",
"TITLE": "Configurazione OIDC",
"DESCRIPTION": "Inserisci i dati per il OIDC Identity Provider." "DESCRIPTION": "Inserisci i dati per il OIDC Identity Provider."
}, },
"JWT": { "JWT": {
"TITLE": "JWT IDP", "TITLE": "Configurazione JWT",
"DESCRIPTION": "Inserisci i dati per il JWT Identity Provider.", "DESCRIPTION": "Inserisci i dati per il JWT Identity Provider.",
"HEADERNAME": "Header Name", "HEADERNAME": "Header Name",
"JWTENDPOINT": "JWT Endpoint", "JWTENDPOINT": "JWT Endpoint",

View File

@ -1,10 +1,14 @@
a { a {
text-decoration: none; text-decoration: none;
outline: none; outline: none;
cursor: pointer; cursor: pointer;
margin: 2px 0; margin: 2px 0;
&.block { &.block {
display: block; display: block;
} }
}
&.sub-formfield-link {
margin: 10px 0;
}
}

View File

@ -4,7 +4,7 @@ $lgn-button-margin: 0 !default;
$lgn-button-line-height: 36px !default; $lgn-button-line-height: 36px !default;
$lgn-button-border-radius: 6px !default; $lgn-button-border-radius: 6px !default;
$lgn-button-focus-transition: opacity 200ms cubic-bezier(0.35, 0, 0.25, 1), $lgn-button-focus-transition: opacity 200ms cubic-bezier(0.35, 0, 0.25, 1),
background-color 200ms cubic-bezier(0.35, 0, 0.25, 1) !default; background-color 200ms cubic-bezier(0.35, 0, 0.25, 1) !default;
// Stroked button padding is 1px less horizontally than default or raised lgn button // Stroked button padding is 1px less horizontally than default or raised lgn button
// button's padding. // button's padding.
@ -40,6 +40,7 @@ $lgn-icon-button-line-height: 40px !default;
border-radius: $lgn-button-border-radius; border-radius: $lgn-button-border-radius;
overflow: visible; overflow: visible;
transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
&[disabled] { &[disabled] {
cursor: default; cursor: default;

View File

@ -280,6 +280,7 @@ footer .watermark .lgn-logo-watermark {
padding: 0 16px; padding: 0 16px;
border-radius: 6px; border-radius: 6px;
overflow: visible; overflow: visible;
transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
} }
.lgn-button[disabled], .lgn-stroked-button[disabled], .lgn-icon-button[disabled] { .lgn-button[disabled], .lgn-stroked-button[disabled], .lgn-icon-button[disabled] {
cursor: default; cursor: default;
@ -306,6 +307,7 @@ footer .watermark .lgn-logo-watermark {
padding: 0 16px; padding: 0 16px;
border-radius: 6px; border-radius: 6px;
overflow: visible; overflow: visible;
transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);
} }
.lgn-raised-button[disabled] { .lgn-raised-button[disabled] {
@ -507,6 +509,9 @@ a {
a.block { a.block {
display: block; display: block;
} }
a.sub-formfield-link {
margin: 10px 0;
}
.lgn-idp { .lgn-idp {
display: block; display: block;
@ -1192,6 +1197,7 @@ footer .watermark .lgn-logo-watermark {
padding: 0 16px; padding: 0 16px;
border-radius: 6px; border-radius: 6px;
overflow: visible; overflow: visible;
transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
} }
.lgn-button[disabled], .lgn-stroked-button[disabled], .lgn-icon-button[disabled] { .lgn-button[disabled], .lgn-stroked-button[disabled], .lgn-icon-button[disabled] {
cursor: default; cursor: default;
@ -1218,6 +1224,7 @@ footer .watermark .lgn-logo-watermark {
padding: 0 16px; padding: 0 16px;
border-radius: 6px; border-radius: 6px;
overflow: visible; overflow: visible;
transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);
} }
.lgn-raised-button[disabled] { .lgn-raised-button[disabled] {
@ -1419,6 +1426,9 @@ a {
a.block { a.block {
display: block; display: block;
} }
a.sub-formfield-link {
margin: 10px 0;
}
.lgn-idp { .lgn-idp {
display: block; display: block;

File diff suppressed because one or more lines are too long

View File

@ -22,7 +22,7 @@
{{template "error-message" .}} {{template "error-message" .}}
{{ if showPasswordReset }} {{ if showPasswordReset }}
<a class="block" href="{{ passwordResetUrl .AuthReqID }}"> <a class="block sub-formfield-link" href="{{ passwordResetUrl .AuthReqID }}">
{{t "Password.ResetLinkText"}} {{t "Password.ResetLinkText"}}
</a> </a>
{{ end }} {{ end }}