project initialized
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
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 { MatSelectModule } from '@angular/material/select';
|
||||
|
||||
import { UiModule } from '@ucap/ng-ui';
|
||||
|
||||
import { I18nModule, UCAP_I18N_NAMESPACE } from '@ucap/ng-i18n';
|
||||
|
||||
import { ModuleConfig } from './config/module-config';
|
||||
import { _MODULE_CONFIG } from './config/token';
|
||||
|
||||
import { ChangePasswordComponent } from './components/change-password.component';
|
||||
import { LoginComponent } from './components/login.component';
|
||||
|
||||
const COMPONENTS = [ChangePasswordComponent, LoginComponent];
|
||||
const DIALOGS = [];
|
||||
const PIPES = [];
|
||||
const DIRECTIVES = [];
|
||||
const SERVICES = [];
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [],
|
||||
exports: []
|
||||
})
|
||||
export class AuthenticationUiRootModule {}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
ReactiveFormsModule,
|
||||
|
||||
FlexLayoutModule,
|
||||
|
||||
MatButtonModule,
|
||||
MatCheckboxModule,
|
||||
MatFormFieldModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
MatSelectModule,
|
||||
|
||||
I18nModule,
|
||||
UiModule
|
||||
],
|
||||
exports: [...COMPONENTS, ...DIRECTIVES, ...PIPES],
|
||||
declarations: [...COMPONENTS, ...DIRECTIVES, ...PIPES],
|
||||
entryComponents: [...DIALOGS],
|
||||
providers: [
|
||||
{
|
||||
provide: UCAP_I18N_NAMESPACE,
|
||||
useValue: ['authentication']
|
||||
}
|
||||
]
|
||||
})
|
||||
export class AuthenticationUiModule {
|
||||
public static forRoot(
|
||||
config: ModuleConfig
|
||||
): ModuleWithProviders<AuthenticationUiRootModule> {
|
||||
return {
|
||||
ngModule: AuthenticationUiRootModule,
|
||||
providers: [{ provide: _MODULE_CONFIG, useValue: config }, ...SERVICES]
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
<div class="change-password-form">
|
||||
<form name="changePasswordForm" [formGroup]="changePasswordForm" novalidate>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'accounts.fieldCurrentPassword' | ucapI18n }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="password"
|
||||
[formControl]="currentLoginPwFormControl"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'accounts.fieldNewPassword' | ucapI18n }}</mat-label>
|
||||
<input matInput type="password" [formControl]="newLoginPwFormControl" />
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'accounts.fieldNewPasswordConfirm' | ucapI18n }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="password"
|
||||
[formControl]="newConfirmLoginPwFormControl"
|
||||
/>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="error-container">
|
||||
<mat-error
|
||||
*ngIf="
|
||||
currentLoginPwFormControl.dirty &&
|
||||
currentLoginPwFormControl.hasError('required')
|
||||
"
|
||||
>
|
||||
{{ 'accounts.errors.requireCurrentPassword' | ucapI18n }}
|
||||
</mat-error>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
currentLoginPwFormControl.dirty &&
|
||||
currentLoginPwFormControl.hasError('ucapPasswordSame')
|
||||
"
|
||||
>
|
||||
{{ 'accounts.errors.notSameWithCurrentPassword' | ucapI18n }}
|
||||
</mat-error>
|
||||
|
||||
<mat-error
|
||||
*ngIf="
|
||||
newLoginPwFormControl.dirty &&
|
||||
newLoginPwFormControl.hasError('required')
|
||||
"
|
||||
>
|
||||
{{ 'accounts.errors.requireNewPassword' | ucapI18n }}
|
||||
</mat-error>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
newLoginPwFormControl.dirty &&
|
||||
newLoginPwFormControl.hasError('ucapNotSameWith')
|
||||
"
|
||||
>
|
||||
{{ 'accounts.errors.sameWithCurrentPassword' | ucapI18n }}
|
||||
</mat-error>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
newLoginPwFormControl.dirty &&
|
||||
newLoginPwFormControl.hasError('ucapPassword')
|
||||
"
|
||||
>
|
||||
<ng-container
|
||||
[ngSwitch]="
|
||||
newLoginPwFormControl.getError('ucapPassword').result.code
|
||||
"
|
||||
>
|
||||
<ng-container *ngSwitchCase="PasswordValidationResult.IncludeSpace">
|
||||
{{ 'accounts.errors.notContainSpacesForPassword' | ucapI18n }}
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="PasswordValidationResult.IncludeUserId">
|
||||
{{ 'accounts.errors.notContainUseridForPassword' | ucapI18n }}
|
||||
</ng-container>
|
||||
<ng-container
|
||||
*ngSwitchCase="PasswordValidationResult.IncludePhoneNumber"
|
||||
>
|
||||
{{ 'accounts.errors.notContainPhonenumberForPassword' | ucapI18n }}
|
||||
</ng-container>
|
||||
<ng-container
|
||||
*ngSwitchCase="PasswordValidationResult.IncludeRepeated"
|
||||
>
|
||||
{{
|
||||
'accounts.errors.notAllowedAlphaNumOver3TimesForPassword'
|
||||
| ucapI18n
|
||||
}}
|
||||
</ng-container>
|
||||
<ng-container
|
||||
*ngSwitchCase="PasswordValidationResult.IncludeIncrements"
|
||||
>
|
||||
{{
|
||||
'accounts.errors.notAllowedConsecutiveAlphaNumOver3TimesForPassword'
|
||||
| ucapI18n
|
||||
}}
|
||||
</ng-container>
|
||||
<ng-container
|
||||
*ngSwitchCase="PasswordValidationResult.IncludeDecrements"
|
||||
>
|
||||
{{
|
||||
'accounts.errors.notAllowedConsecutiveAlphaNumOver3TimesForPassword'
|
||||
| ucapI18n
|
||||
}}
|
||||
</ng-container>
|
||||
<ng-container
|
||||
*ngSwitchCase="PasswordValidationResult.LackOfCombination"
|
||||
>
|
||||
{{ 'accounts.errors.notSatisfiedCombineForPassword' | ucapI18n }}
|
||||
</ng-container>
|
||||
<ng-container
|
||||
*ngSwitchCase="PasswordValidationResult.TooShortCombinationLength"
|
||||
>
|
||||
{{
|
||||
'accounts.errors.minLengthCombineForPassword'
|
||||
| ucapI18n
|
||||
: {
|
||||
countOfCombine: newLoginPwFormControl.getError(
|
||||
'ucapPassword'
|
||||
).result.extra.combinationCount,
|
||||
lengthOfPassword: newLoginPwFormControl.getError(
|
||||
'ucapPassword'
|
||||
).result.extra.minPwLen
|
||||
}
|
||||
}}
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</mat-error>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
newConfirmLoginPwFormControl.dirty &&
|
||||
newConfirmLoginPwFormControl.hasError('required')
|
||||
"
|
||||
>
|
||||
{{ 'accounts.errors.requireNewPassword' | ucapI18n }}
|
||||
</mat-error>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
newConfirmLoginPwFormControl.dirty &&
|
||||
newConfirmLoginPwFormControl.hasError('ucapSameWith')
|
||||
"
|
||||
>
|
||||
{{ 'accounts.errors.notSameWithNewPassword' | ucapI18n }}
|
||||
</mat-error>
|
||||
</div>
|
||||
|
||||
<button
|
||||
mat-raised-button
|
||||
class="submit-button bg-accent-dark"
|
||||
aria-label="패스워드 변경"
|
||||
[disabled]="changePasswordForm.invalid"
|
||||
(click)="onClickChangePassword()"
|
||||
>
|
||||
{{ 'accounts.changePassword' | ucapI18n }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -0,0 +1,65 @@
|
||||
.change-password-form {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-width: 380px;
|
||||
padding: 0px;
|
||||
text-align: center;
|
||||
|
||||
.mat-title {
|
||||
margin: 16px 0 32px 0;
|
||||
}
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
|
||||
mat-form-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.error-container {
|
||||
height: 80px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
margin: 24px auto;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100px;
|
||||
|
||||
.text {
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
padding: 0 8px;
|
||||
z-index: 9999;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 30px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
border-top: 1px solid;
|
||||
}
|
||||
|
||||
&:before {
|
||||
right: 100%;
|
||||
}
|
||||
|
||||
&:after {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ChangePasswordComponent } from './change-password.component';
|
||||
|
||||
describe('Account::ChangePasswordComponent', () => {
|
||||
let component: ChangePasswordComponent;
|
||||
let fixture: ComponentFixture<ChangePasswordComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ChangePasswordComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ChangePasswordComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,154 @@
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter,
|
||||
ChangeDetectorRef
|
||||
} from '@angular/core';
|
||||
import {
|
||||
FormControl,
|
||||
FormGroup,
|
||||
Validators,
|
||||
ValidatorFn,
|
||||
AbstractControl,
|
||||
ValidationErrors,
|
||||
FormBuilder
|
||||
} from '@angular/forms';
|
||||
import {
|
||||
PasswordUtil,
|
||||
PasswordValidationOption,
|
||||
PasswordValidationResult
|
||||
} from '@ucap/pi';
|
||||
|
||||
export function ucapPassword(option: PasswordValidationOption): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationErrors | null => {
|
||||
const result = PasswordUtil.validate(control.value, option);
|
||||
return PasswordValidationResult.Valid !== result.code
|
||||
? { ucapPassword: { result } }
|
||||
: null;
|
||||
};
|
||||
}
|
||||
|
||||
export function ucapPasswordSame(value: string): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationErrors | null => {
|
||||
return !!value && value !== PasswordUtil.encrypt(control.value)
|
||||
? { ucapPasswordSame: true }
|
||||
: null;
|
||||
};
|
||||
}
|
||||
|
||||
export function ucapNotSameWith(targetControl: AbstractControl): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationErrors | null => {
|
||||
return !!targetControl &&
|
||||
(targetControl.value as string) === (control.value as string)
|
||||
? { ucapNotSameWith: true }
|
||||
: null;
|
||||
};
|
||||
}
|
||||
|
||||
export function ucapSameWith(targetControl: AbstractControl): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationErrors | null => {
|
||||
return !!targetControl && targetControl.value !== control.value
|
||||
? { ucapSameWith: true }
|
||||
: null;
|
||||
};
|
||||
}
|
||||
|
||||
export function ucapNotSame(value: string | number): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationErrors | null => {
|
||||
return !!value && value === control.value ? { ucapNotSame: true } : null;
|
||||
};
|
||||
}
|
||||
|
||||
export function ucapSame(value: string | number): ValidatorFn {
|
||||
return (control: AbstractControl): ValidationErrors | null => {
|
||||
return !!value && value !== control.value ? { ucapSame: true } : null;
|
||||
};
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'ucap-authentication-change-password',
|
||||
templateUrl: './change-password.component.html',
|
||||
styleUrls: ['./change-password.component.scss']
|
||||
})
|
||||
export class ChangePasswordComponent implements OnInit {
|
||||
@Input()
|
||||
loginId: string;
|
||||
|
||||
@Input()
|
||||
phoneNumber: string;
|
||||
|
||||
@Input()
|
||||
encryptedLoginPw: string;
|
||||
|
||||
@Output()
|
||||
changePassword = new EventEmitter<{
|
||||
currentLoginPw: string;
|
||||
newLoginPw: string;
|
||||
}>();
|
||||
|
||||
changePasswordForm: FormGroup;
|
||||
currentLoginPwFormControl = new FormControl('');
|
||||
newLoginPwFormControl = new FormControl('');
|
||||
newConfirmLoginPwFormControl = new FormControl('');
|
||||
|
||||
PasswordValidationResult = PasswordValidationResult;
|
||||
|
||||
constructor(
|
||||
private formBuilder: FormBuilder,
|
||||
private changeDetectorRef: ChangeDetectorRef
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
const currentLoginPwValidators: ValidatorFn[] = [Validators.required];
|
||||
if (!!this.encryptedLoginPw) {
|
||||
currentLoginPwValidators.push(ucapPasswordSame(this.encryptedLoginPw));
|
||||
}
|
||||
this.currentLoginPwFormControl.setValidators(currentLoginPwValidators);
|
||||
|
||||
let validateOption: PasswordValidationOption = {};
|
||||
if (!!this.loginId) {
|
||||
validateOption = {
|
||||
...validateOption,
|
||||
userId: this.loginId
|
||||
};
|
||||
}
|
||||
if (!!this.phoneNumber) {
|
||||
validateOption = {
|
||||
...validateOption,
|
||||
phoneNumber: this.phoneNumber
|
||||
};
|
||||
}
|
||||
|
||||
const newLoginPwValidators: ValidatorFn[] = [
|
||||
Validators.required,
|
||||
ucapNotSameWith(this.currentLoginPwFormControl),
|
||||
ucapPassword(validateOption)
|
||||
];
|
||||
this.newLoginPwFormControl.setValidators(newLoginPwValidators);
|
||||
|
||||
const newConfirmLoginPwValidators: ValidatorFn[] = [
|
||||
Validators.required,
|
||||
ucapSameWith(this.newLoginPwFormControl)
|
||||
];
|
||||
this.newConfirmLoginPwFormControl.setValidators(
|
||||
newConfirmLoginPwValidators
|
||||
);
|
||||
|
||||
this.changePasswordForm = this.formBuilder.group({
|
||||
currentLoginPwFormControl: this.currentLoginPwFormControl,
|
||||
newLoginPwFormControl: this.newLoginPwFormControl,
|
||||
newConfirmLoginPwFormControl: this.newConfirmLoginPwFormControl
|
||||
});
|
||||
}
|
||||
|
||||
onClickChangePassword() {
|
||||
this.changePassword.emit({
|
||||
currentLoginPw: PasswordUtil.encrypt(
|
||||
this.currentLoginPwFormControl.value
|
||||
),
|
||||
newLoginPw: PasswordUtil.encrypt(this.newLoginPwFormControl.value)
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
<div class="login-form">
|
||||
<div
|
||||
class="mat-title"
|
||||
style="background-image: url(./assets/images/logo/bg_login_w160.png);"
|
||||
>
|
||||
{{ 'accounts.instructionsOfLogin' | ucapI18n }}
|
||||
</div>
|
||||
|
||||
<form name="loginForm" [formGroup]="loginForm" novalidate>
|
||||
<mat-form-field
|
||||
[style.display]="!!curCompanyCode ? 'none' : 'block'"
|
||||
class="login-company"
|
||||
>
|
||||
<mat-label>{{ 'accounts.fieldCompany' | ucapI18n }}</mat-label>
|
||||
<mat-select [formControl]="companyCodeFormControl">
|
||||
<mat-option
|
||||
*ngFor="let company of companyList"
|
||||
[value]="company.companyCode"
|
||||
>{{ company.companyName }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="input-lineless">
|
||||
<!--<span class="icon-img"><i class="mid mdi-account-tie-outline"></i></span>-->
|
||||
<span class="icon-img">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20.82 22">
|
||||
<path
|
||||
d="M14.39,11.88a5.7,5.7,0,1,0-4.78,0A10.41,10.41,0,0,0,1.59,22v1H22.41V22A10.41,10.41,0,0,0,14.39,11.88Z"
|
||||
transform="translate(-1.59 -1)"
|
||||
style="fill:#fff"
|
||||
/>
|
||||
<path
|
||||
d="M14.39,11.88a5.7,5.7,0,1,0-4.78,0A10.41,10.41,0,0,0,1.59,22v1H22.41V22A10.41,10.41,0,0,0,14.39,11.88ZM8.3,6.7A3.71,3.71,0,1,1,12,10.41,3.7,3.7,0,0,1,8.3,6.7ZM3.65,21a8.42,8.42,0,0,1,7.58-7.37L10,16.58l2,2,2-2-1.23-2.95A8.42,8.42,0,0,1,20.35,21Z"
|
||||
transform="translate(-1.59 -1)"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<mat-form-field class="login-id">
|
||||
<mat-label>{{ 'accounts.fieldLoginId' | ucapI18n }}</mat-label>
|
||||
<input matInput [formControl]="loginIdFormControl" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="input-lineless">
|
||||
<!--<span class="icon-img"><i class="mid mdi-lock-outline"></i></span>-->
|
||||
<span class="icon-img">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 22.07">
|
||||
<title>login-lock</title>
|
||||
<path
|
||||
d="M19,10H18V7A6,6,0,0,0,6,7v3H5a3,3,0,0,0-3,3v7a3,3,0,0,0,3,3H19a3,3,0,0,0,3-3V13A3,3,0,0,0,19,10Z"
|
||||
transform="translate(-2 -0.93)"
|
||||
style="fill:#fff"
|
||||
/>
|
||||
<rect x="9.08" y="12.94" width="1.84" height="3.72" />
|
||||
<path
|
||||
d="M19,22.93H5a3,3,0,0,1-3-3v-7a3,3,0,0,1,3-3H19a3,3,0,0,1,3,3v7A3,3,0,0,1,19,22.93Zm-14-11a1,1,0,0,0-1,1v7a1,1,0,0,0,1,1H19a1,1,0,0,0,1-1v-7a1,1,0,0,0-1-1Z"
|
||||
transform="translate(-2 -0.93)"
|
||||
/>
|
||||
<path
|
||||
d="M17,11.93a1,1,0,0,1-1-1v-4a4,4,0,0,0-8,0v4a1,1,0,0,1-2,0v-4a6,6,0,0,1,12,0v4A1,1,0,0,1,17,11.93Z"
|
||||
transform="translate(-2 -0.93)"
|
||||
/>
|
||||
<rect
|
||||
x="9.58"
|
||||
y="13.36"
|
||||
width="0.84"
|
||||
height="2.72"
|
||||
style="fill:#fff"
|
||||
/>
|
||||
<rect x="9.08" y="12.86" width="1.84" height="3.72" />
|
||||
</svg>
|
||||
</span>
|
||||
<mat-form-field class="login-pw">
|
||||
<mat-label>{{ 'accounts.fieldLoginPw' | ucapI18n }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="password"
|
||||
[formControl]="loginPwFormControl"
|
||||
#loginPw
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="error-container">
|
||||
<mat-error
|
||||
*ngIf="
|
||||
companyCodeFormControl.dirty &&
|
||||
companyCodeFormControl.hasError('required')
|
||||
"
|
||||
>
|
||||
{{ 'accounts.errors.requireCompany' | ucapI18n }}
|
||||
</mat-error>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
loginIdFormControl.dirty && loginIdFormControl.hasError('required')
|
||||
"
|
||||
>
|
||||
{{ 'accounts.errors.requireLoginId' | ucapI18n }}
|
||||
</mat-error>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
loginPwFormControl.dirty && loginPwFormControl.hasError('required')
|
||||
"
|
||||
>
|
||||
{{ 'accounts.errors.requireLoginPw' | ucapI18n }}
|
||||
</mat-error>
|
||||
</div>
|
||||
|
||||
<button
|
||||
mat-raised-button
|
||||
class="submit-button bg-accent-dark"
|
||||
aria-label="LOG IN"
|
||||
[disabled]="loginForm.invalid || !loginBtnEnable"
|
||||
(click)="onClickLogin()"
|
||||
>
|
||||
{{ loginBtnText }}
|
||||
</button>
|
||||
|
||||
<div
|
||||
class="remember-forgot-password"
|
||||
fxLayout="row"
|
||||
fxLayout.xs="column"
|
||||
fxLayoutAlign="space-between center"
|
||||
>
|
||||
<mat-checkbox
|
||||
*ngIf="useRememberMe"
|
||||
class="remember-me"
|
||||
formControlName="rememberMe"
|
||||
aria-label="Remember Me"
|
||||
>
|
||||
{{ 'accounts.rememberMe' | ucapI18n }}
|
||||
</mat-checkbox>
|
||||
|
||||
<mat-checkbox
|
||||
*ngIf="useAutoLogin"
|
||||
class="auto-login"
|
||||
formControlName="autoLogin"
|
||||
aria-label="Auto Login"
|
||||
>
|
||||
{{ 'accounts.autoLogin' | ucapI18n }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="register" fxLayout="column" fxLayoutAlign="center center">
|
||||
<div *ngIf="false">
|
||||
<span class="text">Don't have an account?</span>
|
||||
<a class="link">Forgot Password?</a>
|
||||
<a class="link">Create an account</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="policy" (click)="onClickNoti()">
|
||||
<div class="icon-img"><i class="mid mdi-alarm-light"></i></div>
|
||||
<a class="link">{{ !!notiText ? notiText : '개인정보 처리방침' }}</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,222 @@
|
||||
$desktop-l-width: 1440px;
|
||||
$tablet-l-width: 1024px;
|
||||
$tablet-s-width: 768px;
|
||||
$mob-l-width: 640px;
|
||||
$login-max-height: 800px;
|
||||
|
||||
@mixin desktop-m {
|
||||
@media screen and (max-width: #{$desktop-l-width}) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
// 태블릿
|
||||
@mixin tab {
|
||||
@media screen and (max-width: #{$tablet-l-width}) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
// 모바일 large
|
||||
@mixin mob-l {
|
||||
@media screen and (max-width: #{$mob-l-width}) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
.login-form {
|
||||
position: relative;
|
||||
transform: scale(1);
|
||||
width: 100%;
|
||||
min-width: 100%;
|
||||
top: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
border-radius: 0px;
|
||||
font-size: 14px;
|
||||
|
||||
.mat-title {
|
||||
margin: 10px 0 10px 0;
|
||||
text-indent: -10000000px;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
background-repeat: no-repeat;
|
||||
display: inline-flex;
|
||||
background-size: 100% auto;
|
||||
flex: 1 1 auto;
|
||||
background-position-x: center;
|
||||
}
|
||||
|
||||
form {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
|
||||
.input-lineless {
|
||||
background-color: #e0e0e0;
|
||||
padding: 14px 20px;
|
||||
margin-top: 6px;
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
@media screen and (max-width: #{$tablet-s-width}) {
|
||||
padding: 8px 20px;
|
||||
}
|
||||
.icon-img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 10px;
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
mat-form-field {
|
||||
width: 100%;
|
||||
color: #333333;
|
||||
&.login-pw {
|
||||
//margin-top: 10px;
|
||||
@media screen and (max-width: #{$tablet-s-width}) {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mat-checkbox {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.remember-forgot-password {
|
||||
font-size: 13px;
|
||||
|
||||
.remember-me {
|
||||
}
|
||||
|
||||
.auto-login {
|
||||
font-size: 0.9em;
|
||||
font-weight: 600;
|
||||
margin-bottom: 2vh;
|
||||
}
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
margin: 20px 0 10px;
|
||||
display: block;
|
||||
border-radius: 0;
|
||||
line-height: 50px;
|
||||
font-size: 1.1em;
|
||||
@media screen and (max-width: #{$tablet-s-width}) {
|
||||
line-height: 38px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.register {
|
||||
margin: 32px auto 24px auto;
|
||||
font-weight: 600;
|
||||
|
||||
.text {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
margin: 24px auto;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100px;
|
||||
|
||||
.text {
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
padding: 0 8px;
|
||||
z-index: 9999;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 30px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
border-top: 1px solid;
|
||||
}
|
||||
|
||||
&:before {
|
||||
right: 100%;
|
||||
}
|
||||
|
||||
&:after {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.policy {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
bottom: 2vh;
|
||||
display: block;
|
||||
background-color: #58b0b1;
|
||||
width: 100%;
|
||||
color: #ffffff;
|
||||
font-size: 0.86em;
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
align-items: center;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.icon-img {
|
||||
padding: 12px 10px;
|
||||
width: 50px;
|
||||
color: #ffffff;
|
||||
padding-right: 10px;
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.7);
|
||||
flex: 0 0 auto;
|
||||
@media screen and (max-width: #{$tablet-s-width}) {
|
||||
padding: 9px 10px;
|
||||
}
|
||||
}
|
||||
a {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
button {
|
||||
&.google,
|
||||
&.facebook {
|
||||
width: 192px;
|
||||
text-transform: none;
|
||||
color: #ffffff;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include tab {
|
||||
.login-form {
|
||||
font-size: 0.9em;
|
||||
.mat-title {
|
||||
background-size: 90% auto;
|
||||
}
|
||||
.mat-form-field .mat-form-field-infix input {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.policy {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
width: 100%;
|
||||
font-size: 0.9em;
|
||||
padding: 0px;
|
||||
line-height: 3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoginComponent } from './login.component';
|
||||
|
||||
describe('ui::authentication::LoginComponent', () => {
|
||||
let component: LoginComponent;
|
||||
let fixture: ComponentFixture<LoginComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [LoginComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LoginComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
127
projects/ui-authentication/src/lib/components/login.component.ts
Normal file
127
projects/ui-authentication/src/lib/components/login.component.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter,
|
||||
ViewChild,
|
||||
ElementRef,
|
||||
ChangeDetectorRef
|
||||
} from '@angular/core';
|
||||
import {
|
||||
FormGroup,
|
||||
FormBuilder,
|
||||
Validators,
|
||||
FormControl,
|
||||
ValidatorFn
|
||||
} from '@angular/forms';
|
||||
import { Company } from '@ucap/api-external';
|
||||
|
||||
@Component({
|
||||
selector: 'ucap-authentication-login',
|
||||
templateUrl: './login.component.html',
|
||||
styleUrls: ['./login.component.scss']
|
||||
})
|
||||
export class LoginComponent implements OnInit {
|
||||
@Input()
|
||||
companyList: Company[];
|
||||
@Input()
|
||||
curCompanyCode: string;
|
||||
@Input()
|
||||
loginBtnText: string;
|
||||
@Input()
|
||||
loginBtnEnable: boolean;
|
||||
@Input()
|
||||
notiText: string;
|
||||
|
||||
@Input()
|
||||
companyCode: string;
|
||||
@Input()
|
||||
loginId: string;
|
||||
@Input()
|
||||
rememberMe: boolean;
|
||||
@Input()
|
||||
autoLogin: boolean;
|
||||
|
||||
@Input()
|
||||
useRememberMe: boolean;
|
||||
@Input()
|
||||
useAutoLogin: boolean;
|
||||
|
||||
@Output()
|
||||
login = new EventEmitter<{
|
||||
companyCode: string;
|
||||
loginId: string;
|
||||
loginPw: string;
|
||||
rememberMe: boolean;
|
||||
autoLogin: boolean;
|
||||
notValid: () => void;
|
||||
}>();
|
||||
@Output()
|
||||
notiClick = new EventEmitter();
|
||||
|
||||
@ViewChild('loginPw', { static: true }) loginPwElementRef: ElementRef;
|
||||
|
||||
loginForm: FormGroup;
|
||||
companyCodeFormControl = new FormControl('');
|
||||
loginIdFormControl = new FormControl('');
|
||||
loginPwFormControl = new FormControl('');
|
||||
|
||||
constructor(
|
||||
private formBuilder: FormBuilder,
|
||||
private changeDetectorRef: ChangeDetectorRef
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
const companyCodeValidators: ValidatorFn[] = [Validators.required];
|
||||
this.companyCodeFormControl.setValidators(companyCodeValidators);
|
||||
if (!!this.curCompanyCode) {
|
||||
this.companyCodeFormControl.setValue(this.curCompanyCode);
|
||||
}
|
||||
const loginIdValidators: ValidatorFn[] = [Validators.required];
|
||||
this.loginIdFormControl.setValidators(loginIdValidators);
|
||||
if (!!this.loginId) {
|
||||
this.loginIdFormControl.setValue(this.loginId);
|
||||
}
|
||||
const loginPwValidators: ValidatorFn[] = [Validators.required];
|
||||
this.loginPwFormControl.setValidators(loginPwValidators);
|
||||
|
||||
this.loginForm = this.formBuilder.group({
|
||||
companyCodeFormControl: this.companyCodeFormControl,
|
||||
loginIdFormControl: this.loginIdFormControl,
|
||||
loginPwFormControl: this.loginPwFormControl,
|
||||
rememberMe: [false],
|
||||
autoLogin: [false]
|
||||
});
|
||||
|
||||
if (!!this.rememberMe && this.rememberMe) {
|
||||
this.loginForm.get('rememberMe').setValue(true);
|
||||
}
|
||||
|
||||
if (!!this.autoLogin && this.autoLogin) {
|
||||
this.loginForm.get('autoLogin').setValue(true);
|
||||
}
|
||||
|
||||
if (!this.loginBtnText || this.loginBtnText.trim().length === 0) {
|
||||
this.loginBtnText = 'LOGIN';
|
||||
}
|
||||
this.changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
onClickLogin() {
|
||||
this.login.emit({
|
||||
companyCode: this.loginForm.get('companyCodeFormControl').value,
|
||||
loginId: this.loginForm.get('loginIdFormControl').value,
|
||||
loginPw: this.loginForm.get('loginPwFormControl').value,
|
||||
rememberMe: this.loginForm.get('rememberMe').value,
|
||||
autoLogin: this.loginForm.get('autoLogin').value,
|
||||
notValid: () => {
|
||||
this.loginPwElementRef.nativeElement.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onClickNoti(): void {
|
||||
this.notiClick.emit();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { ModuleConfig as CoreModuleConfig } from '@ucap/core';
|
||||
|
||||
// tslint:disable-next-line: no-empty-interface
|
||||
export interface ModuleConfig extends CoreModuleConfig {}
|
||||
5
projects/ui-authentication/src/lib/config/token.ts
Normal file
5
projects/ui-authentication/src/lib/config/token.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { InjectionToken } from '@angular/core';
|
||||
|
||||
export const _MODULE_CONFIG = new InjectionToken(
|
||||
'@ucap/ui-authentication config of module'
|
||||
);
|
||||
7
projects/ui-authentication/src/public-api.ts
Normal file
7
projects/ui-authentication/src/public-api.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Public API Surface of ui-authentication
|
||||
*/
|
||||
|
||||
export * from './lib/config/module-config';
|
||||
|
||||
export * from './lib/authentication-ui.module';
|
||||
26
projects/ui-authentication/src/test.ts
Normal file
26
projects/ui-authentication/src/test.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
|
||||
import 'zone.js/dist/zone';
|
||||
import 'zone.js/dist/zone-testing';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
import {
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting
|
||||
} from '@angular/platform-browser-dynamic/testing';
|
||||
|
||||
declare const require: {
|
||||
context(path: string, deep?: boolean, filter?: RegExp): {
|
||||
keys(): string[];
|
||||
<T>(id: string): T;
|
||||
};
|
||||
};
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting()
|
||||
);
|
||||
// Then we find all the tests.
|
||||
const context = require.context('./', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
context.keys().map(context);
|
||||
Reference in New Issue
Block a user