This commit is contained in:
leejinho 2019-11-28 17:30:50 +09:00
commit 0f88633aea
26 changed files with 435 additions and 28 deletions

View File

@ -8,7 +8,7 @@
"files.trimTrailingWhitespace": true, "files.trimTrailingWhitespace": true,
"files.trimFinalNewlines": true, "files.trimFinalNewlines": true,
"files.watcherExclude": { "files.watcherExclude": {
"**/dist/electron/win-unpacked/**": true "**/dist": true
}, },
"go.testFlags": ["-v"], "go.testFlags": ["-v"],
"go.testTimeout": "100s", "go.testTimeout": "100s",

View File

@ -44,7 +44,7 @@ import { ROOT_REDUCERS, metaReducers, effects } from './store';
* See: https://github.com/zalmoxisus/redux-devtools-extension * See: https://github.com/zalmoxisus/redux-devtools-extension
*/ */
StoreDevtoolsModule.instrument({ StoreDevtoolsModule.instrument({
name: 'NgRx Book Store App' name: 'UCAP Store App'
// In a production build you would want to disable the Store Devtools // In a production build you would want to disable the Store Devtools
// logOnly: environment.production, // logOnly: environment.production,

View File

@ -0,0 +1 @@
<ucap-account-change-password></ucap-account-change-password>

View File

@ -0,0 +1,27 @@
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { ChangePasswordDialogComponent } from './change-password.dialog.component';
describe('ChangePasswordDialogComponent', () => {
let component: ChangePasswordDialogComponent;
let fixture: ComponentFixture<ChangePasswordDialogComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ChangePasswordDialogComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChangePasswordDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,56 @@
import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
import { KEY_VER_INFO } from '@app/types/ver-info.type';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { Store } from '@ngrx/store';
import { UserInfo } from '@ucap-webmessenger/protocol-sync';
import {
UserInfoSS,
UserInfoF,
UserInfoDN
} from '@ucap-webmessenger/protocol-query';
import { DialogService } from '@ucap-webmessenger/ui';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
export interface ChangePasswordDialogData {}
export interface ChangePasswordDialogResult {
choice: boolean;
}
@Component({
selector: 'app-change-password.dialog',
templateUrl: './change-password.dialog.component.html',
styleUrls: ['./change-password.dialog.component.scss']
})
export class ChangePasswordDialogComponent implements OnInit, OnDestroy {
loginRes: LoginResponse;
sessionVerinfo: VersionInfo2Response;
isMe: boolean;
constructor(
public dialogRef: MatDialogRef<
ChangePasswordDialogData,
ChangePasswordDialogResult
>,
@Inject(MAT_DIALOG_DATA) public data: ChangePasswordDialogData,
private dialogService: DialogService,
private sessionStorageService: SessionStorageService,
private store: Store<any>
) {
this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
KEY_VER_INFO
);
this.loginRes = this.sessionStorageService.get<LoginResponse>(
KEY_LOGIN_RES_INFO
);
}
ngOnInit() {}
ngOnDestroy(): void {}
}

View File

@ -0,0 +1,3 @@
import { ChangePasswordDialogComponent } from './change-password.dialog.component';
export const DIALOGS = [ChangePasswordDialogComponent];

View File

@ -1,3 +1,4 @@
import { DIALOGS as ACCOUNT_DIALOGS } from './account';
import { DIALOGS as CHAT_DIALOGS } from './chat'; import { DIALOGS as CHAT_DIALOGS } from './chat';
import { DIALOGS as GROUP_DIALOGS } from './group'; import { DIALOGS as GROUP_DIALOGS } from './group';
import { DIALOGS as MESSAGE_DIALOGS } from './message'; import { DIALOGS as MESSAGE_DIALOGS } from './message';
@ -5,6 +6,7 @@ import { DIALOGS as PROFILE_DIALOGS } from './profile';
import { DIALOGS as SETTINGS_DIALOGS } from './settings'; import { DIALOGS as SETTINGS_DIALOGS } from './settings';
export const DIALOGS = [ export const DIALOGS = [
...ACCOUNT_DIALOGS,
...CHAT_DIALOGS, ...CHAT_DIALOGS,
...GROUP_DIALOGS, ...GROUP_DIALOGS,
...MESSAGE_DIALOGS, ...MESSAGE_DIALOGS,

View File

@ -40,6 +40,7 @@ import { OverlayModule } from '@angular/cdk/overlay';
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar'; import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
import { UCapUiModule } from '@ucap-webmessenger/ui'; import { UCapUiModule } from '@ucap-webmessenger/ui';
import { UCapUiAccountModule } from '@ucap-webmessenger/ui-account';
import { UCapUiChatModule } from '@ucap-webmessenger/ui-chat'; import { UCapUiChatModule } from '@ucap-webmessenger/ui-chat';
import { UCapUiRoomModule } from '@ucap-webmessenger/ui-room'; import { UCapUiRoomModule } from '@ucap-webmessenger/ui-room';
import { UCapUiProfileModule } from '@ucap-webmessenger/ui-profile'; import { UCapUiProfileModule } from '@ucap-webmessenger/ui-profile';
@ -89,6 +90,7 @@ import { DIALOGS } from './dialogs';
PerfectScrollbarModule, PerfectScrollbarModule,
UCapUiModule, UCapUiModule,
UCapUiAccountModule,
UCapUiChatModule, UCapUiChatModule,
UCapUiRoomModule, UCapUiRoomModule,
UCapUiProfileModule, UCapUiProfileModule,

View File

@ -50,6 +50,8 @@ import * as SyncStore from '@app/store/messenger/sync';
import { KEY_VER_INFO } from '@app/types/ver-info.type'; import { KEY_VER_INFO } from '@app/types/ver-info.type';
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type'; import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
import { environment } from '../../environments/environment';
@Injectable() @Injectable()
export class AppMessengerResolver implements Resolve<void> { export class AppMessengerResolver implements Resolve<void> {
constructor( constructor(
@ -115,8 +117,8 @@ export class AppMessengerResolver implements Resolve<void> {
hostName: '', hostName: '',
ssoMode: SSOMode.AUTH, ssoMode: SSOMode.AUTH,
userSpecificInformation: 'PRO_000482', userSpecificInformation: 'PRO_000482',
productId: 'PRO_000482', productId: environment.productConfig.productId,
productName: 'EZMessenger' productName: environment.productConfig.productName
}); });
}), }),
switchMap(res => { switchMap(res => {
@ -141,11 +143,9 @@ export class AppMessengerResolver implements Resolve<void> {
this.store.dispatch( this.store.dispatch(
CompanyStore.companyList({ CompanyStore.companyList({
companyGroupCode: 'LG' companyGroupCode: environment.companyConfig.companyGroupCode
}) })
); );
// this.store.dispatch(AuthenticationStore.postLogin({ loginRes }));
}), }),
withLatestFrom( withLatestFrom(
this.store.pipe( this.store.pipe(
@ -189,6 +189,7 @@ export class AppMessengerResolver implements Resolve<void> {
loginRes loginRes
}) })
); );
this.store.dispatch(AuthenticationStore.postLogin({ loginRes }));
resolve(); resolve();
}, },
err => { err => {

View File

@ -32,6 +32,7 @@ export class AppAuthenticationService {
this.sessionStorageService.set<LoginInfo>(KEY_LOGIN_INFO, { this.sessionStorageService.set<LoginInfo>(KEY_LOGIN_INFO, {
...loginInfo, ...loginInfo,
initPw: loginInfo.loginId === loginInfo.loginPw,
loginPw: CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(loginInfo.loginPw)) loginPw: CryptoJS.enc.Hex.stringify(CryptoJS.SHA256(loginInfo.loginPw))
}); });

View File

@ -58,6 +58,14 @@ import {
LoginResponse LoginResponse
} from '@ucap-webmessenger/protocol-authentication'; } from '@ucap-webmessenger/protocol-authentication';
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type'; import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
import { ProtocolService } from '@ucap-webmessenger/protocol';
import { environment } from '../../../../environments/environment';
import {
ChangePasswordDialogComponent,
ChangePasswordDialogData,
ChangePasswordDialogResult
} from '@app/layouts/messenger/dialogs/account/change-password.dialog.component';
@Injectable() @Injectable()
export class Effects { export class Effects {
@ -128,13 +136,12 @@ export class Effects {
this.actions$.pipe( this.actions$.pipe(
ofType(loginRedirect), ofType(loginRedirect),
tap(authed => { tap(authed => {
this.ngZone.run(() => { // this.ngZone.run(() => {
// location.href = this.router.parseUrl('/account/login').toString(); // location.href = this.router.parseUrl('/account/login').toString();
this.router.navigate(['/account/login']).then(() => { this.router.navigate(['/account/login']);
this.appAuthenticationService.logout(); this.appAuthenticationService.logout();
this.store.dispatch(logoutInitialize()); this.store.dispatch(logoutInitialize());
}); // });
});
}) })
), ),
{ dispatch: false } { dispatch: false }
@ -147,6 +154,7 @@ export class Effects {
switchMap(action => { switchMap(action => {
return this.authenticationProtocolService.logout({}).pipe( return this.authenticationProtocolService.logout({}).pipe(
map(res => { map(res => {
this.protocolService.disconnect();
this.store.dispatch(loginRedirect()); this.store.dispatch(loginRedirect());
}), }),
catchError(error => of(error)) catchError(error => of(error))
@ -199,7 +207,11 @@ export class Effects {
EnvironmentsInfo EnvironmentsInfo
>(KEY_ENVIRONMENTS_INFO); >(KEY_ENVIRONMENTS_INFO);
if (!loginRes.privateInformationAgree) { if (
environment.productConfig.authentication
.usePrivateInformationAgree &&
!loginRes.privateInformationAgree
) {
const privacyTotalUrl = this.piService.privacyTotalUrl({ const privacyTotalUrl = this.piService.privacyTotalUrl({
companyCode: loginInfo.companyCode, companyCode: loginInfo.companyCode,
userSeq: loginRes.userSeq, userSeq: loginRes.userSeq,
@ -218,8 +230,8 @@ export class Effects {
height: '500px', height: '500px',
disableClose: true, disableClose: true,
data: { data: {
title: '개인정보 동의' title: '개인정보 동의',
// html: `<iframe id="ifm_privacy" src="${privacyTotalUrl}" style="width: 100%;height: 300px;" />` html: `<iframe id="ifm_privacy" src="${privacyTotalUrl}" style="width: 100%;height: 300px;" />`
} }
}); });
@ -231,7 +243,13 @@ export class Effects {
} }
} }
if (!!loginRes.passwordExpired) { if (loginInfo.initPw) {
this.store.dispatch(logout());
const passwordInitStep1Url = this.piService.passwordInitStep1Url({
localeCode: loginInfo.localeCode
});
const result = await this.dialogService.open< const result = await this.dialogService.open<
ConfirmDialogComponent, ConfirmDialogComponent,
ConfirmDialogData, ConfirmDialogData,
@ -241,8 +259,8 @@ export class Effects {
height: '500px', height: '500px',
disableClose: true, disableClose: true,
data: { data: {
title: '패스워드 만료', title: '패스워드 초기화',
message: '' html: `<iframe id="ifm_privacy" src="${passwordInitStep1Url}" style="width: 100%;height: 300px;" />`
} }
}); });
@ -251,6 +269,24 @@ export class Effects {
return; return;
} }
} }
if (!!loginRes.passwordExpired) {
const result = await this.dialogService.open<
ChangePasswordDialogComponent,
ChangePasswordDialogData,
ChangePasswordDialogResult
>(ChangePasswordDialogComponent, {
width: '500px',
height: '500px',
disableClose: false,
data: {}
});
if (!!result && result.choice) {
} else {
return;
}
}
}) })
), ),
{ dispatch: false } { dispatch: false }
@ -319,6 +355,7 @@ export class Effects {
private sessionStorageService: SessionStorageService, private sessionStorageService: SessionStorageService,
private piService: PiService, private piService: PiService,
private appAuthenticationService: AppAuthenticationService, private appAuthenticationService: AppAuthenticationService,
private protocolService: ProtocolService,
private authenticationProtocolService: AuthenticationProtocolService, private authenticationProtocolService: AuthenticationProtocolService,
private serviceProtocolService: ServiceProtocolService, private serviceProtocolService: ServiceProtocolService,
private dialogService: DialogService, private dialogService: DialogService,

View File

@ -155,7 +155,7 @@ export class Effects {
tap(() => { tap(() => {
groupList = []; groupList = [];
}), }),
switchMap(req => { exhaustMap(req => {
return this.syncProtocolService.group2(req).pipe( return this.syncProtocolService.group2(req).pipe(
map(res => { map(res => {
switch (res.SSVC_TYPE) { switch (res.SSVC_TYPE) {
@ -167,7 +167,7 @@ export class Effects {
case SSVC_TYPE_SYNC_GROUP_RES2: case SSVC_TYPE_SYNC_GROUP_RES2:
this.store.dispatch( this.store.dispatch(
group2Success({ group2Success({
groupList, groupList: [...groupList],
syncDate: (res as GroupResponse).syncDate syncDate: (res as GroupResponse).syncDate
}) })
); );

View File

@ -5,6 +5,7 @@ export const KEY_LOGIN_INFO = 'ucap::LOGIN_INFO';
export interface LoginInfo { export interface LoginInfo {
loginId?: string; loginId?: string;
loginPw?: string; loginPw?: string;
initPw?: boolean;
companyCode?: string; companyCode?: string;
companyGroupType?: string; companyGroupType?: string;
localeCode?: LocaleCode; localeCode?: LocaleCode;

View File

@ -13,6 +13,18 @@ export const environment: Environment = {
production: false, production: false,
title: `[개발] UCapMessenger`, title: `[개발] UCapMessenger`,
companyConfig: {
companyGroupCode: 'LG'
},
productConfig: {
productId: 'PRO_000482',
productName: 'EZMessenger',
authentication: {
usePrivateInformationAgree: false
}
},
commonApiModuleConfig: { commonApiModuleConfig: {
hostConfig: { hostConfig: {
protocol: 'http', protocol: 'http',

View File

@ -13,6 +13,18 @@ export const environment: Environment = {
production: true, production: true,
title: `[개발] UCapMessenger`, title: `[개발] UCapMessenger`,
companyConfig: {
companyGroupCode: 'LG'
},
productConfig: {
productId: 'PRO_000482',
productName: 'EZMessenger',
authentication: {
usePrivateInformationAgree: false
}
},
commonApiModuleConfig: { commonApiModuleConfig: {
hostConfig: { hostConfig: {
protocol: 'http', protocol: 'http',

View File

@ -31,6 +31,18 @@ export interface Environment {
runtime?: UCapRuntime; runtime?: UCapRuntime;
title: string; title: string;
companyConfig: {
companyGroupCode: string;
};
productConfig: {
productId: string;
productName: string;
authentication: {
usePrivateInformationAgree: boolean;
};
};
commonApiModuleConfig: CommonApiModuleConfig; commonApiModuleConfig: CommonApiModuleConfig;
publicApiModuleConfig: PublicApiModuleConfig; publicApiModuleConfig: PublicApiModuleConfig;
externalApiModuleConfig: ExternalApiModuleConfig; externalApiModuleConfig: ExternalApiModuleConfig;

View File

@ -0,0 +1,17 @@
import { PIRequest } from './pi';
import { LocaleCode } from '@ucap-webmessenger/core';
import { APIEncoder, ParameterUtil } from '@ucap-webmessenger/api';
export interface PasswordInitStep1Request extends PIRequest {
localeCode: LocaleCode;
}
const passwordInitStep1EncodeMap = {
localeCode: 'locale'
};
export const encodePasswordInitStep1: APIEncoder<PasswordInitStep1Request> = (
req: PasswordInitStep1Request
) => {
return ParameterUtil.encode(passwordInitStep1EncodeMap, req);
};

View File

@ -8,7 +8,7 @@ import {
Login2Request, Login2Request,
Login2Response, Login2Response,
encodeLogin2, encodeLogin2,
decodeLogin2, decodeLogin2
} from '../apis/login2'; } from '../apis/login2';
import { PrivacyTotalRequest, encodePrivacyTotal } from '../apis/privacy-total'; import { PrivacyTotalRequest, encodePrivacyTotal } from '../apis/privacy-total';
import { UrlUtil, Parameter } from '@ucap-webmessenger/api'; import { UrlUtil, Parameter } from '@ucap-webmessenger/api';
@ -16,8 +16,12 @@ import {
UserTermsActionRequest, UserTermsActionRequest,
UserTermsActionResponse, UserTermsActionResponse,
encodeUserTermsAction, encodeUserTermsAction,
decodeUserTermsAction, decodeUserTermsAction
} from '../apis/user-terms-action'; } from '../apis/user-terms-action';
import {
PasswordInitStep1Request,
encodePasswordInitStep1
} from '../apis/password-init-step1';
import { _MODULE_CONFIG } from '../config/token'; import { _MODULE_CONFIG } from '../config/token';
import { ModuleConfig } from '../config/module-config'; import { ModuleConfig } from '../config/module-config';
@ -25,7 +29,7 @@ import { Urls } from '../config/urls';
import { UrlConfig } from '@ucap-webmessenger/core'; import { UrlConfig } from '@ucap-webmessenger/core';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root'
}) })
export class PiService { export class PiService {
readonly urls: Urls; readonly urls: Urls;
@ -46,7 +50,7 @@ export class PiService {
this.urls.login2, this.urls.login2,
{}, {},
{ {
params: encodeLogin2(req), params: encodeLogin2(req)
} }
) )
.pipe(map(res => decodeLogin2(res))); .pipe(map(res => decodeLogin2(res)));
@ -60,7 +64,7 @@ export class PiService {
this.urls.userTermsAction, this.urls.userTermsAction,
{}, {},
{ {
params: encodeUserTermsAction(req), params: encodeUserTermsAction(req)
} }
) )
.pipe(map(res => decodeUserTermsAction(res))); .pipe(map(res => decodeUserTermsAction(res)));
@ -75,4 +79,14 @@ export class PiService {
encodePrivacyTotal(req) as Parameter encodePrivacyTotal(req) as Parameter
); );
} }
/**
* passwordInitStep1Url
*/
public passwordInitStep1Url(req: PasswordInitStep1Request): string {
return UrlUtil.format(
this.urls.passwordInitStep1,
encodePasswordInitStep1(req) as Parameter
);
}
} }

View File

@ -6,6 +6,7 @@ export * from './lib/apis/pi';
export * from './lib/apis/login2'; export * from './lib/apis/login2';
export * from './lib/apis/privacy-total'; export * from './lib/apis/privacy-total';
export * from './lib/apis/user-terms-action'; export * from './lib/apis/user-terms-action';
export * from './lib/apis/password-init-step1';
export * from './lib/types/response-status.type'; export * from './lib/types/response-status.type';

View File

@ -0,0 +1,52 @@
<div class="change-password-form">
<div class="mat-title">비밀번호 변경</div>
<form name="changePasswordForm" [formGroup]="changePasswordForm" novalidate>
<mat-form-field>
<mat-label>현재 패스워드</mat-label>
<input
matInput
type="password"
formControlName="currentLoginPw"
#currentLoginPw
/>
<mat-error>
현재 패스워드를 입력해 주세요
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>신규 패스워드</mat-label>
<input
matInput
type="password"
formControlName="newLoginPw"
#newLoginPw
/>
<mat-error>
신규 패스워드를 입력해 주세요
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>신규 패스워드 확인</mat-label>
<input
matInput
type="password"
formControlName="newConfirmLoginPw"
#newConfirmLoginPw
/>
<mat-error>
신규 패스워드 확인을 입력해 주세요
</mat-error>
</mat-form-field>
<button
mat-raised-button
class="submit-button bg-accent-dark"
aria-label="패스워드 변경"
[disabled]="changePasswordForm.invalid || !changePasswordBtnEnable"
(click)="onClickLogin()"
>
패스워드 변경
</button>
</form>
</div>

View File

@ -0,0 +1,63 @@
.change-password-form {
position: relative;
width: 384px;
max-width: 384px;
padding: 50px;
text-align: center;
background-color: rgba(255, 255, 255, 0.8);
border-radius: 0px;
box-shadow: 4px 4px 0px rgba(0, 0, 0, 0.1);
.mat-title {
margin: 16px 0 32px 0;
}
form {
width: 100%;
text-align: left;
mat-form-field {
width: 100%;
}
.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%;
}
}
}
}

View File

@ -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();
});
});

View File

@ -0,0 +1,67 @@
import {
Component,
OnInit,
Input,
Output,
EventEmitter,
ViewChild,
ElementRef,
ChangeDetectorRef
} from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Company } from '@ucap-webmessenger/api-external';
import { LocalStorageService } from '@ucap-webmessenger/web-storage';
import { LoginInfo, KEY_LOGIN_INFO } from '@app/types';
@Component({
selector: 'ucap-account-change-password',
templateUrl: './change-password.component.html',
styleUrls: ['./change-password.component.scss']
})
export class ChangePasswordComponent implements OnInit {
@Input()
changePasswordBtnEnable: boolean;
@Output()
changePassword = new EventEmitter<{
currentLoginPw: string;
newLoginPw: string;
newConfirmLoginPw: string;
notValid: () => void;
}>();
@ViewChild('currentLoginPw', { static: true })
currentLoginPwElementRef: ElementRef;
@ViewChild('newLoginPw', { static: true })
newLoginPwElementRef: ElementRef;
changePasswordForm: FormGroup;
constructor(
private formBuilder: FormBuilder,
private changeDetectorRef: ChangeDetectorRef,
private localStorageService: LocalStorageService
) {}
ngOnInit() {
const loginInfo: LoginInfo = this.localStorageService.get<LoginInfo>(
KEY_LOGIN_INFO
);
this.changePasswordForm = this.formBuilder.group({
currentLoginPw: ['', Validators.required],
newLoginPw: ['', Validators.required],
newConfirmLoginPw: ['', Validators.required]
});
}
onClickLogin() {
this.changePassword.emit({
currentLoginPw: this.changePasswordForm.get('currentLoginPw').value,
newLoginPw: this.changePasswordForm.get('newLoginPw').value,
newConfirmLoginPw: this.changePasswordForm.get('newConfirmLoginPw').value,
notValid: () => {
this.currentLoginPwElementRef.nativeElement.focus();
}
});
}
}

View File

@ -11,11 +11,12 @@ import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { ChangePasswordComponent } from './components/change-password.component';
import { LoginComponent } from './components/login.component'; import { LoginComponent } from './components/login.component';
import { AccountService } from './services/account.service'; import { AccountService } from './services/account.service';
const COMPONENTS = [LoginComponent]; const COMPONENTS = [ChangePasswordComponent, LoginComponent];
const SERVICES = [AccountService]; const SERVICES = [AccountService];
@NgModule({ @NgModule({

View File

@ -3,5 +3,6 @@
*/ */
export * from './lib/services/account.service'; export * from './lib/services/account.service';
export * from './lib/components/change-password.component';
export * from './lib/components/login.component'; export * from './lib/components/login.component';
export * from './lib/ucap-ui-account.module'; export * from './lib/ucap-ui-account.module';