MOBILE-3565 login: Initial implementation of credentials page
parent
73612f5138
commit
317444049c
|
@ -13,11 +13,15 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
import { IonicModule } from '@ionic/angular';
|
import { IonicModule } from '@ionic/angular';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { CoreIconComponent } from './icon/icon';
|
import { CoreIconComponent } from './icon/icon';
|
||||||
import { CoreLoadingComponent } from './loading/loading';
|
import { CoreLoadingComponent } from './loading/loading';
|
||||||
import { CoreShowPasswordComponent } from './show-password/show-password';
|
import { CoreShowPasswordComponent } from './show-password/show-password';
|
||||||
|
import { CoreDirectivesModule } from '@app/directives/directives.module';
|
||||||
|
import { CorePipesModule } from '@app/pipes/pipes.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -26,7 +30,11 @@ import { CoreShowPasswordComponent } from './show-password/show-password';
|
||||||
CoreShowPasswordComponent,
|
CoreShowPasswordComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
IonicModule,
|
CommonModule,
|
||||||
|
IonicModule.forRoot(),
|
||||||
|
TranslateModule.forChild(),
|
||||||
|
CoreDirectivesModule,
|
||||||
|
CorePipesModule,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CoreIconComponent,
|
CoreIconComponent,
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
|
||||||
|
import { CoreLoginCredentialsPage } from './pages/credentials/credentials.page';
|
||||||
import { CoreLoginInitPage } from './pages/init/init.page';
|
import { CoreLoginInitPage } from './pages/init/init.page';
|
||||||
import { CoreLoginSitePage } from './pages/site/site.page';
|
import { CoreLoginSitePage } from './pages/site/site.page';
|
||||||
|
|
||||||
|
@ -27,6 +28,10 @@ const routes: Routes = [
|
||||||
path: 'site',
|
path: 'site',
|
||||||
component: CoreLoginSitePage,
|
component: CoreLoginSitePage,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'credentials',
|
||||||
|
component: CoreLoginCredentialsPage,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -20,8 +20,10 @@ import { IonicModule } from '@ionic/angular';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { CoreComponentsModule } from '@/app/components/components.module';
|
import { CoreComponentsModule } from '@/app/components/components.module';
|
||||||
|
import { CoreDirectivesModule } from '@/app/directives/directives.module';
|
||||||
|
|
||||||
import { CoreLoginRoutingModule } from './login-routing.module';
|
import { CoreLoginRoutingModule } from './login-routing.module';
|
||||||
|
import { CoreLoginCredentialsPage } from './pages/credentials/credentials.page';
|
||||||
import { CoreLoginInitPage } from './pages/init/init.page';
|
import { CoreLoginInitPage } from './pages/init/init.page';
|
||||||
import { CoreLoginSitePage } from './pages/site/site.page';
|
import { CoreLoginSitePage } from './pages/site/site.page';
|
||||||
import { CoreLoginHelperProvider } from './services/helper';
|
import { CoreLoginHelperProvider } from './services/helper';
|
||||||
|
@ -35,8 +37,10 @@ import { CoreLoginHelperProvider } from './services/helper';
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
CoreComponentsModule,
|
CoreComponentsModule,
|
||||||
|
CoreDirectivesModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
|
CoreLoginCredentialsPage,
|
||||||
CoreLoginInitPage,
|
CoreLoginInitPage,
|
||||||
CoreLoginSitePage,
|
CoreLoginSitePage,
|
||||||
],
|
],
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-buttons slot="start">
|
||||||
|
<ion-back-button></ion-back-button>
|
||||||
|
</ion-buttons>
|
||||||
|
|
||||||
|
<ion-title>{{ 'core.login.login' | translate }}</ion-title>
|
||||||
|
|
||||||
|
<ion-buttons slot="end">
|
||||||
|
<!-- @todo: Settings button. -->
|
||||||
|
</ion-buttons>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
<ion-content padding>
|
||||||
|
<core-loading [hideUntil]="pageLoaded">
|
||||||
|
<div text-wrap text-center margin-bottom>
|
||||||
|
<div class="core-login-site-logo">
|
||||||
|
<!-- Show site logo or a default image. -->
|
||||||
|
<img *ngIf="logoUrl" [src]="logoUrl" role="presentation" onError="this.src='assets/img/login_logo.png'">
|
||||||
|
<img *ngIf="!logoUrl" src="assets/img/login_logo.png" role="presentation">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 *ngIf="siteName" padding class="core-sitename"><core-format-text [text]="siteName" [filter]="false"></core-format-text></h3>
|
||||||
|
<p class="core-siteurl">{{siteUrl}}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form ion-list [formGroup]="credForm" (ngSubmit)="login($event)" class="core-login-form" #credentialsForm>
|
||||||
|
<ion-item *ngIf="siteChecked && !isBrowserSSO">
|
||||||
|
<ion-input type="text" name="username" placeholder="{{ 'core.login.username' | translate }}" formControlName="username" autocapitalize="none" autocorrect="off"></ion-input>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item *ngIf="siteChecked && !isBrowserSSO" margin-bottom>
|
||||||
|
<core-show-password item-content [name]="'password'">
|
||||||
|
<ion-input class="core-ioninput-password" name="password" type="password" placeholder="{{ 'core.login.password' | translate }}" formControlName="password" core-show-password [clearOnEdit]="false"></ion-input>
|
||||||
|
</core-show-password>
|
||||||
|
</ion-item>
|
||||||
|
<div padding>
|
||||||
|
<ion-button block type="submit" [disabled]="siteChecked && !isBrowserSSO && !credForm.valid" class="core-login-login-button">{{ 'core.login.loginbutton' | translate }}</ion-button>
|
||||||
|
<input type="submit" className="core-submit-enter" /> <!-- Remove this once Ionic fixes this bug: https://github.com/ionic-team/ionic-framework/issues/19368 -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="showScanQR">
|
||||||
|
<div class="core-login-site-qrcode-separator">{{ 'core.login.or' | translate }}</div>
|
||||||
|
<ion-item class="core-login-site-qrcode" no-lines>
|
||||||
|
<ion-button block color="light" margin-top icon-start text-wrap (click)="showInstructionsAndScanQR()">
|
||||||
|
<core-icon name="fa-qrcode" aria-hidden="true"></core-icon>
|
||||||
|
{{ 'core.scanqr' | translate }}
|
||||||
|
</ion-button>
|
||||||
|
</ion-item>
|
||||||
|
</ng-container>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Forgotten password button. -->
|
||||||
|
<ion-list no-lines *ngIf="showForgottenPassword" class="core-login-forgotten-password">
|
||||||
|
<ion-item text-center text-wrap (click)="forgottenPassword()" detail-none>
|
||||||
|
{{ 'core.login.forgotten' | translate }}
|
||||||
|
</ion-item>
|
||||||
|
</ion-list>
|
||||||
|
|
||||||
|
<ion-list *ngIf="identityProviders && identityProviders.length" padding-top class="core-login-identity-providers">
|
||||||
|
<ion-item text-wrap no-lines><h3 class="item-heading">{{ 'core.login.potentialidps' | translate }}</h3></ion-item>
|
||||||
|
<ion-item *ngFor="let provider of identityProviders" text-wrap class="core-oauth-icon" (click)="oauthClicked(provider)" title="{{provider.name}}">
|
||||||
|
<img [src]="provider.iconurl" alt="" width="32" height="32" item-start>
|
||||||
|
{{provider.name}}
|
||||||
|
</ion-item>
|
||||||
|
</ion-list>
|
||||||
|
|
||||||
|
<ion-list *ngIf="canSignup" padding-top class="core-login-sign-up">
|
||||||
|
<ion-item text-wrap no-lines><h3 class="item-heading">{{ 'core.login.firsttime' | translate }}</h3></ion-item>
|
||||||
|
<ion-item no-lines text-wrap *ngIf="authInstructions">
|
||||||
|
<p><core-format-text [text]="authInstructions" [filter]="false"></core-format-text></p>
|
||||||
|
</ion-item>
|
||||||
|
<ion-button block color="light" (onClick)="signup()">{{ 'core.login.startsignup' | translate }}</ion-button>
|
||||||
|
</ion-list>
|
||||||
|
</core-loading>
|
||||||
|
</ion-content>
|
|
@ -0,0 +1,326 @@
|
||||||
|
// (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, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
import { NavController } from '@ionic/angular';
|
||||||
|
|
||||||
|
import { CoreApp } from '@services/app';
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
|
import { CoreLoginHelper, CoreLoginHelperProvider } from '@core/login/services/helper';
|
||||||
|
import CoreConfigConstants from '@app/config.json';
|
||||||
|
import { Translate } from '@singletons/core.singletons';
|
||||||
|
import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@/app/classes/site';
|
||||||
|
import { CoreEvents, CoreEventsProvider } from '@/app/services/events';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page that displays a "splash screen" while the app is being initialized.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'page-core-login-credentials',
|
||||||
|
templateUrl: 'credentials.html',
|
||||||
|
})
|
||||||
|
export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
@ViewChild('credentialsForm') formElement: ElementRef;
|
||||||
|
|
||||||
|
credForm: FormGroup;
|
||||||
|
siteUrl: string;
|
||||||
|
siteChecked = false;
|
||||||
|
siteName: string;
|
||||||
|
logoUrl: string;
|
||||||
|
authInstructions: string;
|
||||||
|
canSignup: boolean;
|
||||||
|
identityProviders: CoreSiteIdentityProvider[];
|
||||||
|
pageLoaded = false;
|
||||||
|
isBrowserSSO = false;
|
||||||
|
isFixedUrlSet = false;
|
||||||
|
showForgottenPassword = true;
|
||||||
|
showScanQR: boolean;
|
||||||
|
|
||||||
|
protected siteConfig: CoreSitePublicConfigResponse;
|
||||||
|
protected eventThrown = false;
|
||||||
|
protected viewLeft = false;
|
||||||
|
protected siteId: string;
|
||||||
|
protected urlToOpen: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected fb: FormBuilder,
|
||||||
|
protected route: ActivatedRoute,
|
||||||
|
protected navCtrl: NavController,
|
||||||
|
) {
|
||||||
|
|
||||||
|
const canScanQR = CoreUtils.instance.canScanQR();
|
||||||
|
if (canScanQR) {
|
||||||
|
if (typeof CoreConfigConstants['displayqroncredentialscreen'] == 'undefined') {
|
||||||
|
this.showScanQR = CoreLoginHelper.instance.isFixedUrlSet();
|
||||||
|
} else {
|
||||||
|
this.showScanQR = !!CoreConfigConstants['displayqroncredentialscreen'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.showScanQR = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the component.
|
||||||
|
*/
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.route.queryParams.subscribe(params => {
|
||||||
|
this.siteUrl = params['siteUrl'];
|
||||||
|
this.siteName = params['siteName'] || null;
|
||||||
|
this.logoUrl = !CoreConfigConstants.forceLoginLogo && params['logoUrl'] || null;
|
||||||
|
this.siteConfig = params['siteConfig'];
|
||||||
|
this.urlToOpen = params['urlToOpen'];
|
||||||
|
|
||||||
|
this.credForm = this.fb.group({
|
||||||
|
username: [params['username'] || '', Validators.required],
|
||||||
|
password: ['', Validators.required],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.treatSiteConfig();
|
||||||
|
this.isFixedUrlSet = CoreLoginHelper.instance.isFixedUrlSet();
|
||||||
|
|
||||||
|
if (this.isFixedUrlSet) {
|
||||||
|
// Fixed URL, we need to check if it uses browser SSO login.
|
||||||
|
this.checkSite(this.siteUrl);
|
||||||
|
} else {
|
||||||
|
this.siteChecked = true;
|
||||||
|
this.pageLoaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a site uses local_mobile, requires SSO login, etc.
|
||||||
|
* This should be used only if a fixed URL is set, otherwise this check is already performed in CoreLoginSitePage.
|
||||||
|
*
|
||||||
|
* @param siteUrl Site URL to check.
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async checkSite(siteUrl: string): Promise<void> {
|
||||||
|
this.pageLoaded = false;
|
||||||
|
|
||||||
|
// If the site is configured with http:// protocol we force that one, otherwise we use default mode.
|
||||||
|
const protocol = siteUrl.indexOf('http://') === 0 ? 'http://' : undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await CoreSites.instance.checkSite(siteUrl, protocol);
|
||||||
|
|
||||||
|
this.siteChecked = true;
|
||||||
|
this.siteUrl = result.siteUrl;
|
||||||
|
|
||||||
|
this.siteConfig = result.config;
|
||||||
|
this.treatSiteConfig();
|
||||||
|
|
||||||
|
if (result && result.warning) {
|
||||||
|
CoreDomUtils.instance.showErrorModal(result.warning, true, 4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CoreLoginHelper.instance.isSSOLoginNeeded(result.code)) {
|
||||||
|
// SSO. User needs to authenticate in a browser.
|
||||||
|
this.isBrowserSSO = true;
|
||||||
|
|
||||||
|
// Check that there's no SSO authentication ongoing and the view hasn't changed.
|
||||||
|
if (!CoreApp.instance.isSSOAuthenticationOngoing() && !this.viewLeft) {
|
||||||
|
CoreLoginHelper.instance.confirmAndOpenBrowserForSSOLogin(
|
||||||
|
result.siteUrl, result.code, result.service, result.config?.launchurl);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.isBrowserSSO = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
CoreDomUtils.instance.showErrorModal(error);
|
||||||
|
} finally {
|
||||||
|
this.pageLoaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Treat the site configuration (if it exists).
|
||||||
|
*/
|
||||||
|
protected treatSiteConfig(): void {
|
||||||
|
if (this.siteConfig) {
|
||||||
|
this.siteName = CoreConfigConstants.sitename ? CoreConfigConstants.sitename : this.siteConfig.sitename;
|
||||||
|
this.logoUrl = CoreLoginHelper.instance.getLogoUrl(this.siteConfig);
|
||||||
|
this.authInstructions = this.siteConfig.authinstructions || Translate.instance.instant('core.login.loginsteps');
|
||||||
|
|
||||||
|
const disabledFeatures = CoreLoginHelper.instance.getDisabledFeatures(this.siteConfig);
|
||||||
|
this.identityProviders = CoreLoginHelper.instance.getValidIdentityProviders(this.siteConfig, disabledFeatures);
|
||||||
|
this.canSignup = this.siteConfig.registerauth == 'email' &&
|
||||||
|
!CoreLoginHelper.instance.isEmailSignupDisabled(this.siteConfig, disabledFeatures);
|
||||||
|
this.showForgottenPassword = !CoreLoginHelper.instance.isForgottenPasswordDisabled(this.siteConfig, disabledFeatures);
|
||||||
|
|
||||||
|
if (!this.eventThrown && !this.viewLeft) {
|
||||||
|
this.eventThrown = true;
|
||||||
|
CoreEvents.instance.trigger(CoreEventsProvider.LOGIN_SITE_CHECKED, { config: this.siteConfig });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.authInstructions = null;
|
||||||
|
this.canSignup = false;
|
||||||
|
this.identityProviders = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to authenticate the user.
|
||||||
|
*
|
||||||
|
* @param e Event.
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
async login(e?: Event): Promise<void> {
|
||||||
|
if (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreApp.instance.closeKeyboard();
|
||||||
|
|
||||||
|
// Get input data.
|
||||||
|
const siteUrl = this.siteUrl;
|
||||||
|
const username = this.credForm.value.username;
|
||||||
|
const password = this.credForm.value.password;
|
||||||
|
|
||||||
|
if (!this.siteChecked || this.isBrowserSSO) {
|
||||||
|
// Site wasn't checked (it failed) or a previous check determined it was SSO. Let's check again.
|
||||||
|
await this.checkSite(siteUrl);
|
||||||
|
|
||||||
|
if (!this.isBrowserSSO) {
|
||||||
|
// Site doesn't use browser SSO, throw app's login again.
|
||||||
|
return this.login();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!username) {
|
||||||
|
CoreDomUtils.instance.showErrorModal('core.login.usernamerequired', true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!password) {
|
||||||
|
CoreDomUtils.instance.showErrorModal('core.login.passwordrequired', true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CoreApp.instance.isOnline()) {
|
||||||
|
CoreDomUtils.instance.showErrorModal('core.networkerrormsg', true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modal = await CoreDomUtils.instance.showModalLoading();
|
||||||
|
|
||||||
|
// Start the authentication process.
|
||||||
|
try {
|
||||||
|
const data = await CoreSites.instance.getUserToken(siteUrl, username, password);
|
||||||
|
|
||||||
|
const id = await CoreSites.instance.newSite(data.siteUrl, data.token, data.privateToken);
|
||||||
|
|
||||||
|
// Reset fields so the data is not in the view anymore.
|
||||||
|
this.credForm.controls['username'].reset();
|
||||||
|
this.credForm.controls['password'].reset();
|
||||||
|
|
||||||
|
this.siteId = id;
|
||||||
|
|
||||||
|
await CoreLoginHelper.instance.goToSiteInitialPage(undefined, undefined, undefined, undefined, this.urlToOpen);
|
||||||
|
} catch (error) {
|
||||||
|
CoreLoginHelper.instance.treatUserTokenError(siteUrl, error, username, password);
|
||||||
|
|
||||||
|
if (error.loggedout) {
|
||||||
|
// @todo Go to sites page.
|
||||||
|
} else if (error.errorcode == 'forcepasswordchangenotice') {
|
||||||
|
// Reset password field.
|
||||||
|
this.credForm.controls.password.reset();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
modal.dismiss();
|
||||||
|
|
||||||
|
CoreDomUtils.instance.triggerFormSubmittedEvent(this.formElement, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forgotten password button clicked.
|
||||||
|
*/
|
||||||
|
forgottenPassword(): void {
|
||||||
|
CoreLoginHelper.instance.forgottenPasswordClicked(
|
||||||
|
this.navCtrl, this.siteUrl, this.credForm.value.username, this.siteConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An OAuth button was clicked.
|
||||||
|
*
|
||||||
|
* @param provider The provider that was clicked.
|
||||||
|
*/
|
||||||
|
oauthClicked(provider: CoreSiteIdentityProvider): void {
|
||||||
|
if (!CoreLoginHelper.instance.openBrowserForOAuthLogin(this.siteUrl, provider, this.siteConfig.launchurl)) {
|
||||||
|
CoreDomUtils.instance.showErrorModal('Invalid data.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signup button was clicked.
|
||||||
|
*/
|
||||||
|
signup(): void {
|
||||||
|
// @todo Go to signup.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show instructions and scan QR code.
|
||||||
|
*/
|
||||||
|
showInstructionsAndScanQR(): void {
|
||||||
|
// Show some instructions first.
|
||||||
|
CoreDomUtils.instance.showAlertWithOptions({
|
||||||
|
header: Translate.instance.instant('core.login.faqwhereisqrcode'),
|
||||||
|
message: Translate.instance.instant('core.login.faqwhereisqrcodeanswer',
|
||||||
|
{ $image: CoreLoginHelperProvider.FAQ_QRCODE_IMAGE_HTML }),
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: Translate.instance.instant('core.cancel'),
|
||||||
|
role: 'cancel',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: Translate.instance.instant('core.next'),
|
||||||
|
handler: (): void => {
|
||||||
|
this.scanQR();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scan a QR code and put its text in the URL input.
|
||||||
|
*
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
async scanQR(): Promise<void> {
|
||||||
|
// @todo Scan for a QR code.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View destroyed.
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.viewLeft = true;
|
||||||
|
CoreEvents.instance.trigger(CoreEventsProvider.LOGIN_SITE_UNCHECKED, { config: this.siteConfig }, this.siteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ import CoreConfigConstants from '@app/config.json';
|
||||||
import { Translate } from '@singletons/core.singletons';
|
import { Translate } from '@singletons/core.singletons';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreUrlUtils } from '@/app/services/utils/url';
|
import { CoreUrlUtils } from '@/app/services/utils/url';
|
||||||
|
import { NavController } from '@ionic/angular';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays a "splash screen" while the app is being initialized.
|
* Page that displays a "splash screen" while the app is being initialized.
|
||||||
|
@ -58,6 +59,7 @@ export class CoreLoginSitePage implements OnInit {
|
||||||
constructor(
|
constructor(
|
||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
protected formBuilder: FormBuilder,
|
protected formBuilder: FormBuilder,
|
||||||
|
protected navCtrl: NavController,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
let url = '';
|
let url = '';
|
||||||
|
@ -368,6 +370,9 @@ export class CoreLoginSitePage implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo Navigate to credentials.
|
// @todo Navigate to credentials.
|
||||||
|
this.navCtrl.navigateForward('/login/credentials', {
|
||||||
|
queryParams: pageParams,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Location } from '@angular/common';
|
import { Location } from '@angular/common';
|
||||||
import { Router, Params } from '@angular/router';
|
import { Params } from '@angular/router';
|
||||||
import { NavController } from '@ionic/angular';
|
import { NavController } from '@ionic/angular';
|
||||||
import { Md5 } from 'ts-md5/dist/md5';
|
import { Md5 } from 'ts-md5/dist/md5';
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ export class CoreLoginHelperProvider {
|
||||||
waitingForBrowser = false;
|
waitingForBrowser = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected router: Router,
|
|
||||||
private location: Location,
|
private location: Location,
|
||||||
) {
|
) {
|
||||||
this.logger = CoreLogger.getInstance('CoreLoginHelper');
|
this.logger = CoreLogger.getInstance('CoreLoginHelper');
|
||||||
|
@ -162,6 +161,7 @@ export class CoreLoginHelperProvider {
|
||||||
* @param siteConfig Site config.
|
* @param siteConfig Site config.
|
||||||
*/
|
*/
|
||||||
async forgottenPasswordClicked(
|
async forgottenPasswordClicked(
|
||||||
|
navCtrl: NavController,
|
||||||
siteUrl: string,
|
siteUrl: string,
|
||||||
username: string,
|
username: string,
|
||||||
siteConfig?: CoreSitePublicConfigResponse,
|
siteConfig?: CoreSitePublicConfigResponse,
|
||||||
|
@ -180,7 +180,7 @@ export class CoreLoginHelperProvider {
|
||||||
const canReset = await this.canRequestPasswordReset(siteUrl);
|
const canReset = await this.canRequestPasswordReset(siteUrl);
|
||||||
|
|
||||||
if (canReset) {
|
if (canReset) {
|
||||||
await this.router.navigate(['/login/forgottenpassword'], {
|
await navCtrl.navigateForward(['/login/forgottenpassword'], {
|
||||||
queryParams: {
|
queryParams: {
|
||||||
siteUrl,
|
siteUrl,
|
||||||
username,
|
username,
|
||||||
|
|
|
@ -113,9 +113,9 @@ export class CoreWSProvider {
|
||||||
if (this.retryCalls.length > 0) {
|
if (this.retryCalls.length > 0) {
|
||||||
this.logger.warn('Calls locked, trying later...');
|
this.logger.warn('Calls locked, trying later...');
|
||||||
|
|
||||||
return this.addToRetryQueue<T>(method, siteUrl, data, preSets);
|
return this.addToRetryQueue<T>(method, siteUrl, dataToSend, preSets);
|
||||||
} else {
|
} else {
|
||||||
return this.performPost<T>(method, siteUrl, data, preSets);
|
return this.performPost<T>(method, siteUrl, dataToSend, preSets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue