mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-09-04 10:14:13 +08:00
Add forgot password inputs to login component
- Add forgot password form inputs - Add card flipping using fade -- Add ng-animations lib - Expose email appStrings label - Only show forgot password when enabled on the backend
This commit is contained in:
parent
3efa62fc42
commit
32f6ddd81b
6 changed files with 107 additions and 32 deletions
|
@ -3,40 +3,74 @@
|
|||
<!-- Start of login form section -->
|
||||
|
||||
<form name="login" class="login-form">
|
||||
<scrm-logo-ui></scrm-logo-ui>
|
||||
<scrm-logo-ui></scrm-logo-ui>
|
||||
|
||||
<div class="form-group row" *ngIf="vm.showLanguages">
|
||||
<label class="col-sm-3 ml-2 col-form-label" for="languages">{{vm.appStrings['LBL_LANGUAGE']}}:</label>
|
||||
<div class="select col-sm-8 p-0 inner-addon left-addon">
|
||||
<select #languageSelect id="languages" (change)="languageFacade.updateLanguage(languageSelect.value)">
|
||||
<option [value]="item.key"
|
||||
*ngFor="let item of vm.systemConfigs['languages'].items | keyvalue">{{item.value}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="inner-addon left-addon">
|
||||
<svg-icon class="sicon" src="public/themes/suite8/images/login_user.svg"></svg-icon>
|
||||
<input [(ngModel)]="uname" type="text" name="username"
|
||||
placeholder="{{vm.appStrings['LBL_USER_NAME']}}" aria-label="Username">
|
||||
</div>
|
||||
|
||||
<div class="inner-addon left-addon">
|
||||
<svg-icon class="sicon" src="public/themes/suite8/images/login_password.svg"></svg-icon>
|
||||
<input [(ngModel)]="passw" type="password" name="password"
|
||||
placeholder="{{vm.appStrings['LBL_PASSWORD']}}" aria-label="Password">
|
||||
<div class="form-group row" *ngIf="vm.showLanguages">
|
||||
<label class="col-sm-3 ml-2 col-form-label" for="languages">{{vm.appStrings['LBL_LANGUAGE']}}:</label>
|
||||
<div class="select col-sm-8 p-0 inner-addon left-addon">
|
||||
<select #languageSelect id="languages" (change)="languageFacade.updateLanguage(languageSelect.value)">
|
||||
<option [value]="item.key"
|
||||
*ngFor="let item of vm.systemConfigs['languages'].items | keyvalue">{{item.value}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="login-button"
|
||||
(click)="doLogin()">{{vm.appStrings['LBL_LOGIN_BUTTON_LABEL']}}</button>
|
||||
<div class="forgotten-password">
|
||||
<a href="#" class="forgotten-password-link">
|
||||
{{vm.appStrings['LBL_LOGIN_FORGOT_PASSWORD']}}
|
||||
</a>
|
||||
|
||||
<div class="fade-card">
|
||||
|
||||
<!-- Card front -->
|
||||
<div class="fade-card-front" *ngIf="cardState==='front'" [@fade]>
|
||||
|
||||
<div class="inner-addon left-addon">
|
||||
<svg-icon class="sicon" src="public/themes/suite8/images/login_user.svg"></svg-icon>
|
||||
<input [(ngModel)]="uname" type="text" name="username"
|
||||
placeholder="{{vm.appStrings['LBL_USER_NAME']}}" aria-label="Username">
|
||||
</div>
|
||||
|
||||
<div class="inner-addon left-addon">
|
||||
<svg-icon class="sicon" src="public/themes/suite8/images/login_password.svg"></svg-icon>
|
||||
<input [(ngModel)]="passw" type="password" name="password"
|
||||
placeholder="{{vm.appStrings['LBL_PASSWORD']}}" aria-label="Password">
|
||||
</div>
|
||||
|
||||
<button class="login-button"
|
||||
(click)="doLogin()">{{vm.appStrings['LBL_LOGIN_BUTTON_LABEL']}}</button>
|
||||
<div class="forgotten-password" *ngIf="vm.showForgotPassword">
|
||||
<a href="#" class="forgotten-password-link" (click)="flipCard()">
|
||||
{{vm.appStrings['LBL_LOGIN_FORGOT_PASSWORD']}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Card back-->
|
||||
<div class="fade-card-back" *ngIf="cardState==='back'" [@fade]>
|
||||
<div class="inner-addon left-addon">
|
||||
<svg-icon class="sicon" src="public/themes/suite8/images/login_user.svg"></svg-icon>
|
||||
<input [(ngModel)]="uname" type="text" name="username"
|
||||
placeholder="{{vm.appStrings['LBL_USER_NAME']}}" aria-label="Username">
|
||||
</div>
|
||||
|
||||
<div class="inner-addon left-addon">
|
||||
<svg-icon class="sicon" src="public/themes/suite8/images/email.svg"></svg-icon>
|
||||
<input [(ngModel)]="email" type="email" name="email"
|
||||
placeholder="{{vm.appStrings['LBL_EMAIL']}}" aria-label="Email">
|
||||
</div>
|
||||
|
||||
<button class="submit-button login-button" (click)="recoverPassword()">
|
||||
{{vm.appStrings['LBL_GENERATE_PASSWORD_BUTTON_TITLE']}}
|
||||
</button>
|
||||
<div>
|
||||
<a href="#" class="forgotten-password-link" (click)="flipCard()">
|
||||
{{vm.appStrings['LBL_BACK']}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<!-- End of login form section -->
|
||||
<!-- End of login form section -->
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -11,17 +11,29 @@ import {SystemConfigFacade, SystemConfigMap} from '@services/metadata/configs/sy
|
|||
import {combineLatest, Observable} from 'rxjs';
|
||||
import {LanguageFacade, LanguageStringMap} from '@base/facades/language.facade';
|
||||
import {map} from 'rxjs/operators';
|
||||
import {transition, trigger, useAnimation} from '@angular/animations';
|
||||
import {fadeIn} from 'ng-animate';
|
||||
|
||||
@Component({
|
||||
selector: 'scrm-login-ui',
|
||||
templateUrl: './login.component.html',
|
||||
styleUrls: []
|
||||
styleUrls: [],
|
||||
animations: [
|
||||
trigger('fade', [
|
||||
transition(':enter', useAnimation(fadeIn, {
|
||||
params: {timing: 0.5, delay: 0}
|
||||
})),
|
||||
])
|
||||
]
|
||||
})
|
||||
export class LoginUiComponent {
|
||||
hidden = true;
|
||||
error = '';
|
||||
uname = '';
|
||||
passw = '';
|
||||
email = '';
|
||||
|
||||
cardState = 'front';
|
||||
|
||||
systemConfigs$: Observable<SystemConfigMap> = this.systemConfigFacade.configs$;
|
||||
appStrings$: Observable<LanguageStringMap> = this.languageFacade.languageStrings$;
|
||||
|
@ -29,15 +41,23 @@ export class LoginUiComponent {
|
|||
vm$ = combineLatest([this.systemConfigs$, this.appStrings$]).pipe(
|
||||
map(([systemConfigs, appStrings]) => {
|
||||
let showLanguages = false;
|
||||
let showForgotPassword = false;
|
||||
|
||||
if (systemConfigs.languages && systemConfigs.languages.items) {
|
||||
showLanguages = Object.keys(systemConfigs.languages.items).length > 1;
|
||||
}
|
||||
|
||||
if (systemConfigs.passwordsetting && systemConfigs.passwordsetting.items) {
|
||||
const forgotPasswordProperty = systemConfigs.passwordsetting.items.forgotpasswordON;
|
||||
showForgotPassword = [true, '1', 'true'].includes(forgotPasswordProperty);
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
systemConfigs,
|
||||
appStrings,
|
||||
showLanguages
|
||||
showLanguages,
|
||||
showForgotPassword
|
||||
};
|
||||
})
|
||||
);
|
||||
|
@ -62,10 +82,21 @@ export class LoginUiComponent {
|
|||
this.hidden = false;
|
||||
}
|
||||
|
||||
flipCard() {
|
||||
if (this.cardState === 'front') {
|
||||
this.cardState = 'back';
|
||||
} else {
|
||||
this.cardState = 'front';
|
||||
}
|
||||
}
|
||||
|
||||
doLogin() {
|
||||
this.auth.doLogin(this, this.uname, this.passw, this.onLoginSuccess, this.onLoginError);
|
||||
}
|
||||
|
||||
recoverPassword() {
|
||||
}
|
||||
|
||||
onLoginSuccess(caller: LoginUiComponent, loginResponse: LoginResponseModel) {
|
||||
caller.message.log('OAuth2 login success');
|
||||
caller.router.navigate(['/Home']);
|
||||
|
|
|
@ -8,7 +8,7 @@ export interface SystemConfig {
|
|||
id: string;
|
||||
_id: string;
|
||||
value: string;
|
||||
items: {};
|
||||
items: { [key: string]: any };
|
||||
}
|
||||
|
||||
export interface SystemConfigMap {
|
||||
|
|
|
@ -22,7 +22,8 @@ class AppStringsHandler extends LegacyHandler
|
|||
'ERR_INVALID_PASSWORD',
|
||||
'LBL_PASSWORD',
|
||||
'LBL_LANGUAGE',
|
||||
'LBL_LOGIN_FORGOT_PASSWORD'
|
||||
'LBL_LOGIN_FORGOT_PASSWORD',
|
||||
'LBL_EMAIL'
|
||||
]
|
||||
];
|
||||
|
||||
|
|
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -9703,6 +9703,14 @@
|
|||
"resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz",
|
||||
"integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug=="
|
||||
},
|
||||
"ng-animate": {
|
||||
"version": "0.3.4",
|
||||
"resolved": "https://registry.npmjs.org/ng-animate/-/ng-animate-0.3.4.tgz",
|
||||
"integrity": "sha512-akMSySNAAe4H7f+XhjDvRnxa1eg+6zvl0DwVFXYpFDiGClPGlC93hT1+EXq0z9rq2U8IpBFh2FkSUT/FRIeROw==",
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"ng2-charts": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-2.3.0.tgz",
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
"core-js": "^3.6.4",
|
||||
"graphql": "^14.6.0",
|
||||
"graphql-tag": "^2.10.3",
|
||||
"ng-animate": "^0.3.4",
|
||||
"ng2-charts": "^2.2.3",
|
||||
"nyc": "~14.1.1",
|
||||
"object-hash": "^2.0.2",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue