MOBILE-2253 login: Implement email signup without profile fields
parent
435815cbf2
commit
847359bb2a
|
@ -84,11 +84,11 @@ function treatMergedData(data) {
|
||||||
}
|
}
|
||||||
addProperties(merged, data[filepath], 'mma.'+pluginName+'.');
|
addProperties(merged, data[filepath], 'mma.'+pluginName+'.');
|
||||||
|
|
||||||
} else if (filepath.indexOf('core/assets/countries') === 0) {
|
} else if (filepath.indexOf('assets/countries') === 0) {
|
||||||
|
|
||||||
addProperties(merged, data[filepath], 'mm.core.country-');
|
addProperties(merged, data[filepath], 'mm.core.country-');
|
||||||
|
|
||||||
} else if (filepath.indexOf('core/assets/mimetypes') === 0) {
|
} else if (filepath.indexOf('assets/mimetypes') === 0) {
|
||||||
|
|
||||||
addProperties(merged, data[filepath], 'mm.core.mimetype-');
|
addProperties(merged, data[filepath], 'mm.core.mimetype-');
|
||||||
|
|
||||||
|
@ -181,7 +181,9 @@ var appLangFiles = ['ar.json', 'bg.json', 'ca.json', 'cs.json', 'da.json', 'de.j
|
||||||
lang: [
|
lang: [
|
||||||
'./src/lang/',
|
'./src/lang/',
|
||||||
'./src/core/**/lang/',
|
'./src/core/**/lang/',
|
||||||
'./src/addons/**/lang/'
|
'./src/addons/**/lang/',
|
||||||
|
'./src/assets/countries/',
|
||||||
|
'./src/assets/mimetypes/'
|
||||||
],
|
],
|
||||||
config: './src/config.json',
|
config: './src/config.json',
|
||||||
};
|
};
|
||||||
|
|
|
@ -112,3 +112,10 @@ ion-icon.icon-accessory {
|
||||||
.mm-bold, .mm-bold .label {
|
.mm-bold, .mm-bold .label {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item .core-input-footnote {
|
||||||
|
width: 100%;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
|
@ -22,14 +22,16 @@
|
||||||
<ion-input type="text" name="username" placeholder="{{ 'mm.login.username' | translate }}" formControlName="username" autocapitalize="none" autocorrect="off"></ion-input>
|
<ion-input type="text" name="username" placeholder="{{ 'mm.login.username' | translate }}" formControlName="username" autocapitalize="none" autocorrect="off"></ion-input>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item *ngIf="siteChecked && !isBrowserSSO">
|
<ion-item *ngIf="siteChecked && !isBrowserSSO">
|
||||||
|
<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>
|
<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-item>
|
||||||
<button ion-button block color="primary" [disabled]="siteChecked && !isBrowserSSO && !credForm.valid">{{ 'mm.login.loginbutton' | translate }}</button>
|
<button ion-button block color="primary" [disabled]="siteChecked && !isBrowserSSO && !credForm.valid">{{ 'mm.login.loginbutton' | translate }}</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<!-- Forgotten password button. -->
|
<!-- Forgotten password button. -->
|
||||||
<div padding-top>
|
<div padding-top>
|
||||||
<button ion-button block (click)="forgottenPassword()">{{ 'mm.login.forgotten' | translate }}</button>
|
<button ion-button block text-wrap (click)="forgottenPassword()">{{ 'mm.login.forgotten' | translate }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="identityProviders && identityProviders.length" padding-top>
|
<div *ngIf="identityProviders && identityProviders.length" padding-top>
|
||||||
|
@ -44,7 +46,7 @@
|
||||||
<div *ngIf="canSignup">
|
<div *ngIf="canSignup">
|
||||||
<ion-item text-wrap>
|
<ion-item text-wrap>
|
||||||
<p class="item-heading">{{ 'mm.login.firsttime' | translate }}</p>
|
<p class="item-heading">{{ 'mm.login.firsttime' | translate }}</p>
|
||||||
<p *ngIf="authInstructions"><core-format-text text="{{authInstructions}}"></core-format-text></p>
|
<p *ngIf="authInstructions"><core-format-text [text]="authInstructions"></core-format-text></p>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<button ion-button block (click)="signup()">{{ 'mm.login.startsignup' | translate }}</button>
|
<button ion-button block (click)="signup()">{{ 'mm.login.startsignup' | translate }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
<ion-header>
|
||||||
|
<ion-navbar>
|
||||||
|
<ion-title>{{ 'mm.login.newaccount' | translate }}</ion-title>
|
||||||
|
|
||||||
|
<ion-buttons end>
|
||||||
|
<button ion-button icon-only *ngIf="authInstructions" (click)="showAuthInstructions()" [attr.aria-label]="'mm.login.instructions' | translate">
|
||||||
|
<ion-icon name="help-circle"></ion-icon>
|
||||||
|
</button>
|
||||||
|
</ion-buttons>
|
||||||
|
</ion-navbar>
|
||||||
|
</ion-header>
|
||||||
|
<ion-content>
|
||||||
|
<ion-refresher [enabled]="settingsLoaded" (ionRefresh)="refreshSettings($event)">
|
||||||
|
<ion-refresher-content pullingText="{{ 'mm.core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||||
|
</ion-refresher>
|
||||||
|
|
||||||
|
<core-loading [hideUntil]="settingsLoaded">
|
||||||
|
<form *ngIf="settingsLoaded && settings" [formGroup]="signupForm" (ngSubmit)="create()" class="list list-inset">
|
||||||
|
<ion-list>
|
||||||
|
<ion-item text-wrap class="text-center">
|
||||||
|
<!-- If no sitename show big siteurl. -->
|
||||||
|
<p *ngIf="!siteName" padding class="item-heading">{{siteUrl}}</p>
|
||||||
|
<!-- If sitename, show big sitename and small siteurl. -->
|
||||||
|
<p *ngIf="siteName" padding class="item-heading">{{siteName}}</p>
|
||||||
|
<p *ngIf="siteName">{{siteUrl}}</p>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<!-- Username and password. -->
|
||||||
|
<ion-item-divider text-wrap color="light">
|
||||||
|
{{ 'mm.login.createuserandpass' | translate }}
|
||||||
|
</ion-item-divider>
|
||||||
|
<ion-item text-wrap>
|
||||||
|
<ion-label stacked core-mark-required="true">{{ 'mm.login.username' | translate }}</ion-label>
|
||||||
|
<ion-input type="text" name="username" placeholder="{{ 'mm.login.username' | translate }}" formControlName="username" autocapitalize="none" autocorrect="off"></ion-input>
|
||||||
|
<core-input-errors item-content [control]="signupForm.controls.username" [errorMessages]="usernameErrors"></core-input-errors>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item text-wrap>
|
||||||
|
<ion-label stacked core-mark-required="true">{{ 'mm.login.password' | translate }}</ion-label>
|
||||||
|
<core-show-password item-content [name]="'password'">
|
||||||
|
<ion-input type="password" name="password" placeholder="{{ 'mm.login.password' | translate }}" formControlName="password"></ion-input>
|
||||||
|
</core-show-password>
|
||||||
|
<p *ngIf="settings.passwordpolicy" item-content class="core-input-footnote">
|
||||||
|
{{settings.passwordpolicy}}
|
||||||
|
</p>
|
||||||
|
<core-input-errors item-content [control]="signupForm.controls.password" [errorMessages]="passwordErrors"></core-input-errors>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<!-- More details. -->
|
||||||
|
<ion-item-divider text-wrap color="light">
|
||||||
|
{{ 'mm.login.supplyinfo' | translate }}
|
||||||
|
</ion-item-divider>
|
||||||
|
<ion-item text-wrap>
|
||||||
|
<ion-label stacked core-mark-required="true">{{ 'mm.user.email' | translate }}</ion-label>
|
||||||
|
<ion-input type="email" name="email" placeholder="{{ 'mm.user.email' | translate }}" formControlName="email" autocapitalize="none" autocorrect="off"></ion-input>
|
||||||
|
<core-input-errors item-content [control]="signupForm.controls.email" [errorMessages]="emailErrors"></core-input-errors>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item text-wrap>
|
||||||
|
<ion-label stacked core-mark-required="true">{{ 'mm.user.emailagain' | translate }}</ion-label>
|
||||||
|
<ion-input type="email" name="email2" placeholder="{{ 'mm.user.emailagain' | translate }}" formControlName="email2" autocapitalize="none" autocorrect="off" pattern="{{signupForm.controls.email.value}}"></ion-input>
|
||||||
|
<core-input-errors item-content [control]="signupForm.controls.email2" [errorMessages]="email2Errors"></core-input-errors>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item *ngFor="let nameField of settings.namefields" text-wrap>
|
||||||
|
<ion-label stacked core-mark-required="true">{{ 'mm.user.' + nameField | translate }}</ion-label>
|
||||||
|
<ion-input type="text" name="nameField" placeholder="{{ 'mm.user.' + nameField | translate }}" formControlName="{{nameField}}" autocorrect="off"></ion-input>
|
||||||
|
<core-input-errors item-content [control]="signupForm.controls[nameField]" [errorMessages]="namefieldsErrors[nameField]"></core-input-errors>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item text-wrap>
|
||||||
|
<ion-label stacked>{{ 'mm.user.city' | translate }}</ion-label>
|
||||||
|
<ion-input type="text" name="city" placeholder="{{ 'mm.user.city' | translate }}" formControlName="city" autocorrect="off"></ion-input>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item text-wrap>
|
||||||
|
<ion-label stacked id="core-login-signup-country">{{ 'mm.user.country' | translate }}</ion-label>
|
||||||
|
<ion-select name="country" formControlName="country" aria-labelledby="core-login-signup-country">
|
||||||
|
<ion-option value="">{{ 'mm.login.selectacountry' | translate }}</ion-option>
|
||||||
|
<ion-option *ngFor="let key of countriesKeys" [value]="key">{{countries[key]}}</ion-option>
|
||||||
|
</ion-select>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<!-- Other categories. @todo: Implement once user profile fields are implemented. -->
|
||||||
|
<!-- <div *ngFor="let category in categories">
|
||||||
|
<ion-item-divider text-wrap color="light">{{ category.name }}</div>
|
||||||
|
<mm-user-profile-field *ngFor="let field in category.fields" field="field" edit="true" signup="true" register-auth="email" model="data" scroll-handle="mmLoginEmailSignupScroll"></mm-user-profile-field>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<!-- ReCAPTCHA -->
|
||||||
|
<div *ngIf="settings.recaptchachallengehash && settings.recaptchachallengeimage">
|
||||||
|
<ion-item-divider text-wrap color="light">{{ 'mm.login.security_question' | translate }}</ion-item-divider>
|
||||||
|
<ion-item>
|
||||||
|
<img [src]="settings.recaptchachallengeimage" alt="{{ 'mm.login.recaptchachallengeimage' | translate }}">
|
||||||
|
</ion-item>
|
||||||
|
<ion-item text-wrap>
|
||||||
|
<ion-label stacked core-mark-required="true">{{ 'mm.login.enterthewordsabove' | translate }}</ion-label>
|
||||||
|
<ion-input type="text" name="recaptcharesponse" placeholder="{{ 'mm.login.enterthewordsabove' | translate }}" formControlName="recaptcharesponse" autocapitalize="none" autocorrect="off"></ion-input>
|
||||||
|
<core-input-errors item-content [control]="signupForm.controls.recaptcharesponse"></core-input-errors>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item padding>
|
||||||
|
<!-- Use anchor instead of button to prevent marking form as submitted. -->
|
||||||
|
<a ion-button block (click)="requestCaptcha()">{{ 'mm.login.getanothercaptcha' | translate }}</a>
|
||||||
|
</ion-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Site policy (if any). -->
|
||||||
|
<div *ngIf="settings.sitepolicy">
|
||||||
|
<ion-item-divider text-wrap color="light">{{ 'mm.login.policyagreement' | translate }}</ion-item-divider>
|
||||||
|
<ion-item text-wrap>
|
||||||
|
<p><a [href]="settings.sitepolicy" core-link capture="false">{{ 'mm.login.policyagreementclick' | translate }}</a></p>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item text-wrap>
|
||||||
|
<ion-label core-mark-required="true">{{ 'mm.login.policyaccept' | translate }}</ion-label>
|
||||||
|
<ion-checkbox item-right name="policyagreed" formControlName="policyagreed"></ion-checkbox>
|
||||||
|
<core-input-errors [control]="signupForm.controls.policyagreed" [errorMessages]="policyErrors"></core-input-errors>
|
||||||
|
</ion-item>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Submit button. -->
|
||||||
|
<ion-item padding>
|
||||||
|
<button ion-button block color="primary">{{ 'mm.login.createaccount' | translate }}</button>
|
||||||
|
</ion-item>
|
||||||
|
</ion-list>
|
||||||
|
</form>
|
||||||
|
</core-loading>
|
||||||
|
</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 { CoreLoginEmailSignupPage } from './email-signup';
|
||||||
|
import { CoreLoginModule } from '../../login.module';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { CoreComponentsModule } from '../../../../components/components.module';
|
||||||
|
import { CoreDirectivesModule } from '../../../../directives/directives.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
CoreLoginEmailSignupPage
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CoreComponentsModule,
|
||||||
|
CoreDirectivesModule,
|
||||||
|
CoreLoginModule,
|
||||||
|
IonicPageModule.forChild(CoreLoginEmailSignupPage),
|
||||||
|
TranslateModule.forChild()
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class CoreLoginCredentialsPageModule {}
|
|
@ -0,0 +1,2 @@
|
||||||
|
page-core-login-email-signup {
|
||||||
|
}
|
|
@ -0,0 +1,268 @@
|
||||||
|
// (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, ViewChild } from '@angular/core';
|
||||||
|
import { IonicPage, NavController, NavParams, Content } from 'ionic-angular';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { CoreSitesProvider } from '../../../../providers/sites';
|
||||||
|
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
|
||||||
|
import { CoreTextUtilsProvider } from '../../../../providers/utils/text';
|
||||||
|
import { CoreUtilsProvider } from '../../../../providers/utils/utils';
|
||||||
|
import { CoreWSProvider } from '../../../../providers/ws';
|
||||||
|
import { CoreLoginHelperProvider } from '../../providers/helper';
|
||||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page to signup using email.
|
||||||
|
*/
|
||||||
|
@IonicPage()
|
||||||
|
@Component({
|
||||||
|
selector: 'page-core-login-email-signup',
|
||||||
|
templateUrl: 'email-signup.html',
|
||||||
|
})
|
||||||
|
export class CoreLoginEmailSignupPage {
|
||||||
|
@ViewChild(Content) content: Content;
|
||||||
|
signupForm: FormGroup;
|
||||||
|
siteUrl: string;
|
||||||
|
siteConfig: any;
|
||||||
|
siteName: string;
|
||||||
|
authInstructions: string;
|
||||||
|
settings: any;
|
||||||
|
countries: any;
|
||||||
|
countriesKeys: any[];
|
||||||
|
categories: any[];
|
||||||
|
settingsLoaded: boolean = false;
|
||||||
|
|
||||||
|
// Validation errors.
|
||||||
|
usernameErrors: any;
|
||||||
|
passwordErrors: any;
|
||||||
|
emailErrors: any;
|
||||||
|
email2Errors: any;
|
||||||
|
policyErrors: any;
|
||||||
|
namefieldsErrors: any;
|
||||||
|
|
||||||
|
constructor(private navCtrl: NavController, navParams: NavParams, private fb: FormBuilder, private wsProvider: CoreWSProvider,
|
||||||
|
private sitesProvider: CoreSitesProvider, private loginHelper: CoreLoginHelperProvider,
|
||||||
|
private domUtils: CoreDomUtilsProvider, private translate: TranslateService, private utils: CoreUtilsProvider,
|
||||||
|
private textUtils: CoreTextUtilsProvider) {
|
||||||
|
|
||||||
|
this.siteUrl = navParams.get('siteUrl');
|
||||||
|
|
||||||
|
// Create the signupForm with the basic controls. More controls will be added later.
|
||||||
|
this.signupForm = this.fb.group({
|
||||||
|
'username': ['', Validators.required],
|
||||||
|
'password': ['', Validators.required],
|
||||||
|
'email': ['', Validators.compose([Validators.required, Validators.email])],
|
||||||
|
'email2': ['', Validators.compose([Validators.required, Validators.email])]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setup validation errors.
|
||||||
|
this.usernameErrors = this.loginHelper.getErrorMessages('mm.login.usernamerequired');
|
||||||
|
this.passwordErrors = this.loginHelper.getErrorMessages('mm.login.passwordrequired');
|
||||||
|
this.emailErrors = this.loginHelper.getErrorMessages('mm.login.missingemail');
|
||||||
|
this.email2Errors = this.loginHelper.getErrorMessages('mm.login.missingemail', null, 'mm.login.emailnotmatch');
|
||||||
|
this.policyErrors = this.loginHelper.getErrorMessages('mm.login.policyagree');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View loaded.
|
||||||
|
*/
|
||||||
|
ionViewDidLoad() {
|
||||||
|
// Fetch the data.
|
||||||
|
this.fetchData().finally(() => {
|
||||||
|
this.settingsLoaded = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Complete the FormGroup using the settings received from server.
|
||||||
|
*/
|
||||||
|
protected completeFormGroup() {
|
||||||
|
this.signupForm.addControl('city', this.fb.control(this.settings.defaultcity || ''));
|
||||||
|
this.signupForm.addControl('country', this.fb.control(this.settings.country || ''));
|
||||||
|
|
||||||
|
// Add the name fields.
|
||||||
|
for (let i in this.settings.namefields) {
|
||||||
|
this.signupForm.addControl(this.settings.namefields[i], this.fb.control('', Validators.required));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.settings.recaptchachallengehash && this.settings.recaptchachallengeimage) {
|
||||||
|
this.signupForm.addControl('recaptcharesponse', this.fb.control('', Validators.required));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.settings.sitepolicy) {
|
||||||
|
this.signupForm.addControl('policyagreed', this.fb.control(false, Validators.requiredTrue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the required data from the server-
|
||||||
|
*/
|
||||||
|
protected fetchData() : Promise<any> {
|
||||||
|
// Get site config.
|
||||||
|
return this.sitesProvider.getSitePublicConfig(this.siteUrl).then((config) => {
|
||||||
|
this.siteConfig = config;
|
||||||
|
|
||||||
|
if (this.treatSiteConfig(config)) {
|
||||||
|
return this.getSignupSettings();
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
this.completeFormGroup();
|
||||||
|
}).catch((err) => {
|
||||||
|
this.domUtils.showErrorModal(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get signup settings from server.
|
||||||
|
*/
|
||||||
|
protected getSignupSettings() : Promise<any> {
|
||||||
|
return this.wsProvider.callAjax('auth_email_get_signup_settings', {}, {siteUrl: this.siteUrl}).then((settings) => {
|
||||||
|
this.settings = settings;
|
||||||
|
this.categories = this.loginHelper.formatProfileFieldsForSignup(settings.profilefields);
|
||||||
|
|
||||||
|
if (this.signupForm && this.signupForm.controls['recaptcharesponse']) {
|
||||||
|
this.signupForm.controls['recaptcharesponse'].reset(); // Reset captcha.
|
||||||
|
}
|
||||||
|
|
||||||
|
this.namefieldsErrors = {};
|
||||||
|
if (settings.namefields) {
|
||||||
|
settings.namefields.forEach((field) => {
|
||||||
|
this.namefieldsErrors[field] = this.loginHelper.getErrorMessages('mm.login.missing' + field);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.utils.getCountryList().then((countries) => {
|
||||||
|
this.countries = countries;
|
||||||
|
this.countriesKeys = Object.keys(countries);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Treat the site config, checking if it's valid and extracting the data we're interested in.
|
||||||
|
*
|
||||||
|
* @param {any} siteConfig Site config to treat.
|
||||||
|
*/
|
||||||
|
protected treatSiteConfig(siteConfig) {
|
||||||
|
if (siteConfig && siteConfig.registerauth == 'email' && !this.loginHelper.isEmailSignupDisabled(siteConfig)) {
|
||||||
|
this.siteName = siteConfig.sitename;
|
||||||
|
this.authInstructions = siteConfig.authinstructions;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
this.domUtils.showErrorModal(
|
||||||
|
this.translate.instant('mm.login.signupplugindisabled', {$a: this.translate.instant('mm.login.auth_email')}));
|
||||||
|
this.navCtrl.pop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pull to refresh.
|
||||||
|
*
|
||||||
|
* @param {any} refresher Refresher.
|
||||||
|
*/
|
||||||
|
refreshSettings(refresher: any) : void {
|
||||||
|
this.fetchData().finally(() => {
|
||||||
|
refresher.complete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request another captcha.
|
||||||
|
*
|
||||||
|
* @param {boolean} ignoreError Whether to ignore errors.
|
||||||
|
*/
|
||||||
|
requestCaptcha(ignoreError?: boolean) : void {
|
||||||
|
let modal = this.domUtils.showModalLoading();
|
||||||
|
this.getSignupSettings().catch((err) => {
|
||||||
|
if (!ignoreError && err) {
|
||||||
|
this.domUtils.showErrorModal(err);
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
modal.dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create account.
|
||||||
|
*/
|
||||||
|
create() : void {
|
||||||
|
if (!this.signupForm.valid) {
|
||||||
|
// Form not valid. Scroll to the first element with errors.
|
||||||
|
if (!this.domUtils.scrollToInputError(this.content, document.body)) {
|
||||||
|
// Input not found, show an error modal.
|
||||||
|
this.domUtils.showErrorModal('mm.core.errorinvalidform', true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let params: any = {
|
||||||
|
username: this.signupForm.value.username.trim().toLowerCase(),
|
||||||
|
password: this.signupForm.value.password,
|
||||||
|
firstname: this.textUtils.cleanTags(this.signupForm.value.firstname),
|
||||||
|
lastname: this.textUtils.cleanTags(this.signupForm.value.lastname),
|
||||||
|
email: this.signupForm.value.email.trim(),
|
||||||
|
city: this.textUtils.cleanTags(this.signupForm.value.city),
|
||||||
|
country: this.signupForm.value.country
|
||||||
|
},
|
||||||
|
modal = this.domUtils.showModalLoading('mm.core.sending', true);
|
||||||
|
|
||||||
|
if (this.siteConfig.launchurl) {
|
||||||
|
let service = this.sitesProvider.determineService(this.siteUrl);
|
||||||
|
params.redirect = this.loginHelper.prepareForSSOLogin(this.siteUrl, service, this.siteConfig.launchurl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.settings.recaptchachallengehash && this.settings.recaptchachallengeimage) {
|
||||||
|
params.recaptchachallengehash = this.settings.recaptchachallengehash;
|
||||||
|
params.recaptcharesponse = this.signupForm.value.recaptcharesponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the data for the custom profile fields.
|
||||||
|
// @todo: Implement it once profile fields are implemented.
|
||||||
|
// $mmUserProfileFieldsDelegate.getDataForFields(fields, true, 'email', $scope.data).then(function(fieldsData) {
|
||||||
|
// params.customprofilefields = fieldsData;
|
||||||
|
|
||||||
|
this.wsProvider.callAjax('auth_email_signup_user', params, {siteUrl: this.siteUrl}).then((result) => {
|
||||||
|
if (result.success) {
|
||||||
|
// Show alert and ho back.
|
||||||
|
let message = this.translate.instant('mm.login.emailconfirmsent', {$a: params.email});
|
||||||
|
this.domUtils.showAlert('mm.core.success', message);
|
||||||
|
this.navCtrl.pop();
|
||||||
|
} else {
|
||||||
|
if (result.warnings && result.warnings.length) {
|
||||||
|
this.domUtils.showErrorModal(result.warnings[0].message);
|
||||||
|
} else {
|
||||||
|
this.domUtils.showErrorModal('mm.login.usernotaddederror', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error sending, request another capctha since the current one is probably invalid now.
|
||||||
|
this.requestCaptcha(true);
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
this.domUtils.showErrorModalDefault(error && error.error, 'mm.login.usernotaddederror', true);
|
||||||
|
|
||||||
|
// Error sending, request another capctha since the current one is probably invalid now.
|
||||||
|
this.requestCaptcha(true);
|
||||||
|
}).finally(() => {
|
||||||
|
modal.dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show authentication instructions.
|
||||||
|
*/
|
||||||
|
protected showAuthInstructions() {
|
||||||
|
this.textUtils.expandText(this.translate.instant('mm.login.instructions'), this.authInstructions, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,7 +21,7 @@
|
||||||
{{ 'mm.login.contactyouradministratorissue' | translate:{$a: ''} }}
|
{{ 'mm.login.contactyouradministratorissue' | translate:{$a: ''} }}
|
||||||
</p>
|
</p>
|
||||||
<p *ngIf="issue">
|
<p *ngIf="issue">
|
||||||
<core-format-text>{{issue}}</core-format-text>
|
<core-format-text [text]="issue"></core-format-text>
|
||||||
</p>
|
</p>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,10 @@ export class CoreLoginHelperProvider {
|
||||||
formatProfileFieldsForSignup(profileFields: any[]) : any {
|
formatProfileFieldsForSignup(profileFields: any[]) : any {
|
||||||
let categories = {};
|
let categories = {};
|
||||||
|
|
||||||
|
if (!profileFields) {
|
||||||
|
return categories;
|
||||||
|
}
|
||||||
|
|
||||||
profileFields.forEach((field) => {
|
profileFields.forEach((field) => {
|
||||||
if (!field.signup) {
|
if (!field.signup) {
|
||||||
// Not a signup field, ignore it.
|
// Not a signup field, ignore it.
|
||||||
|
@ -161,7 +165,7 @@ export class CoreLoginHelperProvider {
|
||||||
var errors: any = {};
|
var errors: any = {};
|
||||||
|
|
||||||
if (requiredMsg) {
|
if (requiredMsg) {
|
||||||
errors.required = this.translate.instant(requiredMsg);
|
errors.required = errors.requiredTrue = this.translate.instant(requiredMsg);
|
||||||
}
|
}
|
||||||
if (emailMsg) {
|
if (emailMsg) {
|
||||||
errors.email = this.translate.instant(emailMsg);
|
errors.email = this.translate.instant(emailMsg);
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { LoadingController, Loading, ToastController, Toast, AlertController, Alert, Platform } from 'ionic-angular';
|
import { LoadingController, Loading, ToastController, Toast, AlertController, Alert, Platform, Content } from 'ionic-angular';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { CoreTextUtilsProvider } from './text';
|
import { CoreTextUtilsProvider } from './text';
|
||||||
import { CoreAppProvider } from '../app';
|
import { CoreAppProvider } from '../app';
|
||||||
|
@ -365,7 +365,7 @@ export class CoreDomUtilsProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, check again.
|
// Finally, check again.
|
||||||
if (element.className.indexOf(positionParentClass) != -1) {
|
if (element && element.className.indexOf(positionParentClass) != -1) {
|
||||||
element = null;
|
element = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -564,13 +564,14 @@ export class CoreDomUtilsProvider {
|
||||||
/**
|
/**
|
||||||
* Scroll to a certain element inside another element.
|
* Scroll to a certain element inside another element.
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} scrollEl The element that must be scrolled.
|
* @param {Content|HTMLElement} scrollEl The content that must be scrolled.
|
||||||
* @param {HTMLElement} container Element to search in.
|
* @param {HTMLElement} container Element to search in.
|
||||||
* @param {string} [selector] Selector to find the element to scroll to. If not defined, scroll to the container.
|
* @param {string} [selector] Selector to find the element to scroll to. If not defined, scroll to the container.
|
||||||
* @param {string} [scrollParentClass] Parent class where to stop calculating the position. Default scroll-content.
|
* @param {string} [scrollParentClass] Parent class where to stop calculating the position. Default scroll-content.
|
||||||
* @return {boolean} True if the element is found, false otherwise.
|
* @return {boolean} True if the element is found, false otherwise.
|
||||||
*/
|
*/
|
||||||
scrollToElement(scrollEl: HTMLElement, container: HTMLElement, selector?: string, scrollParentClass?: string) : boolean {
|
scrollToElement(scrollEl: Content|HTMLElement, container: HTMLElement, selector?: string, scrollParentClass?: string)
|
||||||
|
: boolean {
|
||||||
let position = this.getElementXY(container, selector, scrollParentClass);
|
let position = this.getElementXY(container, selector, scrollParentClass);
|
||||||
if (!position) {
|
if (!position) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -583,23 +584,17 @@ export class CoreDomUtilsProvider {
|
||||||
/**
|
/**
|
||||||
* Search for an input with error (mm-input-error directive) and scrolls to it if found.
|
* Search for an input with error (mm-input-error directive) and scrolls to it if found.
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} scrollEl The element that must be scrolled.
|
* @param {Content|HTMLElement} scrollEl The element that must be scrolled.
|
||||||
* @param {HTMLElement} container Element to search in.
|
* @param {HTMLElement} container Element to search in.
|
||||||
* @param [scrollParentClass] Parent class where to stop calculating the position. Default scroll-content.
|
* @param [scrollParentClass] Parent class where to stop calculating the position. Default scroll-content.
|
||||||
* @return {boolean} True if the element is found, false otherwise.
|
* @return {boolean} True if the element is found, false otherwise.
|
||||||
*/
|
*/
|
||||||
scrollToInputError(scrollEl: HTMLElement, container: HTMLElement, scrollParentClass?: string) : boolean {
|
scrollToInputError(scrollEl: Content|HTMLElement, container: HTMLElement, scrollParentClass?: string) : boolean {
|
||||||
// @todo
|
if (!scrollEl) {
|
||||||
return true;
|
return false;
|
||||||
// Wait an instant to make sure errors are shown and scroll to the element.
|
}
|
||||||
// return $timeout(function() {
|
|
||||||
// if (!scrollDelegate) {
|
|
||||||
// scrollDelegate = $ionicScrollDelegate;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// scrollDelegate.resize();
|
return this.scrollToElement(scrollEl, container, '.core-input-error', scrollParentClass);
|
||||||
// return self.scrollToElement(container, '.mm-input-has-errors', scrollDelegate, scrollParentClass);
|
|
||||||
// }, 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -553,8 +553,8 @@ export class CoreUtilsProvider {
|
||||||
|
|
||||||
for (let name in table) {
|
for (let name in table) {
|
||||||
if (name.indexOf('mm.core.country-') === 0) {
|
if (name.indexOf('mm.core.country-') === 0) {
|
||||||
name = name.replace('mm.core.country-', '');
|
let code = name.replace('mm.core.country-', '');
|
||||||
countries[name] = table[name];
|
countries[code] = table[name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue