+
+
diff --git a/src/core/login/pages/site-error/site-error.module.ts b/src/core/login/pages/site-error/site-error.module.ts
new file mode 100644
index 000000000..30b2036d5
--- /dev/null
+++ b/src/core/login/pages/site-error/site-error.module.ts
@@ -0,0 +1,31 @@
+// (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 { CoreLoginSiteErrorPage } from './site-error';
+import { TranslateModule } from '@ngx-translate/core';
+import { CoreDirectivesModule } from '../../../../directives/directives.module';
+
+@NgModule({
+ declarations: [
+ CoreLoginSiteErrorPage
+ ],
+ imports: [
+ CoreDirectivesModule,
+ IonicPageModule.forChild(CoreLoginSiteErrorPage),
+ TranslateModule.forChild()
+ ]
+})
+export class CoreLoginSiteErrorPageModule {}
diff --git a/src/core/login/pages/site-error/site-error.ts b/src/core/login/pages/site-error/site-error.ts
new file mode 100644
index 000000000..6f248056e
--- /dev/null
+++ b/src/core/login/pages/site-error/site-error.ts
@@ -0,0 +1,41 @@
+// (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, ViewController, NavParams } from 'ionic-angular';
+
+/**
+ * Component that displays an error when trying to connect to a site.
+ */
+@IonicPage()
+@Component({
+ selector: 'page-core-login-site-error',
+ templateUrl: 'site-error.html',
+})
+export class CoreLoginSiteErrorPage {
+ siteUrl: string;
+ issue: string;
+
+ constructor(private viewCtrl: ViewController, params: NavParams) {
+ this.siteUrl = params.get('siteUrl');
+ this.issue = params.get('issue');
+ }
+
+ /**
+ * Close modal.
+ */
+ closeModal() : void {
+ this.viewCtrl.dismiss();
+ }
+}
\ No newline at end of file
diff --git a/src/core/login/pages/site-help/site-help.html b/src/core/login/pages/site-help/site-help.html
new file mode 100644
index 000000000..639ad7440
--- /dev/null
+++ b/src/core/login/pages/site-help/site-help.html
@@ -0,0 +1,14 @@
+
+
+ {{ 'mm.login.help' | translate }}
+
+
+
+
+
+
+
+
+
diff --git a/src/core/login/pages/site-help/site-help.module.ts b/src/core/login/pages/site-help/site-help.module.ts
new file mode 100644
index 000000000..942199b3d
--- /dev/null
+++ b/src/core/login/pages/site-help/site-help.module.ts
@@ -0,0 +1,31 @@
+// (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 { CoreLoginSiteHelpPage } from './site-help';
+import { TranslateModule } from '@ngx-translate/core';
+import { CoreDirectivesModule } from '../../../../directives/directives.module';
+
+@NgModule({
+ declarations: [
+ CoreLoginSiteHelpPage
+ ],
+ imports: [
+ CoreDirectivesModule,
+ IonicPageModule.forChild(CoreLoginSiteHelpPage),
+ TranslateModule.forChild(),
+ ]
+})
+export class CoreLoginSiteHelpPageModule {}
diff --git a/src/core/login/pages/site-help/site-help.ts b/src/core/login/pages/site-help/site-help.ts
new file mode 100644
index 000000000..a003b28e7
--- /dev/null
+++ b/src/core/login/pages/site-help/site-help.ts
@@ -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 { Component } from '@angular/core';
+import { IonicPage, ViewController } from 'ionic-angular';
+
+/**
+ * Component that displays some help regarding the CoreLoginSitePage.
+ */
+@IonicPage()
+@Component({
+ selector: 'page-core-login-site-help',
+ templateUrl: 'site-help.html',
+})
+export class CoreLoginSiteHelpPage {
+ constructor(private viewCtrl: ViewController) {}
+
+ /**
+ * Close help modal.
+ */
+ closeHelp() : void {
+ this.viewCtrl.dismiss();
+ }
+}
\ No newline at end of file
diff --git a/src/core/login/pages/site/site.html b/src/core/login/pages/site/site.html
new file mode 100644
index 000000000..88afa3c4c
--- /dev/null
+++ b/src/core/login/pages/site/site.html
@@ -0,0 +1,50 @@
+
+
+ {{ 'mm.login.connecttomoodle' | translate }}
+
+
+
+
+
+
+
+
+
diff --git a/src/core/login/pages/site/site.module.ts b/src/core/login/pages/site/site.module.ts
new file mode 100644
index 000000000..a22ceb243
--- /dev/null
+++ b/src/core/login/pages/site/site.module.ts
@@ -0,0 +1,33 @@
+// (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 { CoreLoginSitePage } from './site';
+import { CoreLoginModule } from '../../login.module';
+import { TranslateModule } from '@ngx-translate/core';
+import { CoreDirectivesModule } from '../../../../directives/directives.module';
+
+@NgModule({
+ declarations: [
+ CoreLoginSitePage
+ ],
+ imports: [
+ CoreDirectivesModule,
+ CoreLoginModule,
+ IonicPageModule.forChild(CoreLoginSitePage),
+ TranslateModule.forChild()
+ ]
+})
+export class CoreLoginSitePageModule {}
diff --git a/src/core/login/pages/site/site.scss b/src/core/login/pages/site/site.scss
new file mode 100644
index 000000000..e2f5f80af
--- /dev/null
+++ b/src/core/login/pages/site/site.scss
@@ -0,0 +1,25 @@
+page-core-login-site {
+ .content {
+ 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;
+ }
+
+ .item-input {
+ border: 1px solid $list-border-color;
+ }
+ }
+}
diff --git a/src/core/login/pages/site/site.ts b/src/core/login/pages/site/site.ts
new file mode 100644
index 000000000..ec1d9034f
--- /dev/null
+++ b/src/core/login/pages/site/site.ts
@@ -0,0 +1,128 @@
+// (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, ModalController } from 'ionic-angular';
+import { CoreAppProvider } from '../../../../providers/app';
+import { CoreSitesProvider } from '../../../../providers/sites';
+import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
+import { CoreConfigConstants } from '../../../../configconstants';
+import { CoreLoginHelperProvider } from '../../providers/helper';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+
+/**
+ * Page to enter or select the site URL to connect to.
+ */
+@IonicPage()
+@Component({
+ selector: 'page-core-login-site',
+ templateUrl: 'site.html',
+})
+export class CoreLoginSitePage {
+ siteForm: FormGroup;
+ fixedSites: any[];
+ displayAsButtons = false;
+
+ constructor(private navCtrl: NavController, fb: FormBuilder, private appProvider: CoreAppProvider,
+ private sitesProvider: CoreSitesProvider, private loginHelper: CoreLoginHelperProvider,
+ private modalCtrl: ModalController, private domUtils: CoreDomUtilsProvider) {
+ let url = '';
+
+ // Load fixed sites if they're set.
+ if (this.loginHelper.hasSeveralFixedSites()) {
+ this.fixedSites = this.loginHelper.getFixedSites();
+ this.displayAsButtons = CoreConfigConstants.multisitesdisplay == 'buttons';
+ url = this.fixedSites[0].url;
+ }
+
+ this.siteForm = fb.group({
+ 'siteUrl': [url, Validators.required]
+ });
+ }
+
+ /**
+ * Try to connect to a site.
+ */
+ connect(url: string) : void {
+ this.appProvider.closeKeyboard();
+
+ if (!url) {
+ this.domUtils.showErrorModal('mm.login.siteurlrequired', true);
+ return;
+ }
+
+ if (!this.appProvider.isOnline()) {
+ this.domUtils.showErrorModal('mm.core.networkerrormsg', true);
+ return;
+ }
+
+ let modal = this.domUtils.showModalLoading(),
+ siteData = this.sitesProvider.getDemoSiteData(url);
+
+ if (siteData) {
+ // It's a demo site.
+ this.sitesProvider.getUserToken(siteData.url, siteData.username, siteData.password).then((data) => {
+ return this.sitesProvider.newSite(data.siteUrl, data.token, data.privateToken).then(() => {
+ return this.loginHelper.goToSiteInitialPage(this.navCtrl, true);
+ }, (error) => {
+ this.domUtils.showErrorModal(error);
+ });
+ }, (error) => {
+ this.loginHelper.treatUserTokenError(siteData.url, error);
+ }).finally(() => {
+ modal.dismiss();
+ });
+
+ } else {
+ // Not a demo site.
+ this.sitesProvider.checkSite(url).then((result) => {
+
+ if (result.warning) {
+ this.domUtils.showErrorModal(result.warning, true, 4000);
+ }
+
+ if (this.loginHelper.isSSOLoginNeeded(result.code)) {
+ // SSO. User needs to authenticate in a browser.
+ this.loginHelper.confirmAndOpenBrowserForSSOLogin(
+ result.siteUrl, result.code, result.service, result.config && result.config.launchurl);
+ } else {
+ this.navCtrl.push('CoreLoginCredentialsPage', {siteUrl: result.siteUrl, siteConfig: result.config});
+ }
+ }, (error) => {
+ this.showLoginIssue(url, error);
+ }).finally(() => {
+ modal.dismiss();
+ });
+ }
+ }
+
+ /**
+ * Show a help modal.
+ */
+ showHelp() : void {
+ let modal = this.modalCtrl.create('CoreLoginSiteHelpPage');
+ modal.present();
+ }
+
+ /**
+ * Show an error that aims people to solve the issue.
+ *
+ * @param {string} url The URL the user was trying to connect to.
+ * @param {string} error Error to display.
+ */
+ protected showLoginIssue(url: string, error: string) : void {
+ let modal = this.modalCtrl.create('CoreLoginSiteErrorPage', {siteUrl: url, issue: error});
+ modal.present();
+ }
+}
diff --git a/src/providers/sites.ts b/src/providers/sites.ts
index 99f138e90..bdbb7007b 100644
--- a/src/providers/sites.ts
+++ b/src/providers/sites.ts
@@ -301,7 +301,9 @@ export class CoreSitesProvider {
}
const observable = this.http.post(siteUrl + '/login/token.php', data).timeout(CoreConstants.wsTimeout);
- return this.utils.observableToPromise(observable).then((data: any) => {
+ return this.utils.observableToPromise(observable).catch((error) => {
+ return Promise.reject(error.message);
+ }).then((data: any) => {
if (data.errorcode && (data.errorcode == 'enablewsdescription' || data.errorcode == 'requirecorrectaccess')) {
return Promise.reject({errorcode: data.errorcode, error: data.error});
} else if (data.error && data.error == 'Web services must be enabled in Advanced features.') {
diff --git a/src/theme/variables.scss b/src/theme/variables.scss
index 21fdcf593..23fdf718a 100644
--- a/src/theme/variables.scss
+++ b/src/theme/variables.scss
@@ -15,6 +15,39 @@ $app-direction: ltr;
@import "ionic.globals";
+// Color palette
+$black: #3a3a3a; // Headings, standard text.
+$gray-darker: #626262; // Text (emphasis-detail), placeholder, background.
+$gray-dark: #9e9e9e; // Borders (never text).
+$gray: #dddddd;
+$gray-light: #eeeeee; // Background.
+$gray-lighter: #f5f5f5;
+$white: #ffffff; // Background, reversed text.
+
+$blue: #0064d2; // Link, background.
+$blue-light: mix($blue, white, 20%); // Background.
+$blue-dark: darken($blue, 10%);
+
+$turquoise: #007982; // Accent.
+$turquoise-light: mix($turquoise, white, 20%); // Background.
+$turquoise-dark: darken($turquoise, 10%);
+
+$green: #5e8100; // Accent.
+$green-light: mix($green, white, 20%);
+$green-dark: darken($green, 10%);
+
+$red: #cb3d4d;
+$red-light: mix($red, white, 20%);
+$red-dark: darken($red, 10%);
+
+$orange: #f98012; // Accent (never text).
+$orange-light: lighten($orange, 10%);
+
+$yellow: #fbad1a; // Accent (never text).
+$yellow-light: mix($yellow, white, 20%);
+$yellow-dark: mix($yellow, black, 40%);
+
+
// Shared Variables
// --------------------------------------------------
// To customize the look and feel of this app, you can override
@@ -22,6 +55,8 @@ $app-direction: ltr;
// To view all the possible Ionic variables, see:
// http://ionicframework.com/docs/theming/overriding-ionic-variables/
+$toolbar-background: $orange;
+$content-padding: 10px;
@@ -91,41 +126,11 @@ $colors: (
// Moodle Mobile variables
// --------------------------------------------------
-// Color palette
-$black: #3a3a3a; // Headings, standard text.
-$gray-darker: #626262; // Text (emphasis-detail), placeholder, background.
-$gray-dark: #9e9e9e; // Borders (never text).
-$gray: #dddddd;
-$gray-light: #eeeeee; // Background.
-$gray-lighter: #f5f5f5;
-$white: #ffffff; // Background, reversed text.
-
-$blue: #0064d2; // Link, background.
-$blue-light: mix($blue, white, 20%); // Background.
-$blue-dark: darken($blue, 10%);
-
-$turquoise: #007982; // Accent.
-$turquoise-light: mix($turquoise, white, 20%); // Background.
-$turquoise-dark: darken($turquoise, 10%);
-
-$green: #5e8100; // Accent.
-$green-light: mix($green, white, 20%);
-$green-dark: darken($green, 10%);
-
-$red: #cb3d4d;
-$red-light: mix($red, white, 20%);
-$red-dark: darken($red, 10%);
-
-$orange: #f98012; // Accent (never text).
-$orange-light: lighten($orange, 10%);
-
-$yellow: #fbad1a; // Accent (never text).
-$yellow-light: mix($yellow, white, 20%);
-$yellow-dark: mix($yellow, black, 40%);
-
// Init screen.
$mm-color-init-screen: #ff5c00;
$mm-color-init-screen-alt: #ff7600;
$mm-init-screen-spinner-color: $white;
$mm-init-screen-logo-width: 60%;
$mm-init-screen-logo-max-width: 300px;
+
+$mm-fixed-url: false;