2
0
Fork 0

Merge pull request #1354 from crazyserver/MOBILE-2430

Mobile 2430
main
Juan Leyva 2018-06-19 16:46:54 +02:00 committed by GitHub
commit 1393dbda04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 236 additions and 274 deletions

View File

@ -53,22 +53,7 @@ export class AddonModAssignFeedbackCommentsComponent extends AddonModAssignFeedb
* Component being initialized. * Component being initialized.
*/ */
ngOnInit(): void { ngOnInit(): void {
let promise, this.getText().then((text) => {
rteEnabled;
// Check if rich text editor is enabled.
if (this.edit) {
promise = this.domUtils.isRichTextEditorEnabled();
} else {
// We aren't editing, so no rich text editor.
promise = Promise.resolve(false);
}
promise.then((enabled) => {
rteEnabled = enabled;
return this.getText(rteEnabled);
}).then((text) => {
this.text = text; this.text = text;
@ -113,10 +98,9 @@ export class AddonModAssignFeedbackCommentsComponent extends AddonModAssignFeedb
/** /**
* Get the text for the plugin. * Get the text for the plugin.
* *
* @param {boolean} rteEnabled Whether Rich Text Editor is enabled.
* @return {Promise<string>} Promise resolved with the text. * @return {Promise<string>} Promise resolved with the text.
*/ */
protected getText(rteEnabled: boolean): Promise<string> { protected getText(): Promise<string> {
// Check if the user already modified the comment. // Check if the user already modified the comment.
return this.feedbackDelegate.getPluginDraftData(this.assign.id, this.userId, this.plugin).then((draft) => { return this.feedbackDelegate.getPluginDraftData(this.assign.id, this.userId, this.plugin).then((draft) => {
if (draft) { if (draft) {
@ -140,7 +124,7 @@ export class AddonModAssignFeedbackCommentsComponent extends AddonModAssignFeedb
// No offline data found, return online text. // No offline data found, return online text.
this.isSent = true; this.isSent = true;
return this.assignProvider.getSubmissionPluginText(this.plugin, this.edit && !rteEnabled); return this.assignProvider.getSubmissionPluginText(this.plugin);
}); });
} }
}); });

View File

@ -15,7 +15,6 @@
import { Injectable, Injector } from '@angular/core'; import { Injectable, Injector } from '@angular/core';
import { CoreSitesProvider } from '@providers/sites'; import { CoreSitesProvider } from '@providers/sites';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTextUtilsProvider } from '@providers/utils/text';
import { AddonModAssignProvider } from '../../../providers/assign'; import { AddonModAssignProvider } from '../../../providers/assign';
import { AddonModAssignOfflineProvider } from '../../../providers/assign-offline'; import { AddonModAssignOfflineProvider } from '../../../providers/assign-offline';
@ -32,9 +31,8 @@ export class AddonModAssignFeedbackCommentsHandler implements AddonModAssignFeed
protected drafts = {}; // Store the data in this service so it isn't lost if the user performs a PTR in the page. protected drafts = {}; // Store the data in this service so it isn't lost if the user performs a PTR in the page.
constructor(private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider, constructor(private sitesProvider: CoreSitesProvider, private textUtils: CoreTextUtilsProvider,
private textUtils: CoreTextUtilsProvider, private assignProvider: AddonModAssignProvider, private assignProvider: AddonModAssignProvider, private assignOfflineProvider: AddonModAssignOfflineProvider) { }
private assignOfflineProvider: AddonModAssignOfflineProvider) { }
/** /**
* Discard the draft data of the feedback plugin. * Discard the draft data of the feedback plugin.
@ -133,9 +131,7 @@ export class AddonModAssignFeedbackCommentsHandler implements AddonModAssignFeed
} }
// No offline data found, get text from plugin. // No offline data found, get text from plugin.
return this.domUtils.isRichTextEditorEnabled().then((enabled) => { return this.assignProvider.getSubmissionPluginText(plugin);
return this.assignProvider.getSubmissionPluginText(plugin, !enabled);
});
}).then((initialText) => { }).then((initialText) => {
const newText = AddonModAssignFeedbackCommentsHandler.getTextFromInputData(this.textUtils, plugin, inputData); const newText = AddonModAssignFeedbackCommentsHandler.getTextFromInputData(this.textUtils, plugin, inputData);
@ -185,14 +181,10 @@ export class AddonModAssignFeedbackCommentsHandler implements AddonModAssignFeed
const draft = this.getDraft(assignId, userId, siteId); const draft = this.getDraft(assignId, userId, siteId);
if (draft) { if (draft) {
return this.domUtils.isRichTextEditorEnabled().then((enabled) => { // Add some HTML to the text if needed.
if (!enabled) { draft.text = this.textUtils.formatHtmlLines(draft.text);
// Rich text editor not enabled, add some HTML to the text if needed.
draft.text = this.textUtils.formatHtmlLines(draft.text);
}
pluginData.assignfeedbackcomments_editor = draft; pluginData.assignfeedbackcomments_editor = draft;
});
} }
} }

View File

@ -50,31 +50,16 @@ export class AddonModAssignSubmissionOnlineTextComponent extends AddonModAssignS
* Component being initialized. * Component being initialized.
*/ */
ngOnInit(): void { ngOnInit(): void {
let promise, // Get the text. Check if we have anything offline.
rteEnabled; this.assignOfflineProvider.getSubmission(this.assign.id).catch(() => {
// No offline data found.
}).then((offlineData) => {
if (offlineData && offlineData.plugindata && offlineData.plugindata.onlinetext_editor) {
return offlineData.plugindata.onlinetext_editor.text;
}
// Check if rich text editor is enabled. // No offline data found, return online text.
if (this.edit) { return this.assignProvider.getSubmissionPluginText(this.plugin);
promise = this.domUtils.isRichTextEditorEnabled();
} else {
// We aren't editing, so no rich text editor.
promise = Promise.resolve(false);
}
promise.then((enabled) => {
rteEnabled = enabled;
// Get the text. Check if we have anything offline.
return this.assignOfflineProvider.getSubmission(this.assign.id).catch(() => {
// No offline data found.
}).then((offlineData) => {
if (offlineData && offlineData.plugindata && offlineData.plugindata.onlinetext_editor) {
return offlineData.plugindata.onlinetext_editor.text;
}
// No offline data found, return online text.
return this.assignProvider.getSubmissionPluginText(this.plugin, this.edit && !rteEnabled);
});
}).then((text) => { }).then((text) => {
// We receive them as strings, convert to int. // We receive them as strings, convert to int.
this.configs.wordlimit = parseInt(this.configs.wordlimit, 10); this.configs.wordlimit = parseInt(this.configs.wordlimit, 10);

View File

@ -16,7 +16,6 @@
import { Injectable, Injector } from '@angular/core'; import { Injectable, Injector } from '@angular/core';
import { CoreSitesProvider } from '@providers/sites'; import { CoreSitesProvider } from '@providers/sites';
import { CoreWSProvider } from '@providers/ws'; import { CoreWSProvider } from '@providers/ws';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTextUtilsProvider } from '@providers/utils/text';
import { AddonModAssignProvider } from '../../../providers/assign'; import { AddonModAssignProvider } from '../../../providers/assign';
import { AddonModAssignOfflineProvider } from '../../../providers/assign-offline'; import { AddonModAssignOfflineProvider } from '../../../providers/assign-offline';
@ -33,9 +32,8 @@ export class AddonModAssignSubmissionOnlineTextHandler implements AddonModAssign
type = 'onlinetext'; type = 'onlinetext';
constructor(private sitesProvider: CoreSitesProvider, private wsProvider: CoreWSProvider, constructor(private sitesProvider: CoreSitesProvider, private wsProvider: CoreWSProvider,
private domUtils: CoreDomUtilsProvider, private textUtils: CoreTextUtilsProvider, private textUtils: CoreTextUtilsProvider, private assignProvider: AddonModAssignProvider,
private assignProvider: AddonModAssignProvider, private assignOfflineProvider: AddonModAssignOfflineProvider, private assignOfflineProvider: AddonModAssignOfflineProvider, private assignHelper: AddonModAssignHelperProvider) { }
private assignHelper: AddonModAssignHelperProvider) { }
/** /**
* Whether the plugin can be edited in offline for existing submissions. In general, this should return false if the * Whether the plugin can be edited in offline for existing submissions. In general, this should return false if the
@ -238,19 +236,16 @@ export class AddonModAssignSubmissionOnlineTextHandler implements AddonModAssign
prepareSubmissionData(assign: any, submission: any, plugin: any, inputData: any, pluginData: any, offline?: boolean, prepareSubmissionData(assign: any, submission: any, plugin: any, inputData: any, pluginData: any, offline?: boolean,
userId?: number, siteId?: string): void | Promise<any> { userId?: number, siteId?: string): void | Promise<any> {
return this.domUtils.isRichTextEditorEnabled().then((enabled) => { let text = this.getTextToSubmit(plugin, inputData);
let text = this.getTextToSubmit(plugin, inputData);
if (!enabled) {
// Rich text editor not enabled, add some HTML to the text if needed.
text = this.textUtils.formatHtmlLines(text);
}
pluginData.onlinetext_editor = { // Add some HTML to the text if needed.
text: text, text = this.textUtils.formatHtmlLines(text);
format: 1,
itemid: 0 // Can't add new files yet, so we use a fake itemid. pluginData.onlinetext_editor = {
}; text: text,
}); format: 1,
itemid: 0 // Can't add new files yet, so we use a fake itemid.
};
} }
/** /**

View File

@ -15,7 +15,6 @@ import { Injector, Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { AddonModDataFieldTextHandler } from '../../text/providers/handler'; import { AddonModDataFieldTextHandler } from '../../text/providers/handler';
import { AddonModDataFieldTextareaComponent } from '../component/textarea'; import { AddonModDataFieldTextareaComponent } from '../component/textarea';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTextUtilsProvider } from '@providers/utils/text';
/** /**
@ -26,8 +25,7 @@ export class AddonModDataFieldTextareaHandler extends AddonModDataFieldTextHandl
name = 'AddonModDataFieldTextareaHandler'; name = 'AddonModDataFieldTextareaHandler';
type = 'textarea'; type = 'textarea';
constructor(protected translate: TranslateService, private textUtils: CoreTextUtilsProvider, constructor(protected translate: TranslateService, private textUtils: CoreTextUtilsProvider) {
private domUtils: CoreDomUtilsProvider) {
super(translate); super(translate);
} }
@ -54,31 +52,27 @@ export class AddonModDataFieldTextareaHandler extends AddonModDataFieldTextHandl
const fieldName = 'f_' + field.id; const fieldName = 'f_' + field.id;
if (inputData[fieldName]) { if (inputData[fieldName]) {
return this.domUtils.isRichTextEditorEnabled().then((enabled) => { const files = this.getFieldEditFiles(field, inputData, originalFieldData);
const files = this.getFieldEditFiles(field, inputData, originalFieldData); let text = this.textUtils.restorePluginfileUrls(inputData[fieldName], files);
let text = this.textUtils.restorePluginfileUrls(inputData[fieldName], files);
if (!enabled) { // Add some HTML to the text if needed.
// Rich text editor not enabled, add some HTML to the text if needed. text = this.textUtils.formatHtmlLines(text);
text = this.textUtils.formatHtmlLines(text);
return [{
fieldid: field.id,
value: text
},
{
fieldid: field.id,
subfield: 'content1',
value: 1
},
{
fieldid: field.id,
subfield: 'itemid',
files: files
} }
];
return [{
fieldid: field.id,
value: text
},
{
fieldid: field.id,
subfield: 'content1',
value: 1
},
{
fieldid: field.id,
subfield: 'itemid',
files: files
}
];
});
} }
return false; return false;

View File

@ -182,29 +182,29 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy {
const files = this.replyData.files || []; const files = this.replyData.files || [];
const options: any = {}; const options: any = {};
const modal = this.domUtils.showModalLoading('core.sending', true); const modal = this.domUtils.showModalLoading('core.sending', true);
let promise;
// Check if rich text editor is enabled or not. // Add some HTML to the message if needed.
this.domUtils.isRichTextEditorEnabled().then((enabled) => { message = this.textUtils.formatHtmlLines(message);
if (!enabled) {
// Rich text editor not enabled, add some HTML to the message if needed.
message = this.textUtils.formatHtmlLines(message);
}
// Upload attachments first if any. // Upload attachments first if any.
if (files.length) { if (files.length) {
return this.forumHelper.uploadOrStoreReplyFiles(this.forum.id, replyingTo, files, false).catch((error) => { promise = this.forumHelper.uploadOrStoreReplyFiles(this.forum.id, replyingTo, files, false).catch((error) => {
// Cannot upload them in online, save them in offline. // Cannot upload them in online, save them in offline.
if (!this.forum.id) { if (!this.forum.id) {
// Cannot store them in offline without the forum ID. Reject. // Cannot store them in offline without the forum ID. Reject.
return Promise.reject(error); return Promise.reject(error);
} }
saveOffline = true; saveOffline = true;
return this.forumHelper.uploadOrStoreReplyFiles(this.forum.id, replyingTo, files, true); return this.forumHelper.uploadOrStoreReplyFiles(this.forum.id, replyingTo, files, true);
}); });
} } else {
}).then((attach) => { promise = Promise.resolve();
}
promise.then((attach) => {
if (attach) { if (attach) {
options.attachmentsid = attach; options.attachmentsid = attach;
} }

View File

@ -68,6 +68,7 @@ export class AddonModForumDiscussionPage implements OnDestroy {
}; };
refreshIcon = 'spinner'; refreshIcon = 'spinner';
syncIcon = 'spinner'; syncIcon = 'spinner';
discussionStr = '';
protected cmId: number; protected cmId: number;
protected forumId: number; protected forumId: number;
@ -101,6 +102,8 @@ export class AddonModForumDiscussionPage implements OnDestroy {
this.isOnline = this.appProvider.isOnline(); this.isOnline = this.appProvider.isOnline();
}); });
this.isSplitViewOn = this.svComponent && this.svComponent.isOn(); this.isSplitViewOn = this.svComponent && this.svComponent.isOn();
this.discussionStr = translate.instant('addon.mod_forum.discussion');
} }
/** /**

View File

@ -423,25 +423,25 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
} }
const modal = this.domUtils.showModalLoading('core.sending', true); const modal = this.domUtils.showModalLoading('core.sending', true);
let promise;
// Check if rich text editor is enabled or not. // Add some HTML to the message if needed.
this.domUtils.isRichTextEditorEnabled().then((enabled) => { message = this.textUtils.formatHtmlLines(message);
if (!enabled) {
// Rich text editor not enabled, add some HTML to the message if needed.
message = this.textUtils.formatHtmlLines(message);
}
// Upload attachments first if any. // Upload attachments first if any.
if (attachments.length) { if (attachments.length) {
return this.forumHelper.uploadOrStoreNewDiscussionFiles(this.forumId, discTimecreated, attachments, false) promise = this.forumHelper.uploadOrStoreNewDiscussionFiles(this.forumId, discTimecreated, attachments, false)
.catch(() => { .catch(() => {
// Cannot upload them in online, save them in offline. // Cannot upload them in online, save them in offline.
saveOffline = true; saveOffline = true;
return this.forumHelper.uploadOrStoreNewDiscussionFiles(this.forumId, discTimecreated, attachments, true); return this.forumHelper.uploadOrStoreNewDiscussionFiles(this.forumId, discTimecreated, attachments, true);
}); });
} } else {
}).then((attach) => { promise = Promise.resolve();
}
promise.then((attach) => {
if (attach) { if (attach) {
options.attachmentsid = attach; options.attachmentsid = attach;
} }

View File

@ -159,9 +159,10 @@ export class AddonModGlossaryEditPage implements OnInit {
* Save the entry. * Save the entry.
*/ */
save(): void { save(): void {
let definition = this.entry.definition; let definition = this.entry.definition,
saveOffline = false,
promise;
const timecreated = this.entry.timecreated || Date.now(); const timecreated = this.entry.timecreated || Date.now();
let saveOffline = false;
if (!this.entry.concept || !definition) { if (!this.entry.concept || !definition) {
this.domUtils.showErrorModal('addon.mod_glossary.fillfields', true); this.domUtils.showErrorModal('addon.mod_glossary.fillfields', true);
@ -171,25 +172,24 @@ export class AddonModGlossaryEditPage implements OnInit {
const modal = this.domUtils.showModalLoading('core.sending', true); const modal = this.domUtils.showModalLoading('core.sending', true);
// Check if rich text editor is enabled or not. // Add some HTML to the definition if needed.
this.domUtils.isRichTextEditorEnabled().then((enabled) => { definition = this.textUtils.formatHtmlLines(definition);
if (!enabled) {
// Rich text editor not enabled, add some HTML to the definition if needed.
definition = this.textUtils.formatHtmlLines(definition);
}
// Upload attachments first if any. // Upload attachments first if any.
if (this.attachments.length > 0) { if (this.attachments.length > 0) {
return this.glossaryHelper.uploadOrStoreFiles(this.glossary.id, this.entry.concept, timecreated, this.attachments, promise = this.glossaryHelper.uploadOrStoreFiles(this.glossary.id, this.entry.concept, timecreated, this.attachments,
false).catch(() => { false).catch(() => {
// Cannot upload them in online, save them in offline. // Cannot upload them in online, save them in offline.
saveOffline = true; saveOffline = true;
return this.glossaryHelper.uploadOrStoreFiles(this.glossary.id, this.entry.concept, timecreated, return this.glossaryHelper.uploadOrStoreFiles(this.glossary.id, this.entry.concept, timecreated,
this.attachments, true); this.attachments, true);
}); });
} } else {
}).then((attach) => { promise = Promise.resolve();
}
promise.then((attach) => {
const options: any = { const options: any = {
aliases: this.options.aliases, aliases: this.options.aliases,
categories: this.options.categories.join(',') categories: this.options.categories.join(',')

View File

@ -107,7 +107,7 @@
</ng-container> </ng-container>
<ion-item> <ion-item>
<button ion-button block (click)="submitQuestion()">{{ question.submitLabel }}</button> <button ion-button block (click)="submitQuestion()" class="button-no-uppercase">{{ question.submitLabel }}</button>
</ion-item> </ion-item>
</form> </form>
</ion-card> </ion-card>
@ -117,7 +117,7 @@
<ion-grid text-wrap *ngIf="pageButtons && pageButtons.length" class="addon-mod_lesson-pagebuttons"> <ion-grid text-wrap *ngIf="pageButtons && pageButtons.length" class="addon-mod_lesson-pagebuttons">
<ion-row align-items-center> <ion-row align-items-center>
<ion-col *ngFor="let button of pageButtons" col-12 col-md-6 col-lg-3 col-xl> <ion-col *ngFor="let button of pageButtons" col-12 col-md-6 col-lg-3 col-xl>
<a ion-button block outline text-wrap [id]="button.id" (click)="buttonClicked(button.data)">{{ button.content }}</a> <a ion-button block outline text-wrap [id]="button.id" (click)="buttonClicked(button.data)" class="button-no-uppercase">{{ button.content }}</a>
</ion-col> </ion-col>
</ion-row> </ion-row>
</ion-grid> </ion-grid>
@ -174,7 +174,7 @@
<core-format-text [text]="eolData.displayofgrade.message"></core-format-text> <core-format-text [text]="eolData.displayofgrade.message"></core-format-text>
</ion-item> </ion-item>
<ion-item text-wrap *ngIf="eolData.reviewlesson"> <ion-item text-wrap *ngIf="eolData.reviewlesson">
<a ion-button block (click)="reviewLesson(eolData.reviewlesson.pageid)"> <a ion-button block (click)="reviewLesson(eolData.reviewlesson.pageid)" class="button-no-uppercase">
<core-format-text [text]="'addon.mod_lesson.reviewlesson' | translate"></core-format-text> <core-format-text [text]="'addon.mod_lesson.reviewlesson' | translate"></core-format-text>
</a> </a>
</ion-item> </ion-item>
@ -184,7 +184,7 @@
<ion-item text-wrap *ngIf="eolData.activitylink && eolData.activitylink.value"> <ion-item text-wrap *ngIf="eolData.activitylink && eolData.activitylink.value">
<ng-container *ngIf="eolData.activitylink.value.formatted"> <ng-container *ngIf="eolData.activitylink.value.formatted">
<!-- Activity link was successfully formatted, render the button. --> <!-- Activity link was successfully formatted, render the button. -->
<a ion-button block color="light" [href]="eolData.activitylink.value.href" core-link [capture]="true"> <a ion-button block color="light" [href]="eolData.activitylink.value.href" core-link [capture]="true" class="button-no-uppercase">
<core-format-text [text]="eolData.activitylink.value.label"></core-format-text> <core-format-text [text]="eolData.activitylink.value.label"></core-format-text>
</a> </a>
</ng-container> </ng-container>

View File

@ -12,10 +12,12 @@ page-addon-mod-lesson-player {
.addon-mod_lesson-pagebuttons .button-block { .addon-mod_lesson-pagebuttons .button-block {
contain: content; contain: content;
height: auto; height: 100%;
display: flex;
flex-direction: column;
.button-inner { .button-inner {
height: auto; flex-grow: 1;
} }
} }
} }

View File

@ -611,9 +611,9 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy {
this.loaded = false; this.loaded = false;
// Use getRawValue to include disabled values. // Use getRawValue to include disabled values.
this.lessonHelper.prepareQuestionData(this.question, this.questionForm.getRawValue()).then((data) => { const data = this.lessonHelper.prepareQuestionData(this.question, this.questionForm.getRawValue());
return this.processPage(data);
}).finally(() => { this.processPage(data).finally(() => {
this.loaded = true; this.loaded = true;
}); });
} }

View File

@ -452,19 +452,12 @@ export class AddonModLessonHelperProvider {
* *
* @param {any} question Question to prepare. * @param {any} question Question to prepare.
* @param {any} data Data to prepare. * @param {any} data Data to prepare.
* @return {Promise<any>} Promise resolved with the data to send when done. * @return {any} Data to send.
*/ */
prepareQuestionData(question: any, data: any): Promise<any> { prepareQuestionData(question: any, data: any): any {
if (question.template == 'essay' && question.textarea) { if (question.template == 'essay' && question.textarea) {
// The answer might need formatting. Check if rich text editor is enabled or not. // Add some HTML to the answer if needed.
return this.domUtils.isRichTextEditorEnabled().then((enabled) => { data[question.textarea.property] = this.textUtils.formatHtmlLines(data[question.textarea.property]);
if (!enabled) {
// Rich text editor not enabled, add some HTML to the answer if needed.
data[question.textarea.property] = this.textUtils.formatHtmlLines(data[question.textarea.property]);
}
return data;
});
} else if (question.template == 'multichoice' && question.multi) { } else if (question.template == 'multichoice' && question.multi) {
// Only send the options with value set to true. // Only send the options with value set to true.
for (const name in data) { for (const name in data) {
@ -474,7 +467,7 @@ export class AddonModLessonHelperProvider {
} }
} }
return Promise.resolve(data); return data;
} }
/** /**

View File

@ -58,7 +58,6 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy {
protected blockId: string; // ID to block the subwiki. protected blockId: string; // ID to block the subwiki.
protected editing: boolean; // Whether the user is editing a page (true) or creating a new one (false). protected editing: boolean; // Whether the user is editing a page (true) or creating a new one (false).
protected editOffline: boolean; // Whether the user is editing an offline page. protected editOffline: boolean; // Whether the user is editing an offline page.
protected rteEnabled: boolean; // Whether rich text editor is enabled.
protected subwikiFiles: any[]; // List of files of the subwiki. protected subwikiFiles: any[]; // List of files of the subwiki.
protected originalContent: string; // The original page content. protected originalContent: string; // The original page content.
protected version: number; // Page version. protected version: number; // Page version.
@ -151,15 +150,8 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy {
// Wait for sync to be over (if any). // Wait for sync to be over (if any).
return this.wikiSync.waitForSync(this.blockId); return this.wikiSync.waitForSync(this.blockId);
}).then(() => { }).then(() => {
// Check if rich text editor is enabled. // Get subwiki files, needed to replace URLs for rich text editor.
return this.domUtils.isRichTextEditorEnabled(); return this.wikiProvider.getSubwikiFiles(this.wikiId, this.groupId, this.userId);
}).then((enabled) => {
this.rteEnabled = enabled;
if (enabled) {
// Get subwiki files, needed to replace URLs for rich text editor.
return this.wikiProvider.getSubwikiFiles(this.wikiId, this.groupId, this.userId);
}
}).then((files) => { }).then((files) => {
this.subwikiFiles = files; this.subwikiFiles = files;
@ -167,8 +159,7 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy {
return this.wikiProvider.getPageForEditing(this.pageId, this.section); return this.wikiProvider.getPageForEditing(this.pageId, this.section);
}).then((editContents) => { }).then((editContents) => {
// Get the original page contents, treating file URLs if needed. // Get the original page contents, treating file URLs if needed.
const content = this.rteEnabled ? this.textUtils.replacePluginfileUrls(editContents.content, this.subwikiFiles) : const content = this.textUtils.replacePluginfileUrls(editContents.content, this.subwikiFiles);
editContents.content;
this.contentControl.setValue(content); this.contentControl.setValue(content);
this.originalContent = content; this.originalContent = content;
@ -411,11 +402,8 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy {
let promise, let promise,
text = values.text; text = values.text;
if (this.rteEnabled) { text = this.textUtils.restorePluginfileUrls(text, this.subwikiFiles);
text = this.textUtils.restorePluginfileUrls(text, this.subwikiFiles); text = this.textUtils.formatHtmlLines(text);
} else {
text = this.textUtils.formatHtmlLines(text);
}
if (this.editing) { if (this.editing) {
// Edit existing page. // Edit existing page.

View File

@ -64,7 +64,6 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit {
weights: any[]; weights: any[];
weight: number; weight: number;
protected rteEnabled: boolean;
protected obsInvalidated: any; protected obsInvalidated: any;
protected hasOffline: boolean; protected hasOffline: boolean;
protected originalData = { protected originalData = {
@ -117,24 +116,13 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit {
} }
} }
let promise;
// Check if rich text editor is enabled. // Check if rich text editor is enabled.
if (this.edit) { if (this.edit) {
// Block the workshop. // Block the workshop.
this.syncProvider.blockOperation(AddonModWorkshopProvider.COMPONENT, this.workshop.id); this.syncProvider.blockOperation(AddonModWorkshopProvider.COMPONENT, this.workshop.id);
promise = this.domUtils.isRichTextEditorEnabled();
} else {
// We aren't editing, so no rich text editor.
promise = Promise.resolve(false);
} }
promise.then((enabled) => { this.load().then(() => {
this.rteEnabled = enabled;
return this.load();
}).then(() => {
this.obsInvalidated = this.eventsProvider.on(AddonModWorkshopProvider.ASSESSMENT_INVALIDATED, this.obsInvalidated = this.eventsProvider.on(AddonModWorkshopProvider.ASSESSMENT_INVALIDATED,
this.load.bind(this), this.sitesProvider.getCurrentSiteId()); this.load.bind(this), this.sitesProvider.getCurrentSiteId());
}).finally(() => { }).finally(() => {

View File

@ -331,21 +331,16 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy {
* @return {Promise<any>} Resolved when done. * @return {Promise<any>} Resolved when done.
*/ */
protected sendEvaluation(): Promise<any> { protected sendEvaluation(): Promise<any> {
const modal = this.domUtils.showModalLoading('core.sending', true); const modal = this.domUtils.showModalLoading('core.sending', true),
inputData = this.evaluateForm.value;
// Check if rich text editor is enabled or not. inputData.grade = inputData.grade >= 0 ? inputData.grade : '';
return this.domUtils.isRichTextEditorEnabled().then((rteEnabled) => { // Add some HTML to the message if needed.
const inputData = this.evaluateForm.value; inputData.text = this.textUtils.formatHtmlLines(inputData.text);
inputData.grade = inputData.grade >= 0 ? inputData.grade : '';
if (!rteEnabled) {
// Rich text editor not enabled, add some HTML to the message if needed.
inputData.text = this.textUtils.formatHtmlLines(inputData.text);
}
// Try to send it to server. // Try to send it to server.
return this.workshopProvider.evaluateAssessment(this.workshopId, this.assessmentId, this.courseId, inputData.text, return this.workshopProvider.evaluateAssessment(this.workshopId, this.assessmentId, this.courseId, inputData.text,
inputData.weight, inputData.grade); inputData.weight, inputData.grade).then(() => {
}).then(() => {
const data = { const data = {
workshopId: this.workshopId, workshopId: this.workshopId,
assessmentId: this.assessmentId, assessmentId: this.assessmentId,

View File

@ -312,25 +312,20 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy {
const modal = this.domUtils.showModalLoading('core.sending', true), const modal = this.domUtils.showModalLoading('core.sending', true),
submissionId = this.submission.id; submissionId = this.submission.id;
// Check if rich text editor is enabled or not. // Add some HTML to the message if needed.
return this.domUtils.isRichTextEditorEnabled().then((rteEnabled) => { inputData.content = this.textUtils.formatHtmlLines(inputData.content);
if (!rteEnabled) {
// Rich text editor not enabled, add some HTML to the message if needed.
inputData.content = this.textUtils.formatHtmlLines(inputData.content);
}
// Upload attachments first if any. // Upload attachments first if any.
allowOffline = !inputData.attachmentfiles.length; allowOffline = !inputData.attachmentfiles.length;
return this.workshopHelper.uploadOrStoreSubmissionFiles(this.workshopId, this.submission.id, inputData.attachmentfiles, return this.workshopHelper.uploadOrStoreSubmissionFiles(this.workshopId, this.submission.id, inputData.attachmentfiles,
this.editing, saveOffline).catch(() => { this.editing, saveOffline).catch(() => {
// Cannot upload them in online, save them in offline. // Cannot upload them in online, save them in offline.
saveOffline = true; saveOffline = true;
allowOffline = true; allowOffline = true;
return this.workshopHelper.uploadOrStoreSubmissionFiles(this.workshopId, this.submission.id, return this.workshopHelper.uploadOrStoreSubmissionFiles(this.workshopId, this.submission.id,
inputData.attachmentfiles, this.editing, saveOffline); inputData.attachmentfiles, this.editing, saveOffline);
});
}).then((attachmentsId) => { }).then((attachmentsId) => {
if (this.editing) { if (this.editing) {
if (saveOffline) { if (saveOffline) {

View File

@ -430,20 +430,15 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy {
protected sendEvaluation(): Promise<any> { protected sendEvaluation(): Promise<any> {
const modal = this.domUtils.showModalLoading('core.sending', true); const modal = this.domUtils.showModalLoading('core.sending', true);
// Check if rich text editor is enabled or not. const inputData = this.feedbackForm.value;
return this.domUtils.isRichTextEditorEnabled().then((rteEnabled) => {
const inputData = this.feedbackForm.value;
inputData.grade = inputData.grade >= 0 ? inputData.grade : ''; inputData.grade = inputData.grade >= 0 ? inputData.grade : '';
if (!rteEnabled) { // Add some HTML to the message if needed.
// Rich text editor not enabled, add some HTML to the message if needed. inputData.text = this.textUtils.formatHtmlLines(inputData.text);
inputData.text = this.textUtils.formatHtmlLines(inputData.text);
}
// Try to send it to server. // Try to send it to server.
return this.workshopProvider.evaluateSubmission(this.workshopId, this.submissionId, this.courseId, inputData.text, return this.workshopProvider.evaluateSubmission(this.workshopId, this.submissionId, this.courseId, inputData.text,
inputData.published, inputData.grade); inputData.published, inputData.grade).then(() => {
}).then(() => {
const data = { const data = {
workshopId: this.workshopId, workshopId: this.workshopId,
cmId: this.module.cmid, cmId: this.module.cmid,

View File

@ -14,7 +14,6 @@
// limitations under the License. // limitations under the License.
import { Injectable, Injector } from '@angular/core'; import { Injectable, Injector } from '@angular/core';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTextUtilsProvider } from '@providers/utils/text';
import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreQuestionHandler } from '@core/question/providers/delegate'; import { CoreQuestionHandler } from '@core/question/providers/delegate';
@ -32,7 +31,7 @@ export class AddonQtypeEssayHandler implements CoreQuestionHandler {
protected div = document.createElement('div'); // A div element to search in HTML code. protected div = document.createElement('div'); // A div element to search in HTML code.
constructor(private utils: CoreUtilsProvider, private questionHelper: CoreQuestionHelperProvider, constructor(private utils: CoreUtilsProvider, private questionHelper: CoreQuestionHelperProvider,
private domUtils: CoreDomUtilsProvider, private textUtils: CoreTextUtilsProvider) { } private textUtils: CoreTextUtilsProvider) { }
/** /**
* Return the name of the behaviour to use for the question. * Return the name of the behaviour to use for the question.
@ -148,12 +147,8 @@ export class AddonQtypeEssayHandler implements CoreQuestionHandler {
const textarea = <HTMLTextAreaElement> this.div.querySelector('textarea[name*=_answer]'); const textarea = <HTMLTextAreaElement> this.div.querySelector('textarea[name*=_answer]');
if (textarea && typeof answers[textarea.name] != 'undefined') { if (textarea && typeof answers[textarea.name] != 'undefined') {
return this.domUtils.isRichTextEditorEnabled().then((enabled) => { // Add some HTML to the text if needed.
if (!enabled) { answers[textarea.name] = this.textUtils.formatHtmlLines(answers[textarea.name]);
// Rich text editor not enabled, add some HTML to the text if needed.
answers[textarea.name] = this.textUtils.formatHtmlLines(answers[textarea.name]);
}
});
} }
} }
} }

View File

@ -41,6 +41,18 @@
height: calc(100% - #{($navbar-ios-height)}); height: calc(100% - #{($navbar-ios-height)});
} }
.platform-cordova.ios .core-avoid-header .menu-inner > ion-content {
top: $navbar-ios-height + $cordova-ios-statusbar-padding;
height: calc(100% - #{($navbar-ios-height + $cordova-ios-statusbar-padding)});
}
.platform-cordova.ios .core-avoid-header .core-avoid-header .menu-inner > ion-content,
.platform-cordova.ios core-tab core-split-view .core-avoid-header .menu-inner > ion-content {
top: 0;
height: 100%;
}
// Highlights inside the input element. // Highlights inside the input element.
@if ($core-text-input-ios-show-highlight) { @if ($core-text-input-ios-show-highlight) {
.card-ios, .list-ios { .card-ios, .list-ios {

View File

@ -39,6 +39,10 @@
.core-big { font-size: 115%; } .core-big { font-size: 115%; }
.invisible { visibility: hidden; } .invisible { visibility: hidden; }
.button-no-uppercase {
text-transform: none;
}
@include media-breakpoint-up(sm) { @include media-breakpoint-up(sm) {
.core-center-view .scroll-content { .core-center-view .scroll-content {
display: flex!important; display: flex!important;

View File

@ -81,7 +81,7 @@ core-ion-tab.show-tab {
} }
.ios { .ios {
@include core-ion-tabs-statusbar-padding($toolbar-ios-height + 15, $toolbar-ios-padding, $content-ios-padding, $cordova-ios-statusbar-padding, $cordova-ios-statusbar-padding-modal-max-width, true); @include core-ion-tabs-statusbar-padding($toolbar-ios-height, $toolbar-ios-padding, $content-ios-padding, $cordova-ios-statusbar-padding, $cordova-ios-statusbar-padding-modal-max-width, true);
} }
.md { .md {

View File

@ -9,7 +9,7 @@ core-loading {
} }
.core-loading-content { .core-loading-content {
display: unset; display: inline;
padding-bottom: 1px; /* This makes height be real */ padding-bottom: 1px; /* This makes height be real */
} }
@ -21,7 +21,7 @@ core-loading {
.scroll-content > core-loading, .scroll-content > core-loading,
ion-content > .scroll-content > core-loading, ion-content > .scroll-content > core-loading,
.core-loading-center { .core-loading-center {
position: unset !important; position: static !important;
} }
.scroll-content > core-loading, .scroll-content > core-loading,

View File

@ -23,7 +23,7 @@
<div [hidden]="rteEnabled"> <div [hidden]="rteEnabled">
<ion-textarea #textarea class="core-textarea" [placeholder]="placeholder" [attr.name]="name" ngControl="control" (ionChange)="onChange($event)"></ion-textarea> <ion-textarea #textarea class="core-textarea" [placeholder]="placeholder" [attr.name]="name" ngControl="control" (ionChange)="onChange($event)"></ion-textarea>
<div class="core-rte-toolbar"> <div class="core-rte-toolbar" [hidden]="!editorSupported">
<div #decorate class="core-rte-buttons"> <div #decorate class="core-rte-buttons">
<button tappable (click)="toggleEditor($event)"><core-icon name="fa-pencil-square-o"></core-icon> {{ 'core.vieweditor' | translate }}</button> <button tappable (click)="toggleEditor($event)"><core-icon name="fa-pencil-square-o"></core-icon> {{ 'core.vieweditor' | translate }}</button>
</div> </div>

View File

@ -103,6 +103,7 @@ core-rich-text-editor {
border-right: 1px solid $gray-dark; border-right: 1px solid $gray-dark;
border-bottom: 1px solid $gray-dark; border-bottom: 1px solid $gray-dark;
flex-grow: 1; flex-grow: 1;
margin: 0;
} }
} }
} }

View File

@ -63,6 +63,7 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy
protected valueChangeSubscription: Subscription; protected valueChangeSubscription: Subscription;
rteEnabled = false; rteEnabled = false;
editorSupported = true;
constructor(private domUtils: CoreDomUtilsProvider, private keyboard: Keyboard, private urlUtils: CoreUrlUtilsProvider, constructor(private domUtils: CoreDomUtilsProvider, private keyboard: Keyboard, private urlUtils: CoreUrlUtilsProvider,
private sitesProvider: CoreSitesProvider, private filepoolProvider: CoreFilepoolProvider, private sitesProvider: CoreSitesProvider, private filepoolProvider: CoreFilepoolProvider,
@ -79,6 +80,8 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy
this.rteEnabled = !!enabled; this.rteEnabled = !!enabled;
}); });
this.editorSupported = this.domUtils.isRichTextEditorSupported();
// Setup the editor. // Setup the editor.
this.editorElement = this.editor.nativeElement as HTMLDivElement; this.editorElement = this.editor.nativeElement as HTMLDivElement;
this.editorElement.innerHTML = this.control.value; this.editorElement.innerHTML = this.control.value;
@ -169,11 +172,12 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy
while (element.parentNode && element.parentNode.tagName != 'ION-CONTENT') { while (element.parentNode && element.parentNode.tagName != 'ION-CONTENT') {
const parent = element.parentNode; const parent = element.parentNode;
if (element.tagName && element.tagName != 'CORE-LOADING') { if (element.tagName && element.tagName != 'CORE-LOADING') {
parent.childNodes.forEach((child) => { for (let x = 0; x < parent.childNodes.length; x++) {
const child = parent.childNodes[x];
if (child.tagName && child != element) { if (child.tagName && child != element) {
height += this.domUtils.getElementHeight(child, false, true, true); height += this.domUtils.getElementHeight(child, false, true, true);
} }
}); }
} }
element = parent; element = parent;
} }
@ -368,8 +372,8 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy
} }
setTimeout(() => { setTimeout(() => {
this.keyboard.show(); this.keyboard.show();
}, 1); });
}, 1); });
} }
/** /**
@ -445,6 +449,17 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy
$event.preventDefault(); $event.preventDefault();
$event.stopPropagation(); $event.stopPropagation();
document.execCommand(command, false, parameters); document.execCommand(command, false, parameters);
setTimeout(() => {
if (this.rteEnabled) {
this.editorElement.focus();
} else {
this.textarea.setFocus();
}
setTimeout(() => {
this.keyboard.show();
});
});
} }
/** /**

View File

@ -18,6 +18,14 @@
font-size: 1.6rem; font-size: 1.6rem;
border: 0; border: 0;
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
word-wrap: break-word;
display: block;
}
&[aria-selected=true] { &[aria-selected=true] {
color: $core-top-tabs-color-active !important; color: $core-top-tabs-color-active !important;
border: 0 !important; border: 0 !important;

View File

@ -2,7 +2,7 @@
<core-dynamic-component [component]="courseFormatComponent" [data]="data"> <core-dynamic-component [component]="courseFormatComponent" [data]="data">
<!-- Course summary. By default we only display the course progress. --> <!-- Course summary. By default we only display the course progress. -->
<core-dynamic-component [component]="courseSummaryComponent" [data]="data"> <core-dynamic-component [component]="courseSummaryComponent" [data]="data">
<ion-list no-lines *ngIf="course.imageThumb || (course.progress != null && course.progress >= 0)"> <ion-list no-lines *ngIf="course.imageThumb || (course.progress != null && course.progress >= 0)" class="core-format-progress-list">
<div *ngIf="course.imageThumb" class="core-course-thumb"> <div *ngIf="course.imageThumb" class="core-course-thumb">
<img [src]="course.imageThumb" core-external-content alt=""/> <img [src]="course.imageThumb" core-external-content alt=""/>
</div> </div>
@ -16,7 +16,7 @@
<!-- Section selector. --> <!-- Section selector. -->
<core-dynamic-component [component]="sectionSelectorComponent" [data]="data"> <core-dynamic-component [component]="sectionSelectorComponent" [data]="data">
<div text-wrap *ngIf="displaySectionSelector && sections && sections.length" no-padding class="clearfix"> <div text-wrap *ngIf="displaySectionSelector && sections && sections.length" no-padding class="clearfix">
<button float-start ion-button (click)="showSectionSelector($event)" clear class="core-button-select"> <button float-start ion-button (click)="showSectionSelector($event)" clear class="core-button-select button-no-uppercase">
{{selectedSection && (selectedSection.formattedName || selectedSection.name) || 'core.course.sections' | translate }} {{selectedSection && (selectedSection.formattedName || selectedSection.name) || 'core.course.sections' | translate }}
<ion-icon name="arrow-dropdown" ios="md-arrow-dropdown"></ion-icon> <ion-icon name="arrow-dropdown" ios="md-arrow-dropdown"></ion-icon>
</button> </button>

View File

@ -6,6 +6,11 @@ ion-badge.core-course-download-section-progress {
} }
core-course-format { core-course-format {
.core-format-progress-list {
margin-bottom: 0;
}
.core-course-thumb { .core-course-thumb {
height: 150px; height: 150px;
width: 100%; width: 100%;

View File

@ -19,7 +19,7 @@
</ion-refresher> </ion-refresher>
<core-loading [hideUntil]="coursesLoaded"> <core-loading [hideUntil]="coursesLoaded">
<ion-searchbar *ngIf="showFilter" [(ngModel)]="filter" (ionInput)="filterChanged($event)" (ionCancel)="filterChanged()" [placeholder]="'core.courses.filtermycourses' | translate"> <ion-searchbar #searchbar *ngIf="showFilter" [(ngModel)]="filter" (ionInput)="filterChanged($event)" (ionCancel)="filterChanged()" [placeholder]="'core.courses.filtermycourses' | translate">
</ion-searchbar> </ion-searchbar>
<ion-grid no-padding> <ion-grid no-padding>
<ion-row no-padding> <ion-row no-padding>

View File

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { Component, OnDestroy } from '@angular/core'; import { Component, OnDestroy, ViewChild } from '@angular/core';
import { IonicPage, NavController } from 'ionic-angular'; import { IonicPage, Searchbar, NavController } from 'ionic-angular';
import { CoreEventsProvider } from '@providers/events'; import { CoreEventsProvider } from '@providers/events';
import { CoreSitesProvider } from '@providers/sites'; import { CoreSitesProvider } from '@providers/sites';
import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreDomUtilsProvider } from '@providers/utils/dom';
@ -31,6 +31,8 @@ import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delega
templateUrl: 'my-courses.html', templateUrl: 'my-courses.html',
}) })
export class CoreCoursesMyCoursesPage implements OnDestroy { export class CoreCoursesMyCoursesPage implements OnDestroy {
@ViewChild('searchbar') searchbar: Searchbar;
courses: any[]; courses: any[];
filteredCourses: any[]; filteredCourses: any[];
searchEnabled: boolean; searchEnabled: boolean;
@ -153,6 +155,11 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
this.filter = ''; this.filter = '';
this.showFilter = !this.showFilter; this.showFilter = !this.showFilter;
this.filteredCourses = this.courses; this.filteredCourses = this.courses;
if (this.showFilter) {
setTimeout(() => {
this.searchbar.setFocus();
});
}
} }
/** /**

View File

@ -80,7 +80,7 @@
</div> </div>
</div> </div>
<!-- Filter courses. --> <!-- Filter courses. -->
<ion-searchbar *ngIf="showFilter" [(ngModel)]="courses.filter" (ionInput)="filterChanged($event)" (ionCancel)="filterChanged()" [placeholder]="'core.courses.filtermycourses' | translate"> <ion-searchbar #searchbar *ngIf="showFilter" [(ngModel)]="courses.filter" (ionInput)="filterChanged($event)" (ionCancel)="filterChanged()" [placeholder]="'core.courses.filtermycourses' | translate">
</ion-searchbar> </ion-searchbar>
<!-- List of courses. --> <!-- List of courses. -->
<div> <div>

View File

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { Component, OnDestroy } from '@angular/core'; import { Component, OnDestroy, ViewChild } from '@angular/core';
import { IonicPage, NavController } from 'ionic-angular'; import { IonicPage, Searchbar, NavController } from 'ionic-angular';
import { CoreEventsProvider } from '@providers/events'; import { CoreEventsProvider } from '@providers/events';
import { CoreSitesProvider } from '@providers/sites'; import { CoreSitesProvider } from '@providers/sites';
import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreDomUtilsProvider } from '@providers/utils/dom';
@ -34,6 +34,8 @@ import * as moment from 'moment';
templateUrl: 'my-overview.html', templateUrl: 'my-overview.html',
}) })
export class CoreCoursesMyOverviewPage implements OnDestroy { export class CoreCoursesMyOverviewPage implements OnDestroy {
@ViewChild('searchbar') searchbar: Searchbar;
firstSelectedTab: number; firstSelectedTab: number;
siteHomeEnabled: boolean; siteHomeEnabled: boolean;
tabsReady = false; tabsReady = false;
@ -245,6 +247,11 @@ export class CoreCoursesMyOverviewPage implements OnDestroy {
this.showFilter = !this.showFilter; this.showFilter = !this.showFilter;
this.courses.filter = ''; this.courses.filter = '';
this.filteredCourses = this.courses[this.courses.selected]; this.filteredCourses = this.courses[this.courses.selected];
if (this.showFilter) {
setTimeout(() => {
this.searchbar.setFocus();
});
}
} }
/** /**

View File

@ -19,7 +19,7 @@
"displayformat": "Display format", "displayformat": "Display format",
"enabledownloadsection": "Enable download sections", "enabledownloadsection": "Enable download sections",
"enablerichtexteditor": "Enable text editor", "enablerichtexteditor": "Enable text editor",
"enablerichtexteditordescription": "If enabled, a text editor will be available when entering content.", "enablerichtexteditordescription": "If enabled, a rich text editor will be shown when entering content. If disabled, plain text editor will be shown. You can toggle between both while editing.",
"enablesyncwifi": "Allow sync only when on Wi-Fi", "enablesyncwifi": "Allow sync only when on Wi-Fi",
"errordeletesitefiles": "Error deleting site files.", "errordeletesitefiles": "Error deleting site files.",
"errorsyncsite": "Error synchronising site data. Please check your Internet connection and try again.", "errorsyncsite": "Error synchronising site data. Please check your Internet connection and try again.",

View File

@ -546,8 +546,7 @@ export class CoreDomUtilsProvider {
* @return {boolean} Whether it's supported. * @return {boolean} Whether it's supported.
*/ */
isRichTextEditorSupported(): boolean { isRichTextEditorSupported(): boolean {
// Disabled just for iOS. return true;
return !this.platform.is('ios');
} }
/** /**

View File

@ -58,7 +58,7 @@ $core-course-image-background: #81ecec, #74b9ff, #a29bfe, #dfe6e9, #00b894, #098
// To view all the possible Ionic variables, see: // To view all the possible Ionic variables, see:
// http://ionicframework.com/docs/theming/overriding-ionic-variables/ // http://ionicframework.com/docs/theming/overriding-ionic-variables/
$toolbar-background: $orange; $toolbar-background: $core-color;
$content-padding: 10px; $content-padding: 10px;
@ -141,7 +141,7 @@ $loading-ios-spinner-color: $core-color;
$spinner-ios-ios-color: $core-color; $spinner-ios-ios-color: $core-color;
$tabs-ios-tab-color-inactive: $tabs-tab-color-inactive; $tabs-ios-tab-color-inactive: $tabs-tab-color-inactive;
$button-ios-outline-background-color: $white; $button-ios-outline-background-color: $white;
$toolbar-ios-height: 44px + 15;
// App Material Design Variables // App Material Design Variables
// -------------------------------------------------- // --------------------------------------------------