MOBILE-2253 login: Implement reconnect page

main
Dani Palou 2017-11-30 12:02:49 +01:00
parent acdf6b3043
commit e5978b7eeb
5 changed files with 338 additions and 0 deletions

View File

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

View File

@ -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>

View File

@ -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 {}

View File

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

View File

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