MOBILE-2253 login: Implement site page
parent
80961c23d9
commit
b3d77dfa5c
|
@ -63,7 +63,9 @@ export function createTranslateLoader(http: HttpClient) {
|
|||
imports: [
|
||||
BrowserModule,
|
||||
HttpClientModule,
|
||||
IonicModule.forRoot(MyApp),
|
||||
IonicModule.forRoot(MyApp, {
|
||||
pageTransition: 'ios-transition'
|
||||
}),
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
|
|
|
@ -16,6 +16,13 @@
|
|||
// automatically applied to the <body> element in the app.
|
||||
|
||||
|
||||
// Alignment
|
||||
// -------------------------
|
||||
|
||||
.text-left { text-align: left; }
|
||||
.text-right { text-align: right; }
|
||||
.text-center { text-align: center; }
|
||||
|
||||
/**
|
||||
* App Branding
|
||||
*/
|
||||
|
@ -53,3 +60,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (min-width: 430px) {
|
||||
.mm-center-view .scroll-content {
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
display: table !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
.mm-view-content {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
|
@ -1051,27 +1051,30 @@ export class CoreSite {
|
|||
modal.dismiss();
|
||||
}
|
||||
|
||||
let promise;
|
||||
if (alertMessage) {
|
||||
promise = this.domUtils.showAlert('mm.core.notice', alertMessage, null, 3000);
|
||||
let alert = this.domUtils.showAlert('mm.core.notice', alertMessage, null, 3000);
|
||||
alert.onDidDismiss(() => {
|
||||
if (inApp) {
|
||||
this.utils.openInApp(url, options);
|
||||
} else {
|
||||
this.utils.openInBrowser(url);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
promise = Promise.resolve();
|
||||
}
|
||||
|
||||
return promise.finally(() => {
|
||||
if (inApp) {
|
||||
this.utils.openInApp(url, options);
|
||||
} else {
|
||||
this.utils.openInBrowser(url);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (!this.privateToken || !this.wsAvailable('tool_mobile_get_autologin_key') ||
|
||||
(this.lastAutoLogin && this.timeUtils.timestamp() - this.lastAutoLogin < 6 * CoreConstants.secondsMinute)) {
|
||||
// No private token, WS not available or last auto-login was less than 6 minutes ago.
|
||||
// Open the final URL without auto-login.
|
||||
return open(url);
|
||||
open(url);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const userId = this.getUserId(),
|
||||
|
@ -1084,15 +1087,16 @@ export class CoreSite {
|
|||
return this.write('tool_mobile_get_autologin_key', params).then((data) => {
|
||||
if (!data.autologinurl || !data.key) {
|
||||
// Not valid data, open the final URL without auto-login.
|
||||
return open(url);
|
||||
open(url);
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastAutoLogin = this.timeUtils.timestamp();
|
||||
|
||||
return open(data.autologinurl + '?userid=' + userId + '&key=' + data.key + '&urltogo=' + url);
|
||||
open(data.autologinurl + '?userid=' + userId + '&key=' + data.key + '&urltogo=' + url);
|
||||
}).catch(() => {
|
||||
// Couldn't get autologin key, open the final URL without auto-login.
|
||||
return open(url);
|
||||
open(url);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"app_id" : "com.moodle.moodlemobile",
|
||||
"appname": "Moodle Mobile",
|
||||
"desktopappname": "Moodle Desktop",
|
||||
"versioncode" : "3000",
|
||||
"versioncode" : 3000,
|
||||
"versionname" : "3.3.5",
|
||||
"cache_expiration_time" : 300000,
|
||||
"default_lang" : "en",
|
||||
|
@ -13,6 +13,7 @@
|
|||
"gcmpn": "694767596569",
|
||||
"customurlscheme": "moodlemobile",
|
||||
"siteurl": "",
|
||||
"multisitesdisplay": "",
|
||||
"skipssoconfirmation": false,
|
||||
"forcedefaultlanguage": false,
|
||||
"privacypolicy": "https://moodle.org/mod/page/view.php?id=8148"
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<ion-header>
|
||||
<ion-navbar>
|
||||
<ion-title>{{ 'mm.core.error' | translate }}</ion-title>
|
||||
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-only (click)="closeModal()" [attr.aria-label]="'mm.core.close' | translate">
|
||||
<ion-icon name="close"></ion-icon>
|
||||
</button>
|
||||
</ion-buttons>
|
||||
</ion-navbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
<h3>{{ 'mm.core.whoops' | translate }}</h3>
|
||||
<p>{{ 'mm.login.problemconnectingerror' | translate }}</p>
|
||||
<p padding>{{siteUrl}}</p>
|
||||
<p>{{ 'mm.login.problemconnectingerrorcontinue' | translate }}</p>
|
||||
<button ion-button block (click)="closeModal()">{{ 'mm.core.tryagain' | translate }}</button>
|
||||
<h3>{{ 'mm.login.stillcantconnect' | translate }}</h3>
|
||||
<p>{{ 'mm.login.contactyouradministrator' | translate }}</p>
|
||||
<p *ngIf="issue">
|
||||
{{ 'mm.login.contactyouradministratorissue' | translate:{$a: ''} }}
|
||||
</p>
|
||||
<p *ngIf="issue">
|
||||
<core-format-text>{{issue}}</core-format-text>
|
||||
</p>
|
||||
</ion-content>
|
||||
|
|
@ -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 {}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<ion-header>
|
||||
<ion-navbar>
|
||||
<ion-title>{{ 'mm.login.help' | translate }}</ion-title>
|
||||
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-only (click)="closeHelp()" [attr.aria-label]="'mm.core.close' | translate">
|
||||
<ion-icon name="close"></ion-icon>
|
||||
</button>
|
||||
</ion-buttons>
|
||||
</ion-navbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
<core-format-text [text]="'mm.login.helpmelogin' | translate"></core-format-text>
|
||||
</ion-content>
|
|
@ -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 {}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<ion-header>
|
||||
<ion-navbar>
|
||||
<ion-title>{{ 'mm.login.connecttomoodle' | translate }}</ion-title>
|
||||
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-only (click)="showHelp()" [attr.aria-label]="'mm.core.help' | translate">
|
||||
<ion-icon name="help-circle"></ion-icon>
|
||||
</button>
|
||||
</ion-buttons>
|
||||
</ion-navbar>
|
||||
</ion-header>
|
||||
<ion-content id="mm-login-site" class="mm-center-view">
|
||||
<form class="mm-view-content" [formGroup]="siteForm" (ngSubmit)="connect(siteForm.value.siteUrl)">
|
||||
<ion-list class="box">
|
||||
<div class="text-center" padding>
|
||||
<img src="assets/img/logo.png" class="avatar-full moodle-logo" role="presentation">
|
||||
</div>
|
||||
|
||||
<!-- Form to input the site URL if there are no fixed sites. -->
|
||||
<div *ngIf="!fixedSites">
|
||||
<p padding>{{ 'mm.login.newsitedescription' | translate }}</p>
|
||||
<ion-item>
|
||||
<ion-input type="url" name="url" placeholder="{{ 'mm.login.siteaddress' | translate }}" formControlName="siteUrl" core-auto-focus></ion-input>
|
||||
</ion-item>
|
||||
</div>
|
||||
|
||||
<!-- Pick the site from a list of fixed sites. -->
|
||||
<div *ngIf="fixedSites" text-wrap>
|
||||
<!-- Display them using a select. -->
|
||||
<ion-item *ngIf="!displayAsButtons">
|
||||
<!-- @todo: Display label and select in different lines. -->
|
||||
<ion-label for="siteSelect">{{ 'mm.login.selectsite' | translate }}</ion-label>
|
||||
<ion-select formControlName="siteUrl" name="url" placeholder="{{ 'mm.login.siteaddress' | translate }}">
|
||||
<ion-option *ngFor="let site of fixedSites" [value]="site.url">{{site.name}}</ion-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<!-- Display them using buttons. -->
|
||||
<div *ngIf="displayAsButtons">
|
||||
<p class="padding no-padding-bottom">{{ 'mm.login.selectsite' | translate }}</p>
|
||||
<a *ngFor="let site of fixedSites" ion-button block (click)="connect(site.url)" title="{{site.name}}">{{site.name}}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!fixedSites || !displayAsButtons">
|
||||
<button ion-button block color="primary" [disabled]="!siteForm.valid">{{ 'mm.login.connect' | translate }}</button>
|
||||
</div>
|
||||
</ion-list>
|
||||
</form>
|
||||
</ion-content>
|
|
@ -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 {}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 = <any[]> 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();
|
||||
}
|
||||
}
|
|
@ -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.') {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue