MOBILE-3565 login: Implement forgotten password page
parent
d66c744ab8
commit
996f1c6ae3
|
@ -37,6 +37,11 @@ const routes: Routes = [
|
||||||
path: 'sites',
|
path: 'sites',
|
||||||
loadChildren: () => import('./pages/sites/sites.page.module').then( m => m.CoreLoginSitesPageModule),
|
loadChildren: () => import('./pages/sites/sites.page.module').then( m => m.CoreLoginSitesPageModule),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'forgottenpassword',
|
||||||
|
loadChildren: () => import('./pages/forgotten-password/forgotten-password.module')
|
||||||
|
.then( m => m.CoreLoginForgottenPasswordPageModule),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -264,12 +264,7 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
|
||||||
* Forgotten password button clicked.
|
* Forgotten password button clicked.
|
||||||
*/
|
*/
|
||||||
forgottenPassword(): void {
|
forgottenPassword(): void {
|
||||||
CoreLoginHelper.instance.forgottenPasswordClicked(
|
CoreLoginHelper.instance.forgottenPasswordClicked(this.siteUrl, this.credForm.value.username, this.siteConfig);
|
||||||
this.navCtrl,
|
|
||||||
this.siteUrl,
|
|
||||||
this.credForm.value.username,
|
|
||||||
this.siteConfig,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-buttons slot="start">
|
||||||
|
<ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button>
|
||||||
|
</ion-buttons>
|
||||||
|
|
||||||
|
<ion-title>{{ 'core.login.passwordforgotten' | translate }}</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
<ion-content>
|
||||||
|
<ion-list lines="none">
|
||||||
|
<ion-item class="ion-text-wrap">
|
||||||
|
{{ 'core.login.passwordforgotteninstructions2' | translate }}
|
||||||
|
</ion-item>
|
||||||
|
</ion-list>
|
||||||
|
<ion-card>
|
||||||
|
<form ion-list [formGroup]="myForm" (ngSubmit)="resetPassword($event)" #resetPasswordForm>
|
||||||
|
<ion-item-divider class="ion-text-wrap">
|
||||||
|
{{ 'core.login.searchby' | translate }}
|
||||||
|
</ion-item-divider>
|
||||||
|
<ion-radio-group formControlName="field">
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>{{ 'core.login.username' | translate }}</ion-label>
|
||||||
|
<ion-radio slot="start" value="username"></ion-radio>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>{{ 'core.user.email' | translate }}</ion-label>
|
||||||
|
<ion-radio slot="start" value="email"></ion-radio>
|
||||||
|
</ion-item>
|
||||||
|
</ion-radio-group>
|
||||||
|
<ion-item>
|
||||||
|
<ion-input type="text" name="value" placeholder="{{ 'core.login.usernameoremail' | translate }}"
|
||||||
|
formControlName="value" autocapitalize="none" autocorrect="off" [core-auto-focus]="autoFocus">
|
||||||
|
</ion-input>
|
||||||
|
</ion-item>
|
||||||
|
<ion-button type="submit" class="ion-margin" expand="block" [disabled]="!myForm.valid">
|
||||||
|
{{ 'core.courses.search' | translate }}
|
||||||
|
</ion-button>
|
||||||
|
</form>
|
||||||
|
</ion-card>
|
||||||
|
</ion-content>
|
|
@ -0,0 +1,47 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
import { IonicModule } from '@ionic/angular';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||||
|
import { CoreLoginForgottenPasswordPage } from './forgotten-password.page';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: CoreLoginForgottenPasswordPage,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes),
|
||||||
|
CommonModule,
|
||||||
|
IonicModule,
|
||||||
|
TranslateModule.forChild(),
|
||||||
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
CoreDirectivesModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
CoreLoginForgottenPasswordPage,
|
||||||
|
],
|
||||||
|
exports: [RouterModule],
|
||||||
|
})
|
||||||
|
export class CoreLoginForgottenPasswordPageModule {}
|
|
@ -0,0 +1,120 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { NavController } from '@ionic/angular';
|
||||||
|
|
||||||
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
import { CoreLoginHelper } from '@core/login/services/helper';
|
||||||
|
import { Translate, Platform } from '@singletons/core.singletons';
|
||||||
|
import { CoreWSExternalWarning } from '@services/ws';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page to recover a forgotten password.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'page-core-login-forgotten-password',
|
||||||
|
templateUrl: 'forgotten-password.html',
|
||||||
|
})
|
||||||
|
export class CoreLoginForgottenPasswordPage implements OnInit {
|
||||||
|
|
||||||
|
@ViewChild('resetPasswordForm') formElement?: ElementRef;
|
||||||
|
|
||||||
|
myForm!: FormGroup;
|
||||||
|
siteUrl!: string;
|
||||||
|
autoFocus!: boolean;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected navCtrl: NavController,
|
||||||
|
protected formBuilder: FormBuilder,
|
||||||
|
protected route: ActivatedRoute,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the component.
|
||||||
|
*/
|
||||||
|
ngOnInit(): void {
|
||||||
|
const params = this.route.snapshot.queryParams;
|
||||||
|
|
||||||
|
this.siteUrl = params['siteUrl'];
|
||||||
|
this.autoFocus = Platform.instance.is('tablet');
|
||||||
|
this.myForm = this.formBuilder.group({
|
||||||
|
field: ['username', Validators.required],
|
||||||
|
value: [params['username'] || '', Validators.required],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request to reset the password.
|
||||||
|
*
|
||||||
|
* @param e Event.
|
||||||
|
*/
|
||||||
|
async resetPassword(e: Event): Promise<void> {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const field = this.myForm.value.field;
|
||||||
|
const value = this.myForm.value.value;
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
CoreDomUtils.instance.showErrorModal('core.login.usernameoremail', true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modal = await CoreDomUtils.instance.showModalLoading('core.sending', true);
|
||||||
|
const isMail = field == 'email';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await CoreLoginHelper.instance.requestPasswordReset(
|
||||||
|
this.siteUrl,
|
||||||
|
isMail ? '' : value,
|
||||||
|
isMail ? value : '',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.status == 'dataerror') {
|
||||||
|
// Error in the data sent.
|
||||||
|
this.showError(isMail, response.warnings!);
|
||||||
|
} else if (response.status == 'emailpasswordconfirmnotsent' || response.status == 'emailpasswordconfirmnoemail') {
|
||||||
|
// Error, not found.
|
||||||
|
CoreDomUtils.instance.showErrorModal(response.notice);
|
||||||
|
} else {
|
||||||
|
// Success.
|
||||||
|
CoreDomUtils.instance.triggerFormSubmittedEvent(this.formElement, true);
|
||||||
|
|
||||||
|
CoreDomUtils.instance.showAlert(Translate.instance.instant('core.success'), response.notice);
|
||||||
|
this.navCtrl.pop();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
CoreDomUtils.instance.showErrorModal(error);
|
||||||
|
} finally {
|
||||||
|
modal.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show an error from the warnings.
|
||||||
|
protected showError(isMail: boolean, warnings: CoreWSExternalWarning[]): void {
|
||||||
|
for (let i = 0; i < warnings.length; i++) {
|
||||||
|
const warning = warnings[i];
|
||||||
|
if ((warning.item == 'email' && isMail) || (warning.item == 'username' && !isMail)) {
|
||||||
|
CoreDomUtils.instance.showErrorModal(warning.message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -163,12 +163,7 @@ export class CoreLoginHelperProvider {
|
||||||
* @param username Username.
|
* @param username Username.
|
||||||
* @param siteConfig Site config.
|
* @param siteConfig Site config.
|
||||||
*/
|
*/
|
||||||
async forgottenPasswordClicked(
|
async forgottenPasswordClicked(siteUrl: string, username: string, siteConfig?: CoreSitePublicConfigResponse): Promise<void> {
|
||||||
navCtrl: NavController,
|
|
||||||
siteUrl: string,
|
|
||||||
username: string,
|
|
||||||
siteConfig?: CoreSitePublicConfigResponse,
|
|
||||||
): Promise<void> {
|
|
||||||
if (siteConfig && siteConfig.forgottenpasswordurl) {
|
if (siteConfig && siteConfig.forgottenpasswordurl) {
|
||||||
// URL set, open it.
|
// URL set, open it.
|
||||||
CoreUtils.instance.openInApp(siteConfig.forgottenpasswordurl);
|
CoreUtils.instance.openInApp(siteConfig.forgottenpasswordurl);
|
||||||
|
@ -183,7 +178,7 @@ export class CoreLoginHelperProvider {
|
||||||
const canReset = await this.canRequestPasswordReset(siteUrl);
|
const canReset = await this.canRequestPasswordReset(siteUrl);
|
||||||
|
|
||||||
if (canReset) {
|
if (canReset) {
|
||||||
await navCtrl.navigateForward(['/login/forgottenpassword'], {
|
await this.navCtrl.navigateForward(['/login/forgottenpassword'], {
|
||||||
queryParams: {
|
queryParams: {
|
||||||
siteUrl,
|
siteUrl,
|
||||||
username,
|
username,
|
||||||
|
@ -445,7 +440,6 @@ export class CoreLoginHelperProvider {
|
||||||
/**
|
/**
|
||||||
* Open a page that doesn't belong to any site.
|
* Open a page that doesn't belong to any site.
|
||||||
*
|
*
|
||||||
* @param navCtrl Nav Controller.
|
|
||||||
* @param page Page to open.
|
* @param page Page to open.
|
||||||
* @param params Params of the page.
|
* @param params Params of the page.
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
|
|
Loading…
Reference in New Issue