forked from EVOgeek/Vmeda.Online
commit
1393dbda04
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(',')
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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(() => {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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%;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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.",
|
||||||
|
|
|
@ -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');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue