From 6fa19efcd5fb6aacc0bb18dee43e5ece724c62ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Mon, 18 Jun 2018 16:26:40 +0200 Subject: [PATCH 1/3] MOBILE-2430 tabs: Fix status bar top padding --- src/app/app.ios.scss | 12 ++++++++++++ src/components/ion-tabs/ion-tabs.scss | 2 +- .../course/components/format/core-course-format.html | 2 +- src/core/course/components/format/format.scss | 5 +++++ src/theme/variables.scss | 4 ++-- 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/app/app.ios.scss b/src/app/app.ios.scss index 58b921be0..084c5f5e1 100644 --- a/src/app/app.ios.scss +++ b/src/app/app.ios.scss @@ -41,6 +41,18 @@ 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. @if ($core-text-input-ios-show-highlight) { .card-ios, .list-ios { diff --git a/src/components/ion-tabs/ion-tabs.scss b/src/components/ion-tabs/ion-tabs.scss index f08ca2a8a..1cb04e2f4 100644 --- a/src/components/ion-tabs/ion-tabs.scss +++ b/src/components/ion-tabs/ion-tabs.scss @@ -81,7 +81,7 @@ core-ion-tab.show-tab { } .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 { diff --git a/src/core/course/components/format/core-course-format.html b/src/core/course/components/format/core-course-format.html index 9471f649a..b90c2e218 100644 --- a/src/core/course/components/format/core-course-format.html +++ b/src/core/course/components/format/core-course-format.html @@ -2,7 +2,7 @@ - +
diff --git a/src/core/course/components/format/format.scss b/src/core/course/components/format/format.scss index e0fb24ce2..ac61d4803 100644 --- a/src/core/course/components/format/format.scss +++ b/src/core/course/components/format/format.scss @@ -6,6 +6,11 @@ ion-badge.core-course-download-section-progress { } core-course-format { + + .core-format-progress-list { + margin-bottom: 0; + } + .core-course-thumb { height: 150px; width: 100%; diff --git a/src/theme/variables.scss b/src/theme/variables.scss index 047cbaf22..32c26f543 100644 --- a/src/theme/variables.scss +++ b/src/theme/variables.scss @@ -58,7 +58,7 @@ $core-course-image-background: #81ecec, #74b9ff, #a29bfe, #dfe6e9, #00b894, #098 // To view all the possible Ionic variables, see: // http://ionicframework.com/docs/theming/overriding-ionic-variables/ -$toolbar-background: $orange; +$toolbar-background: $core-color; $content-padding: 10px; @@ -141,7 +141,7 @@ $loading-ios-spinner-color: $core-color; $spinner-ios-ios-color: $core-color; $tabs-ios-tab-color-inactive: $tabs-tab-color-inactive; $button-ios-outline-background-color: $white; - +$toolbar-ios-height: 44px + 15; // App Material Design Variables // -------------------------------------------------- From 757882428f273b8b9587608d23ed16fb37b398db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Mon, 18 Jun 2018 16:24:27 +0200 Subject: [PATCH 2/3] MOBILE-2430 rte: Enable RTE for iOS --- .../feedback/comments/component/comments.ts | 22 ++------- .../feedback/comments/providers/handler.ts | 20 +++----- .../onlinetext/component/onlinetext.ts | 33 ++++--------- .../onlinetext/providers/handler.ts | 27 +++++------ .../data/fields/textarea/providers/handler.ts | 46 ++++++++----------- src/addon/mod/forum/components/post/post.ts | 38 +++++++-------- .../pages/new-discussion/new-discussion.ts | 32 ++++++------- src/addon/mod/glossary/pages/edit/edit.ts | 38 +++++++-------- src/addon/mod/lesson/pages/player/player.ts | 6 +-- src/addon/mod/lesson/providers/helper.ts | 17 ++----- src/addon/mod/wiki/pages/edit/edit.ts | 22 ++------- .../assessment-strategy.ts | 14 +----- .../workshop/pages/assessment/assessment.ts | 21 ++++----- .../pages/edit-submission/edit-submission.ts | 27 +++++------ .../workshop/pages/submission/submission.ts | 19 +++----- src/addon/qtype/essay/providers/handler.ts | 11 ++--- .../core-rich-text-editor.html | 2 +- .../rich-text-editor/rich-text-editor.scss | 1 + .../rich-text-editor/rich-text-editor.ts | 23 ++++++++-- src/core/settings/lang/en.json | 2 +- src/providers/utils/dom.ts | 3 +- 21 files changed, 169 insertions(+), 255 deletions(-) diff --git a/src/addon/mod/assign/feedback/comments/component/comments.ts b/src/addon/mod/assign/feedback/comments/component/comments.ts index 9d1715c1c..9e28120e3 100644 --- a/src/addon/mod/assign/feedback/comments/component/comments.ts +++ b/src/addon/mod/assign/feedback/comments/component/comments.ts @@ -53,22 +53,7 @@ export class AddonModAssignFeedbackCommentsComponent extends AddonModAssignFeedb * Component being initialized. */ ngOnInit(): void { - let promise, - 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.getText().then((text) => { this.text = text; @@ -113,10 +98,9 @@ export class AddonModAssignFeedbackCommentsComponent extends AddonModAssignFeedb /** * Get the text for the plugin. * - * @param {boolean} rteEnabled Whether Rich Text Editor is enabled. * @return {Promise} Promise resolved with the text. */ - protected getText(rteEnabled: boolean): Promise { + protected getText(): Promise { // Check if the user already modified the comment. return this.feedbackDelegate.getPluginDraftData(this.assign.id, this.userId, this.plugin).then((draft) => { if (draft) { @@ -140,7 +124,7 @@ export class AddonModAssignFeedbackCommentsComponent extends AddonModAssignFeedb // No offline data found, return online text. this.isSent = true; - return this.assignProvider.getSubmissionPluginText(this.plugin, this.edit && !rteEnabled); + return this.assignProvider.getSubmissionPluginText(this.plugin); }); } }); diff --git a/src/addon/mod/assign/feedback/comments/providers/handler.ts b/src/addon/mod/assign/feedback/comments/providers/handler.ts index 713167bc0..108fef23a 100644 --- a/src/addon/mod/assign/feedback/comments/providers/handler.ts +++ b/src/addon/mod/assign/feedback/comments/providers/handler.ts @@ -15,7 +15,6 @@ import { Injectable, Injector } from '@angular/core'; import { CoreSitesProvider } from '@providers/sites'; -import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { AddonModAssignProvider } from '../../../providers/assign'; 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. - constructor(private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider, - private textUtils: CoreTextUtilsProvider, private assignProvider: AddonModAssignProvider, - private assignOfflineProvider: AddonModAssignOfflineProvider) { } + constructor(private sitesProvider: CoreSitesProvider, private textUtils: CoreTextUtilsProvider, + private assignProvider: AddonModAssignProvider, private assignOfflineProvider: AddonModAssignOfflineProvider) { } /** * 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. - return this.domUtils.isRichTextEditorEnabled().then((enabled) => { - return this.assignProvider.getSubmissionPluginText(plugin, !enabled); - }); + return this.assignProvider.getSubmissionPluginText(plugin); }).then((initialText) => { const newText = AddonModAssignFeedbackCommentsHandler.getTextFromInputData(this.textUtils, plugin, inputData); @@ -185,14 +181,10 @@ export class AddonModAssignFeedbackCommentsHandler implements AddonModAssignFeed const draft = this.getDraft(assignId, userId, siteId); if (draft) { - return this.domUtils.isRichTextEditorEnabled().then((enabled) => { - if (!enabled) { - // Rich text editor not enabled, add some HTML to the text if needed. - draft.text = this.textUtils.formatHtmlLines(draft.text); - } + // Add some HTML to the text if needed. + draft.text = this.textUtils.formatHtmlLines(draft.text); - pluginData.assignfeedbackcomments_editor = draft; - }); + pluginData.assignfeedbackcomments_editor = draft; } } diff --git a/src/addon/mod/assign/submission/onlinetext/component/onlinetext.ts b/src/addon/mod/assign/submission/onlinetext/component/onlinetext.ts index 8e9e98633..11ab6f2d0 100644 --- a/src/addon/mod/assign/submission/onlinetext/component/onlinetext.ts +++ b/src/addon/mod/assign/submission/onlinetext/component/onlinetext.ts @@ -50,31 +50,16 @@ export class AddonModAssignSubmissionOnlineTextComponent extends AddonModAssignS * Component being initialized. */ ngOnInit(): void { - let promise, - rteEnabled; + // Get the text. Check if we have anything offline. + 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. - 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; - - // 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); - }); + // No offline data found, return online text. + return this.assignProvider.getSubmissionPluginText(this.plugin); }).then((text) => { // We receive them as strings, convert to int. this.configs.wordlimit = parseInt(this.configs.wordlimit, 10); diff --git a/src/addon/mod/assign/submission/onlinetext/providers/handler.ts b/src/addon/mod/assign/submission/onlinetext/providers/handler.ts index 4f06dc018..718a13f51 100644 --- a/src/addon/mod/assign/submission/onlinetext/providers/handler.ts +++ b/src/addon/mod/assign/submission/onlinetext/providers/handler.ts @@ -16,7 +16,6 @@ import { Injectable, Injector } from '@angular/core'; import { CoreSitesProvider } from '@providers/sites'; import { CoreWSProvider } from '@providers/ws'; -import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { AddonModAssignProvider } from '../../../providers/assign'; import { AddonModAssignOfflineProvider } from '../../../providers/assign-offline'; @@ -33,9 +32,8 @@ export class AddonModAssignSubmissionOnlineTextHandler implements AddonModAssign type = 'onlinetext'; constructor(private sitesProvider: CoreSitesProvider, private wsProvider: CoreWSProvider, - private domUtils: CoreDomUtilsProvider, private textUtils: CoreTextUtilsProvider, - private assignProvider: AddonModAssignProvider, private assignOfflineProvider: AddonModAssignOfflineProvider, - private assignHelper: AddonModAssignHelperProvider) { } + private textUtils: CoreTextUtilsProvider, private assignProvider: AddonModAssignProvider, + private assignOfflineProvider: AddonModAssignOfflineProvider, private assignHelper: AddonModAssignHelperProvider) { } /** * 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, userId?: number, siteId?: string): void | Promise { - return this.domUtils.isRichTextEditorEnabled().then((enabled) => { - 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); - } + let text = this.getTextToSubmit(plugin, inputData); - pluginData.onlinetext_editor = { - text: text, - format: 1, - itemid: 0 // Can't add new files yet, so we use a fake itemid. - }; - }); + // Add some HTML to the text if needed. + text = this.textUtils.formatHtmlLines(text); + + pluginData.onlinetext_editor = { + text: text, + format: 1, + itemid: 0 // Can't add new files yet, so we use a fake itemid. + }; } /** diff --git a/src/addon/mod/data/fields/textarea/providers/handler.ts b/src/addon/mod/data/fields/textarea/providers/handler.ts index 0a5829698..8ffcdcf4b 100644 --- a/src/addon/mod/data/fields/textarea/providers/handler.ts +++ b/src/addon/mod/data/fields/textarea/providers/handler.ts @@ -15,7 +15,6 @@ import { Injector, Injectable } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { AddonModDataFieldTextHandler } from '../../text/providers/handler'; import { AddonModDataFieldTextareaComponent } from '../component/textarea'; -import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreTextUtilsProvider } from '@providers/utils/text'; /** @@ -26,8 +25,7 @@ export class AddonModDataFieldTextareaHandler extends AddonModDataFieldTextHandl name = 'AddonModDataFieldTextareaHandler'; type = 'textarea'; - constructor(protected translate: TranslateService, private textUtils: CoreTextUtilsProvider, - private domUtils: CoreDomUtilsProvider) { + constructor(protected translate: TranslateService, private textUtils: CoreTextUtilsProvider) { super(translate); } @@ -54,31 +52,27 @@ export class AddonModDataFieldTextareaHandler extends AddonModDataFieldTextHandl const fieldName = 'f_' + field.id; if (inputData[fieldName]) { - return this.domUtils.isRichTextEditorEnabled().then((enabled) => { - const files = this.getFieldEditFiles(field, inputData, originalFieldData); - let text = this.textUtils.restorePluginfileUrls(inputData[fieldName], files); + const files = this.getFieldEditFiles(field, inputData, originalFieldData); + let text = this.textUtils.restorePluginfileUrls(inputData[fieldName], files); - if (!enabled) { - // Rich text editor not enabled, add some HTML to the text if needed. - text = this.textUtils.formatHtmlLines(text); + // Add some HTML to the text if needed. + 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; diff --git a/src/addon/mod/forum/components/post/post.ts b/src/addon/mod/forum/components/post/post.ts index 7bee5df7c..39c84c2ea 100644 --- a/src/addon/mod/forum/components/post/post.ts +++ b/src/addon/mod/forum/components/post/post.ts @@ -182,29 +182,29 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy { const files = this.replyData.files || []; const options: any = {}; const modal = this.domUtils.showModalLoading('core.sending', true); + let promise; - // Check if rich text editor is enabled or not. - this.domUtils.isRichTextEditorEnabled().then((enabled) => { - if (!enabled) { - // Rich text editor not enabled, add some HTML to the message if needed. - message = this.textUtils.formatHtmlLines(message); - } + // Add some HTML to the message if needed. + message = this.textUtils.formatHtmlLines(message); - // Upload attachments first if any. - if (files.length) { - return this.forumHelper.uploadOrStoreReplyFiles(this.forum.id, replyingTo, files, false).catch((error) => { - // Cannot upload them in online, save them in offline. - if (!this.forum.id) { - // Cannot store them in offline without the forum ID. Reject. - return Promise.reject(error); - } + // Upload attachments first if any. + if (files.length) { + promise = this.forumHelper.uploadOrStoreReplyFiles(this.forum.id, replyingTo, files, false).catch((error) => { + // Cannot upload them in online, save them in offline. + if (!this.forum.id) { + // Cannot store them in offline without the forum ID. Reject. + return Promise.reject(error); + } - saveOffline = true; + saveOffline = true; - return this.forumHelper.uploadOrStoreReplyFiles(this.forum.id, replyingTo, files, true); - }); - } - }).then((attach) => { + return this.forumHelper.uploadOrStoreReplyFiles(this.forum.id, replyingTo, files, true); + }); + } else { + promise = Promise.resolve(); + } + + promise.then((attach) => { if (attach) { options.attachmentsid = attach; } diff --git a/src/addon/mod/forum/pages/new-discussion/new-discussion.ts b/src/addon/mod/forum/pages/new-discussion/new-discussion.ts index 2ab73fc2b..abc39de32 100644 --- a/src/addon/mod/forum/pages/new-discussion/new-discussion.ts +++ b/src/addon/mod/forum/pages/new-discussion/new-discussion.ts @@ -423,25 +423,25 @@ export class AddonModForumNewDiscussionPage implements OnDestroy { } const modal = this.domUtils.showModalLoading('core.sending', true); + let promise; - // Check if rich text editor is enabled or not. - this.domUtils.isRichTextEditorEnabled().then((enabled) => { - if (!enabled) { - // Rich text editor not enabled, add some HTML to the message if needed. - message = this.textUtils.formatHtmlLines(message); - } + // Add some HTML to the message if needed. + message = this.textUtils.formatHtmlLines(message); - // Upload attachments first if any. - if (attachments.length) { - return this.forumHelper.uploadOrStoreNewDiscussionFiles(this.forumId, discTimecreated, attachments, false) - .catch(() => { - // Cannot upload them in online, save them in offline. - saveOffline = true; + // Upload attachments first if any. + if (attachments.length) { + promise = this.forumHelper.uploadOrStoreNewDiscussionFiles(this.forumId, discTimecreated, attachments, false) + .catch(() => { + // Cannot upload them in online, save them in offline. + saveOffline = true; - return this.forumHelper.uploadOrStoreNewDiscussionFiles(this.forumId, discTimecreated, attachments, true); - }); - } - }).then((attach) => { + return this.forumHelper.uploadOrStoreNewDiscussionFiles(this.forumId, discTimecreated, attachments, true); + }); + } else { + promise = Promise.resolve(); + } + + promise.then((attach) => { if (attach) { options.attachmentsid = attach; } diff --git a/src/addon/mod/glossary/pages/edit/edit.ts b/src/addon/mod/glossary/pages/edit/edit.ts index ab1bf46eb..f685feefd 100644 --- a/src/addon/mod/glossary/pages/edit/edit.ts +++ b/src/addon/mod/glossary/pages/edit/edit.ts @@ -159,9 +159,10 @@ export class AddonModGlossaryEditPage implements OnInit { * Save the entry. */ save(): void { - let definition = this.entry.definition; + let definition = this.entry.definition, + saveOffline = false, + promise; const timecreated = this.entry.timecreated || Date.now(); - let saveOffline = false; if (!this.entry.concept || !definition) { 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); - // Check if rich text editor is enabled or not. - this.domUtils.isRichTextEditorEnabled().then((enabled) => { - if (!enabled) { - // Rich text editor not enabled, add some HTML to the definition if needed. - definition = this.textUtils.formatHtmlLines(definition); - } + // Add some HTML to the definition if needed. + definition = this.textUtils.formatHtmlLines(definition); - // Upload attachments first if any. - if (this.attachments.length > 0) { - return this.glossaryHelper.uploadOrStoreFiles(this.glossary.id, this.entry.concept, timecreated, this.attachments, - false).catch(() => { - // Cannot upload them in online, save them in offline. - saveOffline = true; + // Upload attachments first if any. + if (this.attachments.length > 0) { + promise = this.glossaryHelper.uploadOrStoreFiles(this.glossary.id, this.entry.concept, timecreated, this.attachments, + false).catch(() => { + // Cannot upload them in online, save them in offline. + saveOffline = true; - return this.glossaryHelper.uploadOrStoreFiles(this.glossary.id, this.entry.concept, timecreated, - this.attachments, true); - }); - } - }).then((attach) => { + return this.glossaryHelper.uploadOrStoreFiles(this.glossary.id, this.entry.concept, timecreated, + this.attachments, true); + }); + } else { + promise = Promise.resolve(); + } + + promise.then((attach) => { const options: any = { aliases: this.options.aliases, categories: this.options.categories.join(',') diff --git a/src/addon/mod/lesson/pages/player/player.ts b/src/addon/mod/lesson/pages/player/player.ts index 4b823d33e..137256b46 100644 --- a/src/addon/mod/lesson/pages/player/player.ts +++ b/src/addon/mod/lesson/pages/player/player.ts @@ -611,9 +611,9 @@ export class AddonModLessonPlayerPage implements OnInit, OnDestroy { this.loaded = false; // Use getRawValue to include disabled values. - this.lessonHelper.prepareQuestionData(this.question, this.questionForm.getRawValue()).then((data) => { - return this.processPage(data); - }).finally(() => { + const data = this.lessonHelper.prepareQuestionData(this.question, this.questionForm.getRawValue()); + + this.processPage(data).finally(() => { this.loaded = true; }); } diff --git a/src/addon/mod/lesson/providers/helper.ts b/src/addon/mod/lesson/providers/helper.ts index 617462a49..d22bbb157 100644 --- a/src/addon/mod/lesson/providers/helper.ts +++ b/src/addon/mod/lesson/providers/helper.ts @@ -452,19 +452,12 @@ export class AddonModLessonHelperProvider { * * @param {any} question Question to prepare. * @param {any} data Data to prepare. - * @return {Promise} Promise resolved with the data to send when done. + * @return {any} Data to send. */ - prepareQuestionData(question: any, data: any): Promise { + prepareQuestionData(question: any, data: any): any { if (question.template == 'essay' && question.textarea) { - // The answer might need formatting. Check if rich text editor is enabled or not. - return this.domUtils.isRichTextEditorEnabled().then((enabled) => { - 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; - }); + // Add some HTML to the answer if needed. + data[question.textarea.property] = this.textUtils.formatHtmlLines(data[question.textarea.property]); } else if (question.template == 'multichoice' && question.multi) { // Only send the options with value set to true. for (const name in data) { @@ -474,7 +467,7 @@ export class AddonModLessonHelperProvider { } } - return Promise.resolve(data); + return data; } /** diff --git a/src/addon/mod/wiki/pages/edit/edit.ts b/src/addon/mod/wiki/pages/edit/edit.ts index 0a7dfdc14..3d56004ff 100644 --- a/src/addon/mod/wiki/pages/edit/edit.ts +++ b/src/addon/mod/wiki/pages/edit/edit.ts @@ -58,7 +58,6 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy { 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 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 originalContent: string; // The original page content. protected version: number; // Page version. @@ -151,15 +150,8 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy { // Wait for sync to be over (if any). return this.wikiSync.waitForSync(this.blockId); }).then(() => { - // Check if rich text editor is enabled. - return this.domUtils.isRichTextEditorEnabled(); - }).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); - } + // Get subwiki files, needed to replace URLs for rich text editor. + return this.wikiProvider.getSubwikiFiles(this.wikiId, this.groupId, this.userId); }).then((files) => { this.subwikiFiles = files; @@ -167,8 +159,7 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy { return this.wikiProvider.getPageForEditing(this.pageId, this.section); }).then((editContents) => { // Get the original page contents, treating file URLs if needed. - const content = this.rteEnabled ? this.textUtils.replacePluginfileUrls(editContents.content, this.subwikiFiles) : - editContents.content; + const content = this.textUtils.replacePluginfileUrls(editContents.content, this.subwikiFiles); this.contentControl.setValue(content); this.originalContent = content; @@ -411,11 +402,8 @@ export class AddonModWikiEditPage implements OnInit, OnDestroy { let promise, text = values.text; - if (this.rteEnabled) { - text = this.textUtils.restorePluginfileUrls(text, this.subwikiFiles); - } else { - text = this.textUtils.formatHtmlLines(text); - } + text = this.textUtils.restorePluginfileUrls(text, this.subwikiFiles); + text = this.textUtils.formatHtmlLines(text); if (this.editing) { // Edit existing page. diff --git a/src/addon/mod/workshop/components/assessment-strategy/assessment-strategy.ts b/src/addon/mod/workshop/components/assessment-strategy/assessment-strategy.ts index 89652f0db..1516b9c60 100644 --- a/src/addon/mod/workshop/components/assessment-strategy/assessment-strategy.ts +++ b/src/addon/mod/workshop/components/assessment-strategy/assessment-strategy.ts @@ -64,7 +64,6 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit { weights: any[]; weight: number; - protected rteEnabled: boolean; protected obsInvalidated: any; protected hasOffline: boolean; protected originalData = { @@ -117,24 +116,13 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit { } } - let promise; - // Check if rich text editor is enabled. if (this.edit) { // Block the workshop. 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.rteEnabled = enabled; - - return this.load(); - }).then(() => { + this.load().then(() => { this.obsInvalidated = this.eventsProvider.on(AddonModWorkshopProvider.ASSESSMENT_INVALIDATED, this.load.bind(this), this.sitesProvider.getCurrentSiteId()); }).finally(() => { diff --git a/src/addon/mod/workshop/pages/assessment/assessment.ts b/src/addon/mod/workshop/pages/assessment/assessment.ts index 208734b40..22c1b2bde 100644 --- a/src/addon/mod/workshop/pages/assessment/assessment.ts +++ b/src/addon/mod/workshop/pages/assessment/assessment.ts @@ -331,21 +331,16 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy { * @return {Promise} Resolved when done. */ protected sendEvaluation(): Promise { - 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. - return this.domUtils.isRichTextEditorEnabled().then((rteEnabled) => { - const inputData = this.evaluateForm.value; - 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); - } + inputData.grade = inputData.grade >= 0 ? inputData.grade : ''; + // Add some HTML to the message if needed. + inputData.text = this.textUtils.formatHtmlLines(inputData.text); - // Try to send it to server. - return this.workshopProvider.evaluateAssessment(this.workshopId, this.assessmentId, this.courseId, inputData.text, - inputData.weight, inputData.grade); - }).then(() => { + // Try to send it to server. + return this.workshopProvider.evaluateAssessment(this.workshopId, this.assessmentId, this.courseId, inputData.text, + inputData.weight, inputData.grade).then(() => { const data = { workshopId: this.workshopId, assessmentId: this.assessmentId, diff --git a/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts b/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts index 66fc4d69a..6afeff9a8 100644 --- a/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts +++ b/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts @@ -312,25 +312,20 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { const modal = this.domUtils.showModalLoading('core.sending', true), submissionId = this.submission.id; - // Check if rich text editor is enabled or not. - return this.domUtils.isRichTextEditorEnabled().then((rteEnabled) => { - if (!rteEnabled) { - // Rich text editor not enabled, add some HTML to the message if needed. - inputData.content = this.textUtils.formatHtmlLines(inputData.content); - } + // Add some HTML to the message if needed. + inputData.content = this.textUtils.formatHtmlLines(inputData.content); - // Upload attachments first if any. - allowOffline = !inputData.attachmentfiles.length; + // Upload attachments first if any. + allowOffline = !inputData.attachmentfiles.length; - return this.workshopHelper.uploadOrStoreSubmissionFiles(this.workshopId, this.submission.id, inputData.attachmentfiles, - this.editing, saveOffline).catch(() => { - // Cannot upload them in online, save them in offline. - saveOffline = true; - allowOffline = true; + return this.workshopHelper.uploadOrStoreSubmissionFiles(this.workshopId, this.submission.id, inputData.attachmentfiles, + this.editing, saveOffline).catch(() => { + // Cannot upload them in online, save them in offline. + saveOffline = true; + allowOffline = true; - return this.workshopHelper.uploadOrStoreSubmissionFiles(this.workshopId, this.submission.id, - inputData.attachmentfiles, this.editing, saveOffline); - }); + return this.workshopHelper.uploadOrStoreSubmissionFiles(this.workshopId, this.submission.id, + inputData.attachmentfiles, this.editing, saveOffline); }).then((attachmentsId) => { if (this.editing) { if (saveOffline) { diff --git a/src/addon/mod/workshop/pages/submission/submission.ts b/src/addon/mod/workshop/pages/submission/submission.ts index 5e8b24bc4..6fba624d2 100644 --- a/src/addon/mod/workshop/pages/submission/submission.ts +++ b/src/addon/mod/workshop/pages/submission/submission.ts @@ -430,20 +430,15 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { protected sendEvaluation(): Promise { const modal = this.domUtils.showModalLoading('core.sending', true); - // Check if rich text editor is enabled or not. - return this.domUtils.isRichTextEditorEnabled().then((rteEnabled) => { - const inputData = this.feedbackForm.value; + const inputData = this.feedbackForm.value; - 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); - } + inputData.grade = inputData.grade >= 0 ? inputData.grade : ''; + // Add some HTML to the message if needed. + inputData.text = this.textUtils.formatHtmlLines(inputData.text); - // Try to send it to server. - return this.workshopProvider.evaluateSubmission(this.workshopId, this.submissionId, this.courseId, inputData.text, - inputData.published, inputData.grade); - }).then(() => { + // Try to send it to server. + return this.workshopProvider.evaluateSubmission(this.workshopId, this.submissionId, this.courseId, inputData.text, + inputData.published, inputData.grade).then(() => { const data = { workshopId: this.workshopId, cmId: this.module.cmid, diff --git a/src/addon/qtype/essay/providers/handler.ts b/src/addon/qtype/essay/providers/handler.ts index ead384f00..b75ad9c68 100644 --- a/src/addon/qtype/essay/providers/handler.ts +++ b/src/addon/qtype/essay/providers/handler.ts @@ -14,7 +14,6 @@ // limitations under the License. import { Injectable, Injector } from '@angular/core'; -import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreUtilsProvider } from '@providers/utils/utils'; 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. 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. @@ -148,12 +147,8 @@ export class AddonQtypeEssayHandler implements CoreQuestionHandler { const textarea = this.div.querySelector('textarea[name*=_answer]'); if (textarea && typeof answers[textarea.name] != 'undefined') { - return this.domUtils.isRichTextEditorEnabled().then((enabled) => { - if (!enabled) { - // Rich text editor not enabled, add some HTML to the text if needed. - answers[textarea.name] = this.textUtils.formatHtmlLines(answers[textarea.name]); - } - }); + // Add some HTML to the text if needed. + answers[textarea.name] = this.textUtils.formatHtmlLines(answers[textarea.name]); } } } diff --git a/src/components/rich-text-editor/core-rich-text-editor.html b/src/components/rich-text-editor/core-rich-text-editor.html index 6a38e8470..69f78c45e 100644 --- a/src/components/rich-text-editor/core-rich-text-editor.html +++ b/src/components/rich-text-editor/core-rich-text-editor.html @@ -23,7 +23,7 @@
-
+
diff --git a/src/components/rich-text-editor/rich-text-editor.scss b/src/components/rich-text-editor/rich-text-editor.scss index 53e3ddd8a..075e3e00e 100644 --- a/src/components/rich-text-editor/rich-text-editor.scss +++ b/src/components/rich-text-editor/rich-text-editor.scss @@ -103,6 +103,7 @@ core-rich-text-editor { border-right: 1px solid $gray-dark; border-bottom: 1px solid $gray-dark; flex-grow: 1; + margin: 0; } } } diff --git a/src/components/rich-text-editor/rich-text-editor.ts b/src/components/rich-text-editor/rich-text-editor.ts index 39228fd5a..f4d1955ff 100644 --- a/src/components/rich-text-editor/rich-text-editor.ts +++ b/src/components/rich-text-editor/rich-text-editor.ts @@ -63,6 +63,7 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy protected valueChangeSubscription: Subscription; rteEnabled = false; + editorSupported = true; constructor(private domUtils: CoreDomUtilsProvider, private keyboard: Keyboard, private urlUtils: CoreUrlUtilsProvider, private sitesProvider: CoreSitesProvider, private filepoolProvider: CoreFilepoolProvider, @@ -79,6 +80,8 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy this.rteEnabled = !!enabled; }); + this.editorSupported = this.domUtils.isRichTextEditorSupported(); + // Setup the editor. this.editorElement = this.editor.nativeElement as HTMLDivElement; this.editorElement.innerHTML = this.control.value; @@ -169,11 +172,12 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy while (element.parentNode && element.parentNode.tagName != 'ION-CONTENT') { const parent = element.parentNode; 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) { height += this.domUtils.getElementHeight(child, false, true, true); } - }); + } } element = parent; } @@ -368,8 +372,8 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy } setTimeout(() => { this.keyboard.show(); - }, 1); - }, 1); + }); + }); } /** @@ -445,6 +449,17 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy $event.preventDefault(); $event.stopPropagation(); document.execCommand(command, false, parameters); + + setTimeout(() => { + if (this.rteEnabled) { + this.editorElement.focus(); + } else { + this.textarea.setFocus(); + } + setTimeout(() => { + this.keyboard.show(); + }); + }); } /** diff --git a/src/core/settings/lang/en.json b/src/core/settings/lang/en.json index a68e5bcf7..136a930c6 100644 --- a/src/core/settings/lang/en.json +++ b/src/core/settings/lang/en.json @@ -19,7 +19,7 @@ "displayformat": "Display format", "enabledownloadsection": "Enable download sections", "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", "errordeletesitefiles": "Error deleting site files.", "errorsyncsite": "Error synchronising site data. Please check your Internet connection and try again.", diff --git a/src/providers/utils/dom.ts b/src/providers/utils/dom.ts index 8a21c45ee..3d2ce47d6 100644 --- a/src/providers/utils/dom.ts +++ b/src/providers/utils/dom.ts @@ -546,8 +546,7 @@ export class CoreDomUtilsProvider { * @return {boolean} Whether it's supported. */ isRichTextEditorSupported(): boolean { - // Disabled just for iOS. - return !this.platform.is('ios'); + return true; } /** From f189c6e815bfb545c228f61efa9d4751cdb8c8ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Tue, 19 Jun 2018 12:29:12 +0200 Subject: [PATCH 3/3] MOBILE-2430 ux: Solve minor ux problems --- src/addon/mod/forum/pages/discussion/discussion.ts | 3 +++ src/addon/mod/lesson/pages/player/player.html | 8 ++++---- src/addon/mod/lesson/pages/player/player.scss | 6 ++++-- src/app/app.scss | 4 ++++ src/components/loading/loading.scss | 4 ++-- src/components/tabs/tabs.scss | 8 ++++++++ .../course/components/format/core-course-format.html | 2 +- src/core/courses/pages/my-courses/my-courses.html | 2 +- src/core/courses/pages/my-courses/my-courses.ts | 11 +++++++++-- src/core/courses/pages/my-overview/my-overview.html | 2 +- src/core/courses/pages/my-overview/my-overview.ts | 11 +++++++++-- 11 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/addon/mod/forum/pages/discussion/discussion.ts b/src/addon/mod/forum/pages/discussion/discussion.ts index ae1dab47b..94d36121b 100644 --- a/src/addon/mod/forum/pages/discussion/discussion.ts +++ b/src/addon/mod/forum/pages/discussion/discussion.ts @@ -68,6 +68,7 @@ export class AddonModForumDiscussionPage implements OnDestroy { }; refreshIcon = 'spinner'; syncIcon = 'spinner'; + discussionStr = ''; protected cmId: number; protected forumId: number; @@ -101,6 +102,8 @@ export class AddonModForumDiscussionPage implements OnDestroy { this.isOnline = this.appProvider.isOnline(); }); this.isSplitViewOn = this.svComponent && this.svComponent.isOn(); + + this.discussionStr = translate.instant('addon.mod_forum.discussion'); } /** diff --git a/src/addon/mod/lesson/pages/player/player.html b/src/addon/mod/lesson/pages/player/player.html index 34def2500..627b7757e 100644 --- a/src/addon/mod/lesson/pages/player/player.html +++ b/src/addon/mod/lesson/pages/player/player.html @@ -107,7 +107,7 @@ - + @@ -117,7 +117,7 @@ - {{ button.content }} + {{ button.content }} @@ -174,7 +174,7 @@ - + @@ -184,7 +184,7 @@ - + diff --git a/src/addon/mod/lesson/pages/player/player.scss b/src/addon/mod/lesson/pages/player/player.scss index 8a887b623..540e14ac8 100644 --- a/src/addon/mod/lesson/pages/player/player.scss +++ b/src/addon/mod/lesson/pages/player/player.scss @@ -12,10 +12,12 @@ page-addon-mod-lesson-player { .addon-mod_lesson-pagebuttons .button-block { contain: content; - height: auto; + height: 100%; + display: flex; + flex-direction: column; .button-inner { - height: auto; + flex-grow: 1; } } } diff --git a/src/app/app.scss b/src/app/app.scss index 63c59cae4..ae83c0189 100644 --- a/src/app/app.scss +++ b/src/app/app.scss @@ -39,6 +39,10 @@ .core-big { font-size: 115%; } .invisible { visibility: hidden; } +.button-no-uppercase { + text-transform: none; +} + @include media-breakpoint-up(sm) { .core-center-view .scroll-content { display: flex!important; diff --git a/src/components/loading/loading.scss b/src/components/loading/loading.scss index 503eca75b..3b05c5fdf 100644 --- a/src/components/loading/loading.scss +++ b/src/components/loading/loading.scss @@ -9,7 +9,7 @@ core-loading { } .core-loading-content { - display: unset; + display: inline; padding-bottom: 1px; /* This makes height be real */ } @@ -21,7 +21,7 @@ core-loading { .scroll-content > core-loading, ion-content > .scroll-content > core-loading, .core-loading-center { - position: unset !important; + position: static !important; } .scroll-content > core-loading, diff --git a/src/components/tabs/tabs.scss b/src/components/tabs/tabs.scss index b7e7618b1..20b4e97dc 100644 --- a/src/components/tabs/tabs.scss +++ b/src/components/tabs/tabs.scss @@ -18,6 +18,14 @@ font-size: 1.6rem; border: 0; + span { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + word-wrap: break-word; + display: block; + } + &[aria-selected=true] { color: $core-top-tabs-color-active !important; border: 0 !important; diff --git a/src/core/course/components/format/core-course-format.html b/src/core/course/components/format/core-course-format.html index b90c2e218..c3dc312e4 100644 --- a/src/core/course/components/format/core-course-format.html +++ b/src/core/course/components/format/core-course-format.html @@ -16,7 +16,7 @@
- diff --git a/src/core/courses/pages/my-courses/my-courses.html b/src/core/courses/pages/my-courses/my-courses.html index 25d1308d0..9c01fb0f3 100644 --- a/src/core/courses/pages/my-courses/my-courses.html +++ b/src/core/courses/pages/my-courses/my-courses.html @@ -19,7 +19,7 @@ - + diff --git a/src/core/courses/pages/my-courses/my-courses.ts b/src/core/courses/pages/my-courses/my-courses.ts index 1508d2831..cd14a0d56 100644 --- a/src/core/courses/pages/my-courses/my-courses.ts +++ b/src/core/courses/pages/my-courses/my-courses.ts @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnDestroy } from '@angular/core'; -import { IonicPage, NavController } from 'ionic-angular'; +import { Component, OnDestroy, ViewChild } from '@angular/core'; +import { IonicPage, Searchbar, NavController } from 'ionic-angular'; import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; @@ -31,6 +31,8 @@ import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delega templateUrl: 'my-courses.html', }) export class CoreCoursesMyCoursesPage implements OnDestroy { + @ViewChild('searchbar') searchbar: Searchbar; + courses: any[]; filteredCourses: any[]; searchEnabled: boolean; @@ -153,6 +155,11 @@ export class CoreCoursesMyCoursesPage implements OnDestroy { this.filter = ''; this.showFilter = !this.showFilter; this.filteredCourses = this.courses; + if (this.showFilter) { + setTimeout(() => { + this.searchbar.setFocus(); + }); + } } /** diff --git a/src/core/courses/pages/my-overview/my-overview.html b/src/core/courses/pages/my-overview/my-overview.html index e34364830..c52f77707 100644 --- a/src/core/courses/pages/my-overview/my-overview.html +++ b/src/core/courses/pages/my-overview/my-overview.html @@ -80,7 +80,7 @@
- +
diff --git a/src/core/courses/pages/my-overview/my-overview.ts b/src/core/courses/pages/my-overview/my-overview.ts index fbc38ec9d..fd67329cd 100644 --- a/src/core/courses/pages/my-overview/my-overview.ts +++ b/src/core/courses/pages/my-overview/my-overview.ts @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnDestroy } from '@angular/core'; -import { IonicPage, NavController } from 'ionic-angular'; +import { Component, OnDestroy, ViewChild } from '@angular/core'; +import { IonicPage, Searchbar, NavController } from 'ionic-angular'; import { CoreEventsProvider } from '@providers/events'; import { CoreSitesProvider } from '@providers/sites'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; @@ -34,6 +34,8 @@ import * as moment from 'moment'; templateUrl: 'my-overview.html', }) export class CoreCoursesMyOverviewPage implements OnDestroy { + @ViewChild('searchbar') searchbar: Searchbar; + firstSelectedTab: number; siteHomeEnabled: boolean; tabsReady = false; @@ -245,6 +247,11 @@ export class CoreCoursesMyOverviewPage implements OnDestroy { this.showFilter = !this.showFilter; this.courses.filter = ''; this.filteredCourses = this.courses[this.courses.selected]; + if (this.showFilter) { + setTimeout(() => { + this.searchbar.setFocus(); + }); + } } /**