mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ACS-7385][ADF] Break Login dependency on Material Module (#9501)
This commit is contained in:
@@ -5,7 +5,11 @@
|
||||
[showLoginActions]="false"
|
||||
[backgroundImageUrl]="''"
|
||||
(success)="onLoginSuccess($event)">
|
||||
<adf-login-header><ng-template></ng-template></adf-login-header>
|
||||
<adf-login-footer><ng-template></ng-template></adf-login-footer>
|
||||
<adf-login-header>
|
||||
<ng-template></ng-template>
|
||||
</adf-login-header>
|
||||
<adf-login-footer>
|
||||
<ng-template></ng-template>
|
||||
</adf-login-footer>
|
||||
</adf-login>
|
||||
</div>
|
@@ -15,13 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BasicAlfrescoAuthService, CoreTestingModule, LoginDialogPanelComponent } from '@alfresco/adf-core';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { LoginDialogPanelComponent } from './login-dialog-panel.component';
|
||||
import { of } from 'rxjs';
|
||||
import { CoreTestingModule } from '../../testing/core.testing.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { BasicAlfrescoAuthService } from '../../auth/basic-auth/basic-alfresco-auth.service';
|
||||
import { OidcAuthenticationService } from '../../auth/services/oidc-authentication.service';
|
||||
import { of } from 'rxjs';
|
||||
import { OidcAuthenticationService } from '../../../auth/services/oidc-authentication.service';
|
||||
|
||||
describe('LoginDialogPanelComponent', () => {
|
||||
let component: LoginDialogPanelComponent;
|
||||
@@ -38,7 +36,7 @@ describe('LoginDialogPanelComponent', () => {
|
||||
CoreTestingModule
|
||||
],
|
||||
providers: [
|
||||
{ provide: OidcAuthenticationService, useValue: {}}
|
||||
{ provide: OidcAuthenticationService, useValue: {} }
|
||||
]
|
||||
});
|
||||
fixture = TestBed.createComponent(LoginDialogPanelComponent);
|
@@ -15,14 +15,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, ViewEncapsulation, ViewChild, Output, EventEmitter } from '@angular/core';
|
||||
import { LoginComponent } from './login.component';
|
||||
import { LoginSuccessEvent } from '../models/login-success.event';
|
||||
import { Component, EventEmitter, Output, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { LoginFooterDirective } from '../../directives/login-footer.directive';
|
||||
import { LoginHeaderDirective } from '../../directives/login-header.directive';
|
||||
import { LoginSuccessEvent } from '../../models/login-success.event';
|
||||
import { LoginComponent } from '../login/login.component';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-login-dialog-panel',
|
||||
standalone: true,
|
||||
templateUrl: './login-dialog-panel.component.html',
|
||||
styleUrls: ['./login-dialog-panel.component.scss'],
|
||||
imports: [
|
||||
LoginComponent,
|
||||
LoginHeaderDirective,
|
||||
LoginFooterDirective
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class LoginDialogPanelComponent {
|
@@ -1,27 +0,0 @@
|
||||
<header
|
||||
mat-dialog-title
|
||||
data-automation-id="login-dialog-title">
|
||||
{{data?.title}}
|
||||
</header>
|
||||
|
||||
<mat-dialog-content class="adf-login-dialog-content">
|
||||
<adf-login-dialog-panel #adfLoginPanel (success)="onLoginSuccess($event)">
|
||||
</adf-login-dialog-panel>
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions class="adf-login-dialog-content-actions" align="end">
|
||||
<button
|
||||
mat-button (click)="close()"
|
||||
data-automation-id="login-dialog-actions-cancel">
|
||||
{{ 'LOGIN.DIALOG.CANCEL' | translate }}
|
||||
</button>
|
||||
|
||||
<button
|
||||
mat-button
|
||||
class="choose-action"
|
||||
data-automation-id="login-dialog-actions-perform"
|
||||
[disabled]="!isFormValid()"
|
||||
(click)="submitForm()">
|
||||
{{ buttonActionName | translate}}
|
||||
</button>
|
||||
</mat-dialog-actions>
|
@@ -0,0 +1,24 @@
|
||||
<header mat-dialog-title
|
||||
data-automation-id="login-dialog-title">
|
||||
{{ data?.title }}
|
||||
</header>
|
||||
|
||||
<mat-dialog-content class="adf-login-dialog-content">
|
||||
<adf-login-dialog-panel #adfLoginPanel (success)="onLoginSuccess($event)">
|
||||
</adf-login-dialog-panel>
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions class="adf-login-dialog-content-actions" align="end">
|
||||
<button mat-button (click)="close()"
|
||||
data-automation-id="login-dialog-actions-cancel">
|
||||
{{ 'LOGIN.DIALOG.CANCEL' | translate }}
|
||||
</button>
|
||||
|
||||
<button mat-button
|
||||
class="choose-action"
|
||||
data-automation-id="login-dialog-actions-perform"
|
||||
[disabled]="!isFormValid()"
|
||||
(click)="submitForm()">
|
||||
{{ buttonActionName | translate }}
|
||||
</button>
|
||||
</mat-dialog-actions>
|
@@ -15,14 +15,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Meta, moduleMetadata, Story } from '@storybook/angular';
|
||||
import { CoreStoryModule } from '../../testing/core.story.module';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { LoginModule } from './../login.module';
|
||||
import { LoginDialogStorybookComponent } from './login-dialog.stories.component';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { AuthenticationService } from '../../auth/services/authentication.service';
|
||||
import { AuthenticationMock } from '../../auth/mock/authentication.service.mock';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { Meta, moduleMetadata, Story } from '@storybook/angular';
|
||||
import { AuthenticationService } from '../../../auth';
|
||||
import { AuthenticationMock } from '../../../auth/mock/authentication.service.mock';
|
||||
import { CoreStoryModule } from '../../../testing/core.story.module';
|
||||
import { LoginModule } from '../../login.module';
|
||||
import { LoginDialogStorybookComponent } from './login-dialog.stories.component';
|
||||
|
||||
export default {
|
||||
component: LoginDialogStorybookComponent,
|
@@ -15,14 +15,24 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, Inject, ViewEncapsulation, ViewChild } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { Component, Inject, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { LoginDialogPanelComponent } from '../login-dialog-panel/login-dialog-panel.component';
|
||||
import { LoginDialogComponentData } from './login-dialog-component-data.interface';
|
||||
import { LoginDialogPanelComponent } from './login-dialog-panel.component';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-login-dialog',
|
||||
standalone: true,
|
||||
templateUrl: './login-dialog.component.html',
|
||||
styleUrls: ['./login-dialog.component.scss'],
|
||||
imports: [
|
||||
MatDialogModule,
|
||||
LoginDialogPanelComponent,
|
||||
TranslateModule,
|
||||
MatButtonModule
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class LoginDialogComponent {
|
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import { Component, Output, EventEmitter } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Subject } from 'rxjs';
|
||||
import { LoginDialogComponent } from './login-dialog.component';
|
||||
@@ -23,9 +24,14 @@ import { LoginDialogComponentData } from './login-dialog-component-data.interfac
|
||||
|
||||
@Component({
|
||||
selector: 'adf-login-dialog-storybook',
|
||||
template: `<button mat-raised-button (click)="openLoginDialog()">
|
||||
Open dialog
|
||||
</button>`
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatButtonModule
|
||||
],
|
||||
template: `
|
||||
<button mat-raised-button (click)="openLoginDialog()">
|
||||
Open dialog
|
||||
</button>`
|
||||
})
|
||||
export class LoginDialogStorybookComponent {
|
||||
|
@@ -1,218 +0,0 @@
|
||||
<div class="adf-login-content" [style.background-image]="getBackgroundUrlImageUrl()">
|
||||
<div class="adf-ie11FixerParent">
|
||||
<div class="adf-ie11FixerChild">
|
||||
|
||||
<mat-card class="adf-login-card-wide">
|
||||
<form
|
||||
id="adf-login-form"
|
||||
[formGroup]="form"
|
||||
autocomplete="off"
|
||||
(submit)="onSubmit(form.value)">
|
||||
<mat-card-header class="adf-login-card-header-text">
|
||||
<mat-card-title>
|
||||
<div class="adf-alfresco-logo">
|
||||
<!--HEADER TEMPLATE-->
|
||||
<ng-template
|
||||
*ngIf="headerTemplate"
|
||||
ngFor
|
||||
[ngForOf]="[data]"
|
||||
[ngForTemplate]="headerTemplate">
|
||||
</ng-template>
|
||||
<img
|
||||
*ngIf="!headerTemplate"
|
||||
id="adf-login-img-logo"
|
||||
class="adf-img-logo"
|
||||
[src]="logoImageUrl"
|
||||
alt="{{'LOGIN.LOGO' | translate }}">
|
||||
</div>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
|
||||
<mat-card-content class="adf-login-controls">
|
||||
|
||||
<!--ERRORS AREA-->
|
||||
<div class="adf-error-container">
|
||||
<div
|
||||
*ngIf="isError"
|
||||
id="login-error"
|
||||
data-automation-id="login-error"
|
||||
class="adf-error adf-error-message">
|
||||
<mat-icon class="adf-error-icon">warning</mat-icon>
|
||||
<span class="adf-login-error-message">
|
||||
{{errorMsg | translate }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!ssoLogin">
|
||||
|
||||
<!--USERNAME FIELD-->
|
||||
<div
|
||||
class="adf-login__field"
|
||||
[ngClass]="{'adf-is-invalid': isErrorStyle(form.controls.username)}">
|
||||
<mat-form-field
|
||||
class="adf-full-width adf-login-form-field"
|
||||
floatPlaceholder="never"
|
||||
color="primary">
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
class="adf-full-width"
|
||||
formControlName="username"
|
||||
id="username"
|
||||
data-automation-id="username"
|
||||
placeholder="{{'LOGIN.LABEL.USERNAME' | translate }}"
|
||||
autocapitalize="none"
|
||||
(blur)="trimUsername($event)">
|
||||
</mat-form-field>
|
||||
<span
|
||||
*ngIf="formError['username']"
|
||||
class="adf-login-validation"
|
||||
for="username">
|
||||
<span
|
||||
id="username-error"
|
||||
class="adf-login-error"
|
||||
data-automation-id="username-error">
|
||||
{{formError['username'] | translate}}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!--PASSWORD FIELD-->
|
||||
<div class="adf-login__field">
|
||||
<mat-form-field
|
||||
class="adf-full-width adf-login-form-field"
|
||||
floatPlaceholder="never"
|
||||
color="primary">
|
||||
<input
|
||||
matInput
|
||||
placeholder="{{'LOGIN.LABEL.PASSWORD' | translate }}"
|
||||
[type]="isPasswordShow ? 'text' : 'password'"
|
||||
formControlName="password"
|
||||
id="password"
|
||||
data-automation-id="password">
|
||||
<button
|
||||
matSuffix
|
||||
mat-icon-button
|
||||
type="button"
|
||||
[attr.aria-label]="(isPasswordShow ? 'LOGIN.ARIA-LABEL.HIDE-PASSWORD' : 'LOGIN.ARIA-LABEL.SHOW-PASSWORD') | translate"
|
||||
(click)="toggleShowPassword($event)"
|
||||
(keyup.enter)="toggleShowPassword($event)"
|
||||
[attr.data-automation-id]="isPasswordShow ? 'hide_password' : 'show_password'">
|
||||
<mat-icon class="adf-login-form-password-icon adf-login-password-icon">
|
||||
{{ isPasswordShow ? 'visibility' : 'visibility_off' }}
|
||||
</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
<span
|
||||
class="adf-login-validation"
|
||||
for="password"
|
||||
*ngIf="formError['password']">
|
||||
<span
|
||||
id="password-required"
|
||||
class="adf-login-error"
|
||||
data-automation-id="password-required">
|
||||
{{formError['password'] | translate}}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!--CUSTOM CONTENT-->
|
||||
<ng-content></ng-content>
|
||||
|
||||
<br>
|
||||
<button
|
||||
type="submit"
|
||||
id="login-button"
|
||||
class="adf-login-button"
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
[class.adf-isChecking]="actualLoginStep === LoginSteps.Checking"
|
||||
[class.adf-isWelcome]="actualLoginStep === LoginSteps.Welcome"
|
||||
data-automation-id="login-button"
|
||||
[disabled]="!form.valid"
|
||||
[attr.aria-label]="'LOGIN.BUTTON.LOGIN' | translate">
|
||||
<span
|
||||
*ngIf="actualLoginStep === LoginSteps.Landing"
|
||||
class="adf-login-button-label">
|
||||
{{'LOGIN.BUTTON.LOGIN' | translate }}
|
||||
</span>
|
||||
<div
|
||||
*ngIf="actualLoginStep === LoginSteps.Checking"
|
||||
class="adf-interactive-login-label">
|
||||
<span class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.CHECKING' | translate}}
|
||||
</span>
|
||||
<div class="adf-login-spinner-container">
|
||||
<mat-spinner
|
||||
id="checking-spinner"
|
||||
class="adf-login-checking-spinner"
|
||||
[strokeWidth]="4"
|
||||
[diameter]="25">
|
||||
</mat-spinner>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="actualLoginStep === LoginSteps.Welcome"
|
||||
class="adf-interactive-login-label">
|
||||
<span class="adf-login-button-label">{{ 'LOGIN.BUTTON.WELCOME' | translate }}</span>
|
||||
<mat-icon class="adf-welcome-icon">done</mat-icon>
|
||||
</div>
|
||||
</button>
|
||||
<div *ngIf="showRememberMe" class="adf-login__remember-me">
|
||||
<mat-checkbox
|
||||
id="adf-login-remember"
|
||||
color="primary"
|
||||
class="adf-login-remember-me"
|
||||
[checked]="rememberMe"
|
||||
(change)="rememberMe = !rememberMe">
|
||||
<div class="adf-login-remember-me-label">
|
||||
{{ 'LOGIN.LABEL.REMEMBER' | translate }}
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="ssoLogin">
|
||||
<button
|
||||
type="button"
|
||||
(click)="implicitLogin()"
|
||||
id="login-button-sso"
|
||||
[attr.aria-label]="'LOGIN.BUTTON.SSO' | translate"
|
||||
class="adf-login-button"
|
||||
mat-raised-button color="primary"
|
||||
data-automation-id="login-button-sso">
|
||||
<span class="adf-login-button-label">{{ 'LOGIN.BUTTON.SSO' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions *ngIf="footerTemplate || showLoginActions">
|
||||
|
||||
<div class="adf-login-action-container">
|
||||
<!--FOOTER TEMPLATE-->
|
||||
<ng-template
|
||||
*ngIf="footerTemplate"
|
||||
ngFor
|
||||
[ngForOf]="[data]"
|
||||
[ngForTemplate]="footerTemplate">
|
||||
</ng-template>
|
||||
<div class="adf-login-action" *ngIf="!footerTemplate && showLoginActions">
|
||||
<div id="adf-login-action-left" class="adf-login-action-left">
|
||||
<a href="{{needHelpLink}}">{{'LOGIN.ACTION.HELP' | translate }}</a>
|
||||
</div>
|
||||
<div id="adf-login-action-right" class="adf-login-action-right">
|
||||
<a href="{{registerLink}}">{{'LOGIN.ACTION.REGISTER' | translate }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
|
||||
<div class="adf-copyright" data-automation-id="login-copyright">
|
||||
{{ copyrightText }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
200
lib/core/src/lib/login/components/login/login.component.html
Normal file
200
lib/core/src/lib/login/components/login/login.component.html
Normal file
@@ -0,0 +1,200 @@
|
||||
<div class="adf-login-content" [style.background-image]="'url(' + backgroundImageUrl + ')'">
|
||||
<div class="adf-ie11FixerParent">
|
||||
<div class="adf-ie11FixerChild">
|
||||
|
||||
<mat-card class="adf-login-card-wide">
|
||||
<form id="adf-login-form"
|
||||
[formGroup]="form"
|
||||
autocomplete="off"
|
||||
(submit)="onSubmit(form.value)">
|
||||
<mat-card-header class="adf-login-card-header-text">
|
||||
<mat-card-title>
|
||||
<div class="adf-alfresco-logo">
|
||||
<!--HEADER TEMPLATE-->
|
||||
<ng-template *ngIf="headerTemplate"
|
||||
ngFor
|
||||
[ngForOf]="[data]"
|
||||
[ngForTemplate]="headerTemplate">
|
||||
</ng-template>
|
||||
<img *ngIf="!headerTemplate"
|
||||
id="adf-login-img-logo"
|
||||
class="adf-img-logo"
|
||||
[src]="logoImageUrl"
|
||||
alt="{{ 'LOGIN.LOGO' | translate }}">
|
||||
</div>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
|
||||
<mat-card-content class="adf-login-controls">
|
||||
|
||||
<!--ERRORS AREA-->
|
||||
<div class="adf-error-container">
|
||||
<div *ngIf="isError"
|
||||
id="login-error"
|
||||
data-automation-id="login-error"
|
||||
class="adf-error adf-error-message">
|
||||
<mat-icon class="adf-error-icon">warning</mat-icon>
|
||||
<span class="adf-login-error-message">
|
||||
{{ errorMsg | translate }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!ssoLogin">
|
||||
|
||||
<!--USERNAME FIELD-->
|
||||
<div class="adf-login__field"
|
||||
[ngClass]="{'adf-is-invalid': isErrorStyle(form.controls.username)}">
|
||||
<mat-form-field class="adf-full-width adf-login-form-field"
|
||||
floatPlaceholder="never"
|
||||
color="primary">
|
||||
<input matInput
|
||||
type="text"
|
||||
class="adf-full-width"
|
||||
formControlName="username"
|
||||
id="username"
|
||||
data-automation-id="username"
|
||||
placeholder="{{'LOGIN.LABEL.USERNAME' | translate }}"
|
||||
autocapitalize="none"
|
||||
(blur)="trimUsername($event)">
|
||||
</mat-form-field>
|
||||
<span *ngIf="formError['username']"
|
||||
class="adf-login-validation"
|
||||
for="username">
|
||||
<span id="username-error"
|
||||
class="adf-login-error"
|
||||
data-automation-id="username-error">
|
||||
{{ formError['username'] | translate }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!--PASSWORD FIELD-->
|
||||
<div class="adf-login__field">
|
||||
<mat-form-field class="adf-full-width adf-login-form-field"
|
||||
floatPlaceholder="never"
|
||||
color="primary">
|
||||
<input matInput
|
||||
placeholder="{{'LOGIN.LABEL.PASSWORD' | translate }}"
|
||||
[type]="isPasswordShow ? 'text' : 'password'"
|
||||
formControlName="password"
|
||||
id="password"
|
||||
data-automation-id="password">
|
||||
<button matSuffix
|
||||
mat-icon-button
|
||||
type="button"
|
||||
[attr.aria-label]="(isPasswordShow ? 'LOGIN.ARIA-LABEL.HIDE-PASSWORD' : 'LOGIN.ARIA-LABEL.SHOW-PASSWORD') | translate"
|
||||
(click)="toggleShowPassword($event)"
|
||||
(keyup.enter)="toggleShowPassword($event)"
|
||||
[attr.data-automation-id]="isPasswordShow ? 'hide_password' : 'show_password'">
|
||||
<mat-icon class="adf-login-form-password-icon adf-login-password-icon">
|
||||
{{ isPasswordShow ? 'visibility' : 'visibility_off' }}
|
||||
</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
<span class="adf-login-validation"
|
||||
for="password"
|
||||
*ngIf="formError['password']">
|
||||
<span id="password-required"
|
||||
class="adf-login-error"
|
||||
data-automation-id="password-required">
|
||||
{{ formError['password'] | translate }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!--CUSTOM CONTENT-->
|
||||
<ng-content></ng-content>
|
||||
|
||||
<br>
|
||||
<button type="submit"
|
||||
id="login-button"
|
||||
class="adf-login-button"
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
[class.adf-isChecking]="actualLoginStep === LoginSteps.Checking"
|
||||
[class.adf-isWelcome]="actualLoginStep === LoginSteps.Welcome"
|
||||
data-automation-id="login-button"
|
||||
[disabled]="!form.valid"
|
||||
[attr.aria-label]="'LOGIN.BUTTON.LOGIN' | translate">
|
||||
<span *ngIf="actualLoginStep === LoginSteps.Landing"
|
||||
class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.LOGIN' | translate }}
|
||||
</span>
|
||||
<div *ngIf="actualLoginStep === LoginSteps.Checking"
|
||||
class="adf-interactive-login-label">
|
||||
<span class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.CHECKING' | translate }}
|
||||
</span>
|
||||
<div class="adf-login-spinner-container">
|
||||
<mat-spinner id="checking-spinner"
|
||||
class="adf-login-checking-spinner"
|
||||
[strokeWidth]="4"
|
||||
[diameter]="25">
|
||||
</mat-spinner>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="actualLoginStep === LoginSteps.Welcome"
|
||||
class="adf-interactive-login-label">
|
||||
<span class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.WELCOME' | translate }}
|
||||
</span>
|
||||
<mat-icon class="adf-welcome-icon">done</mat-icon>
|
||||
</div>
|
||||
</button>
|
||||
<div *ngIf="showRememberMe" class="adf-login__remember-me">
|
||||
<mat-checkbox id="adf-login-remember"
|
||||
color="primary"
|
||||
class="adf-login-remember-me"
|
||||
[checked]="rememberMe"
|
||||
(change)="rememberMe = !rememberMe">
|
||||
<div class="adf-login-remember-me-label">
|
||||
{{ 'LOGIN.LABEL.REMEMBER' | translate }}
|
||||
</div>
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="ssoLogin">
|
||||
<button type="button"
|
||||
(click)="implicitLogin()"
|
||||
id="login-button-sso"
|
||||
[attr.aria-label]="'LOGIN.BUTTON.SSO' | translate"
|
||||
class="adf-login-button"
|
||||
mat-raised-button color="primary"
|
||||
data-automation-id="login-button-sso">
|
||||
<span class="adf-login-button-label">
|
||||
{{ 'LOGIN.BUTTON.SSO' | translate }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions *ngIf="footerTemplate || showLoginActions">
|
||||
|
||||
<div class="adf-login-action-container">
|
||||
<!--FOOTER TEMPLATE-->
|
||||
<ng-template *ngIf="footerTemplate"
|
||||
ngFor
|
||||
[ngForOf]="[data]"
|
||||
[ngForTemplate]="footerTemplate">
|
||||
</ng-template>
|
||||
<div class="adf-login-action" *ngIf="!footerTemplate && showLoginActions">
|
||||
<div id="adf-login-action-left" class="adf-login-action-left">
|
||||
<a href="{{ needHelpLink }}">{{ 'LOGIN.ACTION.HELP' | translate }}</a>
|
||||
</div>
|
||||
<div id="adf-login-action-right" class="adf-login-action-right">
|
||||
<a href="{{ registerLink }}">{{ 'LOGIN.ACTION.REGISTER' | translate }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
|
||||
<div class="adf-copyright" data-automation-id="login-copyright">
|
||||
{{ copyrightText }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -1,4 +1,4 @@
|
||||
@import '../../styles/mixins';
|
||||
@import '../../../styles/mixins';
|
||||
|
||||
.adf-login {
|
||||
@include flex-column;
|
||||
@@ -63,7 +63,7 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (max-width: 482px) {
|
||||
@media screen and (width <= 482px) {
|
||||
.adf-login-card-wide {
|
||||
width: calc(100% - 32px);
|
||||
}
|
||||
@@ -185,6 +185,8 @@
|
||||
|
||||
.adf-login__field {
|
||||
margin: 1em 0 0;
|
||||
display: block;
|
||||
padding-bottom: 18px;
|
||||
font-size: var(--theme-subheading-2-font-size);
|
||||
|
||||
& input:-webkit-autofill {
|
||||
@@ -221,13 +223,6 @@
|
||||
opacity: 0.87;
|
||||
}
|
||||
|
||||
.adf-login__field {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-bottom: 18px;
|
||||
}
|
||||
|
||||
.adf-login-remember-me:has(.adf-login-remember-me-label) {
|
||||
color: var(--adf-theme-foreground-text-color);
|
||||
}
|
@@ -15,21 +15,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
AppConfigService,
|
||||
AuthenticationService,
|
||||
BasicAlfrescoAuthService,
|
||||
CoreTestingModule,
|
||||
LoginErrorEvent,
|
||||
LoginSuccessEvent,
|
||||
LogService,
|
||||
UserPreferencesService
|
||||
} from '@alfresco/adf-core';
|
||||
import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
|
||||
import { Validators } from '@angular/forms';
|
||||
|
||||
import { Router } from '@angular/router';
|
||||
import { UserPreferencesService } from '../../common/services/user-preferences.service';
|
||||
import { AppConfigService } from '../../app-config/app-config.service';
|
||||
import { AuthenticationService } from '../../auth/services/authentication.service';
|
||||
import { LoginErrorEvent } from '../models/login-error.event';
|
||||
import { LoginSuccessEvent } from '../models/login-success.event';
|
||||
import { LoginComponent } from './login.component';
|
||||
import { EMPTY, of, throwError } from 'rxjs';
|
||||
import { CoreTestingModule } from '../../testing/core.testing.module';
|
||||
import { LogService } from '../../common/services/log.service';
|
||||
import { BasicAlfrescoAuthService } from '../../auth/basic-auth/basic-alfresco-auth.service';
|
||||
import { OidcAuthenticationService } from '../../auth/services/oidc-authentication.service';
|
||||
import { OidcAuthenticationService } from '../../../auth/services/oidc-authentication.service';
|
||||
import { LoginComponent } from './login.component';
|
||||
|
||||
describe('LoginComponent', () => {
|
||||
let component: LoginComponent;
|
||||
@@ -65,7 +67,8 @@ describe('LoginComponent', () => {
|
||||
providers: [
|
||||
{
|
||||
provide: OidcAuthenticationService, useValue: {
|
||||
ssoLogin: () => { },
|
||||
ssoLogin: () => {
|
||||
},
|
||||
isPublicUrl: () => false,
|
||||
hasValidIdToken: () => false,
|
||||
isLoggedIn: () => false
|
||||
@@ -581,7 +584,7 @@ describe('LoginComponent', () => {
|
||||
|
||||
loginWithCredentials('fake-username-ECM-access-error', 'fake-password');
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
it('should trim the username value', () => {
|
||||
usernameInput.value = 'username ';
|
||||
@@ -623,7 +626,7 @@ describe('LoginComponent', () => {
|
||||
});
|
||||
|
||||
loginWithCredentials('fake-username', 'fake-password');
|
||||
});
|
||||
});
|
||||
|
||||
it('should emit success event after the login has succeeded and discard password', fakeAsync(() => {
|
||||
spyOn(basicAlfrescoAuthService, 'login').and.returnValue(of({ type: 'type', ticket: 'ticket' }));
|
@@ -15,13 +15,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Meta, moduleMetadata, Story } from '@storybook/angular';
|
||||
import { CoreStoryModule } from '../../testing/core.story.module';
|
||||
import { LoginModule } from '../login.module';
|
||||
import { LoginComponent } from './login.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AuthenticationService } from './../../auth/services/authentication.service';
|
||||
import { AuthenticationMock } from '../../auth/mock/authentication.service.mock';
|
||||
import { Meta, moduleMetadata, Story } from '@storybook/angular';
|
||||
import { AuthenticationService } from '../../../auth';
|
||||
import { AuthenticationMock } from '../../../auth/mock/authentication.service.mock';
|
||||
import { CoreStoryModule } from '../../../testing/core.story.module';
|
||||
import { LoginModule } from '../../login.module';
|
||||
import { LoginComponent } from './login.component';
|
||||
|
||||
export default {
|
||||
component: LoginComponent,
|
@@ -15,22 +15,29 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, EventEmitter, Input, OnInit, Output, TemplateRef, ViewEncapsulation, OnDestroy } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { Router, ActivatedRoute, Params } from '@angular/router';
|
||||
import { AuthenticationService } from '../../auth/services/authentication.service';
|
||||
import { TranslationService } from '../../translation/translation.service';
|
||||
import { UserPreferencesService } from '../../common/services/user-preferences.service';
|
||||
|
||||
import { LoginErrorEvent } from '../models/login-error.event';
|
||||
import { LoginSubmitEvent } from '../models/login-submit.event';
|
||||
import { LoginSuccessEvent } from '../models/login-success.event';
|
||||
import { AppConfigService, AppConfigValues } from '../../app-config/app-config.service';
|
||||
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, TemplateRef, ViewEncapsulation } from '@angular/core';
|
||||
import { AbstractControl, ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { BasicAlfrescoAuthService } from '../../auth/basic-auth/basic-alfresco-auth.service';
|
||||
import { OidcAuthenticationService } from '../../auth/services/oidc-authentication.service';
|
||||
import { AppConfigService, AppConfigValues } from '../../../app-config';
|
||||
import { AuthenticationService, BasicAlfrescoAuthService } from '../../../auth';
|
||||
import { OidcAuthenticationService } from '../../../auth/services/oidc-authentication.service';
|
||||
import { UserPreferencesService } from '../../../common';
|
||||
import { TranslationService } from '../../../translation';
|
||||
|
||||
import { LoginErrorEvent } from '../../models/login-error.event';
|
||||
import { LoginSubmitEvent } from '../../models/login-submit.event';
|
||||
import { LoginSuccessEvent } from '../../models/login-success.event';
|
||||
|
||||
// eslint-disable-next-line no-shadow
|
||||
enum LoginSteps {
|
||||
@@ -47,14 +54,27 @@ interface ValidationMessage {
|
||||
interface LoginFormValues {
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'adf-login',
|
||||
standalone: true,
|
||||
templateUrl: './login.component.html',
|
||||
styleUrls: ['./login.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: {class: 'adf-login'}
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatCardModule,
|
||||
ReactiveFormsModule,
|
||||
TranslateModule,
|
||||
MatIconModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatButtonModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatCheckboxModule
|
||||
],
|
||||
host: { class: 'adf-login' }
|
||||
})
|
||||
export class LoginComponent implements OnInit, OnDestroy {
|
||||
isPasswordShow: boolean = false;
|
||||
@@ -137,8 +157,7 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
private router: Router,
|
||||
private appConfig: AppConfigService,
|
||||
private userPreferences: UserPreferencesService,
|
||||
private route: ActivatedRoute,
|
||||
private sanitizer: DomSanitizer
|
||||
private route: ActivatedRoute
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -164,7 +183,7 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
const url = params['redirectUrl'];
|
||||
const provider = this.appConfig.get<string>(AppConfigValues.PROVIDERS);
|
||||
|
||||
this.basicAlfrescoAuthService.setRedirect({provider, url});
|
||||
this.basicAlfrescoAuthService.setRedirect({ provider, url });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -197,7 +216,7 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
this.disableError();
|
||||
|
||||
const args = new LoginSubmitEvent({
|
||||
controls: {username: this.form.controls.username}
|
||||
controls: { username: this.form.controls.username }
|
||||
});
|
||||
this.executeSubmit.emit(args);
|
||||
|
||||
@@ -243,30 +262,29 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
performLogin(values: { username: string; password: string }) {
|
||||
this.authService.login(values.username, values.password, this.rememberMe)
|
||||
.subscribe(
|
||||
async (token: any) => {
|
||||
const redirectUrl = this.basicAlfrescoAuthService.getRedirect();
|
||||
this.authService.login(values.username, values.password, this.rememberMe).subscribe(
|
||||
async (token: any) => {
|
||||
const redirectUrl = this.basicAlfrescoAuthService.getRedirect();
|
||||
|
||||
this.actualLoginStep = LoginSteps.Welcome;
|
||||
this.userPreferences.setStoragePrefix(values.username);
|
||||
values.password = null;
|
||||
this.success.emit(new LoginSuccessEvent(token, values.username, null));
|
||||
this.actualLoginStep = LoginSteps.Welcome;
|
||||
this.userPreferences.setStoragePrefix(values.username);
|
||||
values.password = null;
|
||||
this.success.emit(new LoginSuccessEvent(token, values.username, null));
|
||||
|
||||
if (redirectUrl) {
|
||||
this.basicAlfrescoAuthService.setRedirect(null);
|
||||
await this.router.navigateByUrl(redirectUrl);
|
||||
} else if (this.successRoute) {
|
||||
await this.router.navigate([this.successRoute]);
|
||||
}
|
||||
},
|
||||
(err: any) => {
|
||||
this.actualLoginStep = LoginSteps.Landing;
|
||||
this.displayErrorMessage(err);
|
||||
this.isError = true;
|
||||
this.error.emit(new LoginErrorEvent(err));
|
||||
if (redirectUrl) {
|
||||
this.basicAlfrescoAuthService.setRedirect(null);
|
||||
await this.router.navigateByUrl(redirectUrl);
|
||||
} else if (this.successRoute) {
|
||||
await this.router.navigate([this.successRoute]);
|
||||
}
|
||||
);
|
||||
},
|
||||
(err: any) => {
|
||||
this.actualLoginStep = LoginSteps.Landing;
|
||||
this.displayErrorMessage(err);
|
||||
this.isError = true;
|
||||
this.error.emit(new LoginErrorEvent(err));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,10 +360,6 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
event.target.value = event.target.value.trim();
|
||||
}
|
||||
|
||||
getBackgroundUrlImageUrl(): SafeStyle {
|
||||
return this.sanitizer.bypassSecurityTrustStyle(`url(${this.backgroundImageUrl})`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default formError values
|
||||
*/
|
@@ -15,10 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { LoginComponent } from '../components/login.component';
|
||||
import { LoginFooterDirective } from './login-footer.directive';
|
||||
import { CoreTestingModule } from '../../testing/core.testing.module';
|
||||
import { CoreTestingModule, LoginComponent, LoginFooterDirective } from '@alfresco/adf-core';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { OidcAuthenticationService } from '../../auth/services/oidc-authentication.service';
|
||||
|
||||
|
@@ -15,27 +15,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
AfterContentInit,
|
||||
ContentChild,
|
||||
Directive,
|
||||
TemplateRef
|
||||
} from '@angular/core';
|
||||
import { LoginComponent } from '../components/login.component';
|
||||
import { AfterContentInit, ContentChild, Directive, TemplateRef } from '@angular/core';
|
||||
import { LoginComponent } from '../components/login/login.component';
|
||||
|
||||
/**
|
||||
* Directive selectors without adf- prefix will be deprecated on 3.0.0
|
||||
*/
|
||||
@Directive({
|
||||
selector: 'adf-login-footer, login-footer'
|
||||
selector: 'adf-login-footer',
|
||||
standalone: true
|
||||
})
|
||||
export class LoginFooterDirective implements AfterContentInit {
|
||||
|
||||
@ContentChild(TemplateRef)
|
||||
template: any;
|
||||
|
||||
constructor(
|
||||
private alfrescoLoginComponent: LoginComponent) {
|
||||
constructor(private alfrescoLoginComponent: LoginComponent) {
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
|
@@ -15,10 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { LoginComponent } from '../components/login.component';
|
||||
import { LoginHeaderDirective } from './login-header.directive';
|
||||
import { CoreTestingModule } from '../../testing/core.testing.module';
|
||||
import { CoreTestingModule, LoginComponent, LoginHeaderDirective } from '@alfresco/adf-core';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { OidcAuthenticationService } from '../../auth/services/oidc-authentication.service';
|
||||
|
||||
|
@@ -15,27 +15,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
AfterContentInit,
|
||||
ContentChild,
|
||||
Directive,
|
||||
TemplateRef
|
||||
} from '@angular/core';
|
||||
import { LoginComponent } from '../components/login.component';
|
||||
import { AfterContentInit, ContentChild, Directive, TemplateRef } from '@angular/core';
|
||||
import { LoginComponent } from '../components/login/login.component';
|
||||
|
||||
/**
|
||||
* Directive selectors without adf- prefix will be deprecated on 3.0.0
|
||||
*/
|
||||
@Directive({
|
||||
selector: 'adf-login-header, login-header'
|
||||
selector: 'adf-login-header',
|
||||
standalone: true
|
||||
})
|
||||
export class LoginHeaderDirective implements AfterContentInit {
|
||||
|
||||
@ContentChild(TemplateRef)
|
||||
template: any;
|
||||
|
||||
constructor(
|
||||
private alfrescoLoginComponent: LoginComponent) {
|
||||
constructor(private alfrescoLoginComponent: LoginComponent) {
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
|
@@ -15,29 +15,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MaterialModule } from '../material.module';
|
||||
import { LoginDialogPanelComponent } from './components/login-dialog-panel/login-dialog-panel.component';
|
||||
import { LoginDialogComponent } from './components/login-dialog/login-dialog.component';
|
||||
|
||||
import { LoginComponent } from './components/login.component';
|
||||
import { LoginComponent } from './components/login/login.component';
|
||||
import { LoginFooterDirective } from './directives/login-footer.directive';
|
||||
import { LoginHeaderDirective } from './directives/login-header.directive';
|
||||
import { LoginDialogComponent } from './components/login-dialog.component';
|
||||
import { LoginDialogPanelComponent } from './components/login-dialog-panel.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule,
|
||||
MaterialModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
CommonModule,
|
||||
TranslateModule
|
||||
],
|
||||
declarations: [
|
||||
LoginComponent,
|
||||
LoginFooterDirective,
|
||||
LoginHeaderDirective,
|
||||
|
@@ -19,6 +19,6 @@ export class LoginSuccessEvent {
|
||||
constructor(
|
||||
public token: any,
|
||||
public username: string,
|
||||
public password: string) {
|
||||
}
|
||||
public password: string
|
||||
) {}
|
||||
}
|
||||
|
@@ -18,10 +18,10 @@
|
||||
export * from './directives/login-header.directive';
|
||||
export * from './directives/login-footer.directive';
|
||||
|
||||
export * from './components/login.component';
|
||||
export * from './components/login-dialog.component';
|
||||
export * from './components/login-dialog-component-data.interface';
|
||||
export * from './components/login-dialog-panel.component';
|
||||
export * from './components/login/login.component';
|
||||
export * from './components/login-dialog/login-dialog.component';
|
||||
export * from './components/login-dialog/login-dialog-component-data.interface';
|
||||
export * from './components/login-dialog-panel/login-dialog-panel.component';
|
||||
|
||||
export * from './models/login-error.event';
|
||||
export * from './models/login-submit.event';
|
||||
|
Reference in New Issue
Block a user