From f184a09550ebb1b255dee95a063520e6f0c7412c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 10 Mar 2022 13:58:14 +0100 Subject: [PATCH] MOBILE-3814 course: Add action sheet to enrol me on course summary --- scripts/langindex.json | 1 + .../pages/course-storage/course-storage.scss | 8 +- src/core/features/course/lang.json | 1 + .../pages/course-summary/course-summary.html | 36 +++----- .../pages/course-summary/course-summary.ts | 86 +++++++++++++++---- .../course-list-item/course-list-item.ts | 2 +- src/theme/theme.base.scss | 29 +++---- src/theme/theme.light.scss | 3 +- 8 files changed, 103 insertions(+), 63 deletions(-) diff --git a/scripts/langindex.json b/scripts/langindex.json index 29d1c1122..3010f8f0a 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1567,6 +1567,7 @@ "core.course.thisweek": "format_weeks/currentsection", "core.course.todo": "completion", "core.course.useactivityonbrowser": "local_moodlemobileapp", + "core.course.viewcourse": "block_timeline", "core.course.warningmanualcompletionmodified": "local_moodlemobileapp", "core.course.warningofflinemanualcompletiondeleted": "local_moodlemobileapp", "core.coursedetails": "moodle", diff --git a/src/addons/storagemanager/pages/course-storage/course-storage.scss b/src/addons/storagemanager/pages/course-storage/course-storage.scss index 91a4907f4..bf803e5ab 100644 --- a/src/addons/storagemanager/pages/course-storage/course-storage.scss +++ b/src/addons/storagemanager/pages/course-storage/course-storage.scss @@ -3,6 +3,10 @@ :host { --course-storage-max-activity-height: 120px; + ion-card ion-item { + --inner-padding-end: 0px; + } + ion-card.section ion-card-header { margin-bottom: 8px; padding-top: 8px; @@ -48,7 +52,3 @@ ion-item core-mod-icon { display: flex; align-items: center; } - -ion-item { - --inner-padding-end: 0px; -} diff --git a/src/core/features/course/lang.json b/src/core/features/course/lang.json index efa7b5613..1b1ae4835 100644 --- a/src/core/features/course/lang.json +++ b/src/core/features/course/lang.json @@ -54,6 +54,7 @@ "thisweek": "This week", "todo": "To do", "useactivityonbrowser": "You can still use it using your device's web browser.", + "viewcourse": "View course", "warningmanualcompletionmodified": "The manual completion of an activity was modified on the site.", "warningofflinemanualcompletiondeleted": "Some offline manual completion of course '{{name}}' has been deleted. {{error}}" } diff --git a/src/core/features/course/pages/course-summary/course-summary.html b/src/core/features/course/pages/course-summary/course-summary.html index 2b699e288..cde4c68c3 100644 --- a/src/core/features/course/pages/course-summary/course-summary.html +++ b/src/core/features/course/pages/course-summary/course-summary.html @@ -130,43 +130,27 @@ - + {{item.data.title | translate }} - - - - -

{{ instance.name }}

- - {{ 'core.courses.enrolme' | translate }} - -
-
- - -

{{ 'core.courses.otherenrolments' | translate }}

- - {{ 'core.courses.completeenrolmentbrowser' | translate }} - -
-
-
+ + {{ 'core.courses.enrolme' | translate }} + - + {{ 'core.courses.notenrollable' | translate }} - - - - {{ 'core.course' | translate }} - + + + {{ 'core.course.viewcourse' | translate }}
diff --git a/src/core/features/course/pages/course-summary/course-summary.ts b/src/core/features/course/pages/course-summary/course-summary.ts index 82e096ecf..694346601 100644 --- a/src/core/features/course/pages/course-summary/course-summary.ts +++ b/src/core/features/course/pages/course-summary/course-summary.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Component, OnDestroy, OnInit, Input, ViewChild, ElementRef } from '@angular/core'; -import { IonRefresher } from '@ionic/angular'; +import { ActionSheetButton, IonRefresher } from '@ionic/angular'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; @@ -31,7 +31,7 @@ import { CoreCourseOptionsMenuHandlerToDisplay, } from '@features/course/services/course-options-delegate'; import { CoreCourseHelper } from '@features/course/services/course-helper'; -import { ModalController, NgZone, Platform, Translate } from '@singletons'; +import { ActionSheetController, ModalController, NgZone, Platform, Translate } from '@singletons'; import { CoreCoursesSelfEnrolPasswordComponent } from '../../../courses/components/self-enrol-password/self-enrol-password'; import { CoreNavigator } from '@services/navigator'; import { CoreUtils } from '@services/utils/utils'; @@ -57,7 +57,7 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { isEnrolled = false; canAccessCourse = true; selfEnrolInstances: CoreCourseEnrolmentMethod[] = []; - paypalEnabled = false; + otherEnrolments = false; dataLoaded = false; isModal = false; contactsExpanded = false; @@ -65,6 +65,8 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { courseUrl = ''; progress?: number; + protected actionSheet?: HTMLIonActionSheetElement; + courseMenuHandlers: CoreCourseOptionsMenuHandlerToDisplay[] = []; protected useGuestAccess = false; @@ -146,18 +148,24 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { protected async getCourse(refresh = false): Promise { // Get course enrolment methods. this.selfEnrolInstances = []; + this.otherEnrolments = false; try { const enrolmentMethods = await CoreCourses.getCourseEnrolmentMethods(this.courseId); this.guestInstanceId = undefined; enrolmentMethods.forEach((method) => { + if (!method.status) { + return; + } + if (method.type === 'self') { this.selfEnrolInstances.push(method); } else if (method.type === 'guest') { this.guestInstanceId = method.id; - } else if (method.type === 'paypal') { - this.paypalEnabled = true; + } else { + // Other enrolments that comes from that WS should need user action. + this.otherEnrolments = true; } }); } catch (error) { @@ -196,7 +204,10 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { this.course = courseByField; } - this.paypalEnabled = !this.isEnrolled && courseByField.enrollmentmethods?.indexOf('paypal') > -1; + // enrollmentmethods contains ALL enrolment methods including manual. + if (!this.isEnrolled && courseByField.enrollmentmethods?.some((method) => method === 'paypal')) { + this.otherEnrolments = true; + } } catch { // Ignore errors. @@ -256,7 +267,7 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { try { await CoreDomUtils.showConfirm( Translate.instant('core.courses.browserenrolinstructions'), - undefined, + Translate.instant('core.courses.completeenrolmentbrowser'), Translate.instant('core.openinbrowser'), ); } catch { @@ -276,15 +287,15 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { } /** - * User clicked in a self enrol button. + * Confirm user to Self enrol in course. * - * @param instanceId The instance ID of the enrolment method. + * @param enrolMethod The enrolment method. */ - async selfEnrolClicked(instanceId: number): Promise { + async selfEnrolConfirm(enrolMethod: CoreCourseEnrolmentMethod): Promise { try { - await CoreDomUtils.showConfirm(Translate.instant('core.courses.confirmselfenrol')); + await CoreDomUtils.showConfirm(Translate.instant('core.courses.confirmselfenrol'), enrolMethod.name); - this.selfEnrolInCourse('', instanceId); + this.selfEnrolInCourse(enrolMethod.id); } catch { // User cancelled. } @@ -293,11 +304,11 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { /** * Self enrol in a course. * - * @param password Password to use. * @param instanceId The instance ID. + * @param password Password to use. * @return Promise resolved when self enrolled. */ - async selfEnrolInCourse(password: string, instanceId: number): Promise { + async selfEnrolInCourse(instanceId: number, password = ''): Promise { const modal = await CoreDomUtils.showModalLoading('core.loading', true); try { @@ -336,7 +347,7 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { ); if (modalData !== undefined) { - this.selfEnrolInCourse(modalData, instanceId); + this.selfEnrolInCourse(instanceId, modalData); return; } @@ -442,6 +453,51 @@ export class CoreCourseSummaryPage implements OnInit, OnDestroy { } } + /** + * Open enrol action sheet. + */ + async enrolMe(): Promise { + if (this.selfEnrolInstances.length == 1 && !this.otherEnrolments) { + this.selfEnrolConfirm(this.selfEnrolInstances[0]); + + return; + } + + if (this.selfEnrolInstances.length == 0 && this.otherEnrolments) { + this.browserEnrol(); + + return; + } + + const buttons: ActionSheetButton[] = this.selfEnrolInstances.map((enrolMethod) => ({ + text: enrolMethod.name, + handler: (): void => { + this.selfEnrolConfirm(enrolMethod); + }, + })); + + if (this.otherEnrolments) { + buttons.push({ + text: Translate.instant('core.courses.completeenrolmentbrowser'), + handler: (): void => { + this.browserEnrol(); + }, + }); + } + + buttons.push({ + text: Translate.instant('core.cancel'), + role: 'cancel', + }); + + this.actionSheet = await ActionSheetController.create({ + header: Translate.instant('core.courses.enrolme'), + buttons: buttons, + }); + + await this.actionSheet.present(); + } + /** * Toggle list of contacts. */ diff --git a/src/core/features/courses/components/course-list-item/course-list-item.ts b/src/core/features/courses/components/course-list-item/course-list-item.ts index c73a3dd3a..c13587b47 100644 --- a/src/core/features/courses/components/course-list-item/course-list-item.ts +++ b/src/core/features/courses/components/course-list-item/course-list-item.ts @@ -114,7 +114,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On } else if (instance === 'paypal') { this.enrolmentIcons.push({ label: 'core.courses.otherenrolments', - icon: 'fab-paypal', + icon: 'fas-external-link-alt', }); } }); diff --git a/src/theme/theme.base.scss b/src/theme/theme.base.scss index f8384c689..1396e9a71 100644 --- a/src/theme/theme.base.scss +++ b/src/theme/theme.base.scss @@ -833,24 +833,23 @@ ion-toolbar h1 .core-bar-button-image img { } // Action sheet. -.md ion-action-sheet { +ion-action-sheet.md { + .action-sheet-title { + @include padding(4px, null, 4px, 16px); + font-size: 12px; + min-height: auto; + color: var(--medium); + line-height: 2em; + font-weight: normal; + } + + .action-sheet-group:first-child { + border-radius: var(--big-radius) var(--big-radius) 0 0; + } + .action-sheet-group-cancel { box-shadow: var(--drop-shadow-top, none); } - - .action-sheet-title { - border-bottom: 2px solid var(--title-border-color); - } -} - -.ios ion-action-sheet { - .action-sheet-title { - font-size: 16px; - } - - .action-sheet-title { - border-bottom: 2px solid var(--title-border-color); - } } // Radio. diff --git a/src/theme/theme.light.scss b/src/theme/theme.light.scss index 193d74b8d..c19cac3bf 100644 --- a/src/theme/theme.light.scss +++ b/src/theme/theme.light.scss @@ -216,7 +216,6 @@ ion-action-sheet { --button-color: var(--ion-text-color); --button-color-selected: var(--ion-text-color); - --title-border-color: var(--primary); .action-sheet-title { --color: var(--ion-text-color); @@ -325,7 +324,7 @@ --core-star-color: var(--primary); --core-large-avatar-size: 90px; - --core-avatar-size: 40px; + --core-avatar-size: var(--a11y-min-target-size); --core-courseimage-on-course-size: 72px; --core-courseimage-radius: var(--medium-radius);