MOBILE-2253 login: Implement reconnect page
parent
acdf6b3043
commit
e5978b7eeb
|
@ -124,3 +124,37 @@ ion-icon.icon-accessory {
|
|||
// Set bgcolor in content instead of overriding $background-color because that variable is applied to a lot of places.
|
||||
background-color: $gray-light;
|
||||
}
|
||||
|
||||
// Large centered avatar.
|
||||
.item-avatar-center {
|
||||
text-align: center;
|
||||
padding-left: 16px;
|
||||
|
||||
&.item-complex .item-content {
|
||||
text-align: center;
|
||||
padding-left: 49px;
|
||||
}
|
||||
|
||||
> img:first-child,
|
||||
ion-avatar img {
|
||||
display: block;
|
||||
margin: auto;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
max-width: 90px;
|
||||
max-height: 90px;
|
||||
margin-bottom: 10px;
|
||||
border-radius : 50%;
|
||||
padding: 4px;
|
||||
border: 1px solid #ddd;
|
||||
|
||||
&.avatar-full {
|
||||
border-radius: 2%;
|
||||
border: 0;
|
||||
max-width: 100%;
|
||||
max-height: 160px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<ion-header>
|
||||
<ion-navbar>
|
||||
<ion-title>{{ 'mm.login.reconnect' | translate }}</ion-title>
|
||||
</ion-navbar>
|
||||
</ion-header>
|
||||
<ion-content padding class="mm-center-view">
|
||||
<ion-list no-lines class="box">
|
||||
<ion-item *ngIf="site" text-wrap class="item-avatar-center" [ngClass]="{'item-avatar-center': site.avatar, 'text-center': !site.avatar}">
|
||||
<ion-avatar *ngIf="site.avatar">
|
||||
<!-- Show user avatar. -->
|
||||
<img [src]="site.avatar" class="avatar" core-external-content [siteId]="site.id" alt="{{ 'mm.core.pictureof' | translate:{$a: site.fullname} }}" role="presentation">
|
||||
</ion-avatar>
|
||||
|
||||
<!-- Show site logo or a default image. -->
|
||||
<img *ngIf="!site.avatar && logoUrl" [src]="logoUrl" core-external-content [siteId]="site.id" role="presentation">
|
||||
<img *ngIf="!site.avatar && !logoUrl" src="assets/img/logo.png" class="moodle-logo" role="presentation">
|
||||
|
||||
<!-- If no sitename show big siteurl. -->
|
||||
<p *ngIf="!siteName" class="item-heading mm-siteurl">{{siteUrl}}</p>
|
||||
<!-- If sitename, show big sitename and small siteurl. -->
|
||||
<p *ngIf="siteName" class="item-heading mm-sitename">{{siteName}}</p>
|
||||
<p *ngIf="siteName" class="mm-siteurl">{{siteUrl}}</p>
|
||||
|
||||
<p *ngIf="!isLoggedOut">
|
||||
<ion-icon padding name="alert"></ion-icon> {{ 'mm.login.reconnectdescription' | translate }}
|
||||
</p>
|
||||
</ion-item>
|
||||
<ion-item padding text-wrap class="mm-username">
|
||||
<p class="item-heading">{{ 'mm.login.username' | translate }}</p>
|
||||
<p>{{username}}</p>
|
||||
</ion-item>
|
||||
<form [formGroup]="credForm" (ngSubmit)="login()">
|
||||
<ion-item>
|
||||
<core-show-password item-content [name]="'password'">
|
||||
<ion-input class="mm-ioninput-password" name="password" type="password" placeholder="{{ 'mm.login.password' | translate }}" formControlName="password" mm-show-password></ion-input>
|
||||
</core-show-password>
|
||||
</ion-item>
|
||||
<ion-buttons class="button-bar">
|
||||
<a ion-button (click)="cancel()">{{ 'mm.login.cancel' | translate }}</a>
|
||||
<button ion-button color="primary" [disabled]="!credForm.valid">{{ 'mm.login.loginbutton' | translate }}</button>
|
||||
</ion-buttons>
|
||||
</form>
|
||||
|
||||
<!-- Identity providers. -->
|
||||
<div *ngIf="identityProviders && identityProviders.length" padding-top>
|
||||
<p>{{ 'mm.login.potentialidps' | translate }}</p>
|
||||
<ion-item *ngFor="let provider of identityProviders" text-wrap class="mm-oauth-icon" (click)="oauthClicked(provider)" title="{{provider.name}}">
|
||||
<img [src]="provider.iconurl" alt="{{provider.name}}">
|
||||
<span>{{provider.name}}</span>
|
||||
<ion-icon class="icon-accessory" name="arrow-forward" md="ios-arrow-forward" item-end></ion-icon>
|
||||
</ion-item>
|
||||
</div>
|
||||
</ion-list>
|
||||
</ion-content>
|
|
@ -0,0 +1,35 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// 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 { IonicPageModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreLoginReconnectPage } from './reconnect';
|
||||
import { CoreLoginModule } from '../../login.module';
|
||||
import { CoreComponentsModule } from '../../../../components/components.module';
|
||||
import { CoreDirectivesModule } from '../../../../directives/directives.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
CoreLoginReconnectPage
|
||||
],
|
||||
imports: [
|
||||
CoreComponentsModule,
|
||||
CoreDirectivesModule,
|
||||
CoreLoginModule,
|
||||
IonicPageModule.forChild(CoreLoginReconnectPage),
|
||||
TranslateModule.forChild()
|
||||
]
|
||||
})
|
||||
export class CoreLoginReconnectPageModule {}
|
|
@ -0,0 +1,47 @@
|
|||
page-core-login-reconnect {
|
||||
.content {
|
||||
.mm-ioninput-password {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
background: -webkit-radial-gradient(white, $gray-light);
|
||||
background: radial-gradient(white, $gray-light);
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
img.moodle-logo {
|
||||
width: 90%;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.box {
|
||||
padding: 16px;
|
||||
background: $white;
|
||||
border: 1px solid $gray;
|
||||
}
|
||||
|
||||
.mm-sitename, .mm-siteurl {
|
||||
@if $mm-fixed-url { display: none; }
|
||||
}
|
||||
|
||||
.list .item-input, .list .mm-username {
|
||||
border: 1px solid $list-border-color;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.label {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.list .mm-username {
|
||||
&.item-md {
|
||||
@include padding-horizontal($item-md-padding-left * 1.5, $content-padding);
|
||||
}
|
||||
&.item-ios {
|
||||
@include padding-horizontal($item-ios-padding-left * 1.5, $content-padding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// 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 } from '@angular/core';
|
||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
|
||||
import { CoreAppProvider } from '../../../../providers/app';
|
||||
import { CoreSitesProvider } from '../../../../providers/sites';
|
||||
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
|
||||
import { CoreLoginHelperProvider } from '../../providers/helper';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
/**
|
||||
* Page to enter the user password to reconnect to a site.
|
||||
*/
|
||||
@IonicPage()
|
||||
@Component({
|
||||
selector: 'page-core-login-reconnect',
|
||||
templateUrl: 'reconnect.html',
|
||||
})
|
||||
export class CoreLoginReconnectPage {
|
||||
credForm: FormGroup;
|
||||
siteUrl: string;
|
||||
username: string;
|
||||
siteName: string;
|
||||
logoUrl: string;
|
||||
identityProviders: any[];
|
||||
site: any;
|
||||
|
||||
protected infoSiteUrl: string;
|
||||
protected pageName: string;
|
||||
protected pageParams: any;
|
||||
protected siteConfig: any;
|
||||
protected isLoggedOut: boolean;
|
||||
protected siteId: string;
|
||||
|
||||
constructor(private navCtrl: NavController, navParams: NavParams, fb: FormBuilder, private appProvider: CoreAppProvider,
|
||||
private sitesProvider: CoreSitesProvider, private loginHelper: CoreLoginHelperProvider,
|
||||
private domUtils: CoreDomUtilsProvider) {
|
||||
|
||||
let currentSite = this.sitesProvider.getCurrentSite();
|
||||
|
||||
this.infoSiteUrl = navParams.get('infoSiteUrl');
|
||||
this.pageName = navParams.get('pageName');
|
||||
this.pageParams = navParams.get('pageParams');
|
||||
this.siteConfig = navParams.get('siteConfig');
|
||||
this.siteUrl = navParams.get('siteUrl');
|
||||
this.siteId = navParams.get('siteId');
|
||||
|
||||
this.isLoggedOut = currentSite && currentSite.isLoggedOut();
|
||||
this.credForm = fb.group({
|
||||
'password': ['', Validators.required]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* View loaded.
|
||||
*/
|
||||
ionViewDidLoad() {
|
||||
if (this.siteConfig) {
|
||||
this.identityProviders = this.loginHelper.getValidIdentityProviders(this.siteConfig);
|
||||
}
|
||||
|
||||
this.sitesProvider.getSite(this.siteId).then((site) => {
|
||||
this.site = {
|
||||
id: site.id,
|
||||
fullname: site.infos.fullname,
|
||||
avatar: site.infos.userpictureurl
|
||||
};
|
||||
|
||||
this.username = site.infos.username;
|
||||
this.siteUrl = site.infos.siteurl;
|
||||
this.siteName = site.infos.sitename;
|
||||
|
||||
// Check logoURL if user avatar is not set.
|
||||
if (this.site.avatar.startsWith(site.infos.siteurl + '/theme/image.php')) {
|
||||
this.site.avatar = false;
|
||||
return site.getPublicConfig().then((config) => {
|
||||
this.logoUrl = config.logourl || config.compactlogourl;
|
||||
});
|
||||
}
|
||||
}).catch(() => {
|
||||
// Shouldn't happen. Just leave the view.
|
||||
this.cancel();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel reconnect.
|
||||
*/
|
||||
cancel() {
|
||||
this.sitesProvider.logout().finally(() => {
|
||||
this.navCtrl.setRoot('CoreLoginSitesPage');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to authenticate the user.
|
||||
*/
|
||||
login() : void {
|
||||
this.appProvider.closeKeyboard();
|
||||
|
||||
// Get input data.
|
||||
let siteUrl = this.siteUrl,
|
||||
username = this.username,
|
||||
password = this.credForm.value.password;
|
||||
|
||||
if (!password) {
|
||||
this.domUtils.showErrorModal('mm.login.passwordrequired', true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.appProvider.isOnline()) {
|
||||
this.domUtils.showErrorModal('mm.core.networkerrormsg', true);
|
||||
return;
|
||||
}
|
||||
|
||||
let modal = this.domUtils.showModalLoading();
|
||||
|
||||
// Start the authentication process.
|
||||
this.sitesProvider.getUserToken(siteUrl, username, password).then((data) => {
|
||||
return this.sitesProvider.updateSiteToken(this.infoSiteUrl, username, data.token, data.privateToken).then(() => {
|
||||
// Update site info too because functions might have changed (e.g. unisntall local_mobile).
|
||||
return this.sitesProvider.updateSiteInfoByUrl(this.infoSiteUrl, username).finally(() => {
|
||||
// Reset fields so the data is not in the view anymore.
|
||||
this.credForm.controls['password'].reset();
|
||||
|
||||
if (this.pageName) {
|
||||
// Page defined, go to that page instead of site initial page.
|
||||
return this.navCtrl.setRoot(this.pageName, this.pageParams);
|
||||
} else {
|
||||
return this.loginHelper.goToSiteInitialPage(this.navCtrl, true);
|
||||
}
|
||||
}).catch((error) => {
|
||||
// Site deleted? Go back to login page.
|
||||
this.domUtils.showErrorModal('mm.login.errorupdatesite', true);
|
||||
this.cancel();
|
||||
});
|
||||
});
|
||||
}).catch((error) => {
|
||||
this.loginHelper.treatUserTokenError(siteUrl, error);
|
||||
}).finally(() => {
|
||||
modal.dismiss();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* An OAuth button was clicked.
|
||||
*
|
||||
* @param {any} provider The provider that was clicked.
|
||||
*/
|
||||
oauthClicked(provider) : void {
|
||||
if (!this.loginHelper.openBrowserForOAuthLogin(this.siteUrl, provider, this.siteConfig.launchurl)) {
|
||||
this.domUtils.showErrorModal('Invalid data.');
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue