From add521a0e78a2de19ca4459b3affbc1c18aa1196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 19 Nov 2020 16:37:46 +0100 Subject: [PATCH] MOBILE-3594 course: Improve course listing and add course image parallax --- .../core-courses-course-list-item.html | 22 ++++- .../course-list-item/course-list-item.scss | 48 ++++++++++ .../course-list-item/course-list-item.ts | 22 +++-- .../course-progress/course-progress.scss | 20 ++--- .../pages/course-preview/course-preview.html | 13 ++- .../pages/course-preview/course-preview.scss | 41 ++++++--- .../courses/services/courses.helper.ts | 90 +++++++++++++------ src/theme/variables.scss | 20 ++--- 8 files changed, 207 insertions(+), 69 deletions(-) create mode 100644 src/core/features/courses/components/course-list-item/course-list-item.scss diff --git a/src/core/features/courses/components/course-list-item/core-courses-course-list-item.html b/src/core/features/courses/components/course-list-item/core-courses-course-list-item.html index 1495e6d9f..ccf64943c 100644 --- a/src/core/features/courses/components/course-list-item/core-courses-course-list-item.html +++ b/src/core/features/courses/components/course-list-item/core-courses-course-list-item.html @@ -1,11 +1,31 @@ - + + + + +

+ + + + | + + + + +

+

+ +

{ + CoreCoursesHelper.instance.loadCourseColorAndImage(this.course); + // Check if the user is enrolled in the course. try { - await CoreCourses.instance.getUserCourse(this.course.id); + const course = await CoreCourses.instance.getUserCourse(this.course.id); + this.course.progress = course.progress; + this.course.completionusertracked = course.completionusertracked; this.isEnrolled = true; } catch { @@ -87,11 +95,13 @@ export class CoreCoursesCourseListItemComponent implements OnInit { * @param course The course to open. */ openCourse(): void { - if (this.isEnrolled) { + /* if (this.isEnrolled) { CoreCourseHelper.instance.openCourse(this.course); } else { this.navCtrl.navigateForward('/courses/preview', { queryParams: { course: this.course } }); - } + } */ + // @todo while opencourse function is not completed, open preview page. + this.navCtrl.navigateForward('/courses/preview', { queryParams: { course: this.course } }); } } diff --git a/src/core/features/courses/components/course-progress/course-progress.scss b/src/core/features/courses/components/course-progress/course-progress.scss index 688838d8c..67b5b9470 100644 --- a/src/core/features/courses/components/course-progress/course-progress.scss +++ b/src/core/features/courses/components/course-progress/course-progress.scss @@ -6,34 +6,34 @@ height: calc(100% - 20px); &[course-color="0"] .core-course-thumb { - background: var(--core-course-image-background-0); + background: var(--core-course-color-0); } &[course-color="1"] .core-course-thumb { - background: var(--core-course-image-background-1); + background: var(--core-course-color-1); } &[course-color="2"] .core-course-thumb { - background: var(--core-course-image-background-2); + background: var(--core-course-color-2); } &[course-color="3"] .core-course-thumb { - background: var(--core-course-image-background-3); + background: var(--core-course-color-3); } &[course-color="4"] .core-course-thumb { - background: var(--core-course-image-background-4); + background: var(--core-course-color-4); } &[course-color="5"] .core-course-thumb { - background: var(--core-course-image-background-5); + background: var(--core-course-color-5); } &[course-color="6"] .core-course-thumb { - background: var(--core-course-image-background-6); + background: var(--core-course-color-6); } &[course-color="7"] .core-course-thumb { - background: var(--core-course-image-background-7); + background: var(--core-course-color-7); } &[course-color="8"] .core-course-thumb { - background: var(--core-course-image-background-8); + background: var(--core-course-color-8); } &[course-color="9"] .core-course-thumb { - background: var(--core-course-image-background-9); + background: var(--core-course-color-9); } .core-course-thumb { diff --git a/src/core/features/courses/pages/course-preview/course-preview.html b/src/core/features/courses/pages/course-preview/course-preview.html index b11a999d8..5d4e09c2b 100644 --- a/src/core/features/courses/pages/course-preview/course-preview.html +++ b/src/core/features/courses/pages/course-preview/course-preview.html @@ -11,11 +11,12 @@ - - +
+
+
@@ -37,7 +38,11 @@ - {{ 'core.teachers' | translate }} + + +

{{ 'core.teachers' | translate }}

+
+

{{ 'core.openinbrowser' | translate }}

- +
diff --git a/src/core/features/courses/pages/course-preview/course-preview.scss b/src/core/features/courses/pages/course-preview/course-preview.scss index 02d06fcd7..ba783b098 100644 --- a/src/core/features/courses/pages/course-preview/course-preview.scss +++ b/src/core/features/courses/pages/course-preview/course-preview.scss @@ -1,20 +1,39 @@ :host { - .core-course-thumb { - height: 150px; - width: 100%; + --scroll-factor: 0.5; + --translate-z: calc(-2 * var(--scroll-factor))px; + --scale: calc(1 + var(--scroll-factor) * 2); + + perspective: 1px; + perspective-origin: center top; + transform-style: preserve-3d; + + .core-course-thumb-parallax-content { + transform: translateZ(0); + -webkit-filter: drop-shadow(0px -3px 3px rgba(var(--drop-shadow))); + filter: drop-shadow(0px -3px 3px rgba(var(--drop-shadow))); + } + .core-course-thumb-parallax { + height: 40vw; + max-height: 35vh; + z-index: -1; overflow: hidden; + } + .core-course-thumb { + overflow: hidden; + text-align: center; cursor: pointer; pointer-events: auto; - position: relative; + transform-origin: center top; - img { - position: absolute; - top: 0; - bottom: 0; - margin: auto; - width: 100%; - } + /** + * Calculated with scroll-factor: 0.5; + * translate-z: -2 * $scroll-factor px; + * scale: 1 + $scroll-factor * 2; + */ + transform: translateZ(-1px) scale(2); } + + .core-customfieldvalue core-format-text { display: inline; } diff --git a/src/core/features/courses/services/courses.helper.ts b/src/core/features/courses/services/courses.helper.ts index 0cef4e4f0..f2fac5251 100644 --- a/src/core/features/courses/services/courses.helper.ts +++ b/src/core/features/courses/services/courses.helper.ts @@ -18,6 +18,7 @@ import { CoreUtils } from '@services/utils/utils'; import { CoreSites } from '@services/sites'; import { CoreCourses, CoreCourseSearchedData, CoreCourseUserAdminOrNavOptionIndexed, CoreEnrolledCourseData } from './courses'; import { makeSingleton } from '@singletons/core.singletons'; +import { CoreWSExternalFile } from '@services/ws'; // import { AddonCourseCompletionProvider } from '@addon/coursecompletion/providers/coursecompletion'; // import { CoreCoursePickerMenuPopoverComponent } from '@components/course-picker-menu/course-picker-menu-popover'; @@ -51,20 +52,17 @@ export class CoreCoursesHelperProvider { course: CoreEnrolledCourseDataWithExtraInfo, courseByField: CoreCourseSearchedData, addCategoryName: boolean = false, + colors?: (string | undefined)[], ): void { if (courseByField) { course.displayname = courseByField.displayname; course.categoryname = addCategoryName ? courseByField.categoryname : undefined; - - if (courseByField.overviewfiles && courseByField.overviewfiles[0]) { - course.courseImage = courseByField.overviewfiles[0].fileurl; - } else { - delete course.courseImage; - } + course.overviewfiles = course.overviewfiles || courseByField.overviewfiles; } else { delete course.displayname; - delete course.courseImage; } + + this.loadCourseColorAndImage(course, colors); } /** @@ -84,21 +82,14 @@ export class CoreCoursesHelperProvider { let coursesInfo = {}; let courseInfoAvailable = false; - const site = CoreSites.instance.getCurrentSite(); const promises: Promise[] = []; - const colors: (string | undefined)[] = []; + let colors: (string | undefined)[] = []; - if (site?.isVersionGreaterEqualThan('3.8')) { - promises.push(site.getConfig().then((configs) => { - for (let x = 0; x < 10; x++) { - colors[x] = configs['core_admin_coursecolor' + (x + 1)] || undefined; - } + promises.push(this.loadCourseSiteColors().then((loadedColors) => { + colors = loadedColors; - return; - }).catch(() => { - // Ignore errors. - })); - } + return; + })); if (CoreCourses.instance.isGetCoursesByFieldAvailable() && (loadCategoryNames || (typeof courses[0].overviewfiles == 'undefined' && typeof courses[0].displayname == 'undefined'))) { @@ -117,15 +108,52 @@ export class CoreCoursesHelperProvider { await Promise.all(promises); courses.forEach((course) => { - this.loadCourseExtraInfo(course, courseInfoAvailable ? coursesInfo[course.id] : course, loadCategoryNames); - - if (!course.courseImage) { - course.colorNumber = course.id % 10; - course.color = colors.length ? colors[course.colorNumber] : undefined; - } + this.loadCourseExtraInfo(course, courseInfoAvailable ? coursesInfo[course.id] : course, loadCategoryNames, colors); }); } + /** + * Load course colors from site config. + * + * @return course colors RGB. + */ + protected async loadCourseSiteColors(): Promise<(string | undefined)[]> { + const site = CoreSites.instance.getCurrentSite(); + const colors: (string | undefined)[] = []; + + if (site?.isVersionGreaterEqualThan('3.8')) { + try { + const configs = await site.getConfig(); + for (let x = 0; x < 10; x++) { + colors[x] = configs['core_admin_coursecolor' + (x + 1)] || undefined; + } + } catch { + // Ignore errors. + } + } + + return colors; + } + + /** + * Loads the color of the course or the thumb image. + * + * @param course Course data. + * @param colors Colors loaded. + */ + async loadCourseColorAndImage(course: CoreCourseWithImageAndColor, colors?: (string | undefined)[]): Promise { + if (!colors) { + colors = await this.loadCourseSiteColors(); + } + + if (course.overviewfiles && course.overviewfiles[0]) { + course.courseImage = course.overviewfiles[0].fileurl; + } else { + course.colorNumber = course.id % 10; + course.color = colors.length ? colors[course.colorNumber] : undefined; + } + } + /** * Get user courses with admin and nav options. * @@ -157,12 +185,20 @@ export class CoreCoursesHelperProvider { export class CoreCoursesHelper extends makeSingleton(CoreCoursesHelperProvider) { } /** - * Enrolled course data with extra rendering info. + * Course with colors info and course image. */ -export type CoreEnrolledCourseDataWithExtraInfo = CoreEnrolledCourseData & { +export type CoreCourseWithImageAndColor = { + id: number; // Course id. + overviewfiles?: CoreWSExternalFile[]; colorNumber?: number; // Color index number. color?: string; // Color RGB. courseImage?: string; // Course thumbnail. +}; + +/** + * Enrolled course data with extra rendering info. + */ +export type CoreEnrolledCourseDataWithExtraInfo = CoreCourseWithImageAndColor & CoreEnrolledCourseData & { categoryname?: string; // Category name, }; diff --git a/src/theme/variables.scss b/src/theme/variables.scss index 1bda05033..e35b04f3c 100644 --- a/src/theme/variables.scss +++ b/src/theme/variables.scss @@ -154,16 +154,16 @@ --core-login-background: var(--custom-login-background, var(--white)); --core-login-text-color: var(--custom-login-text-color, var(--black)); - --core-course-image-background-0: var(--custom-course-image-background-0, #81ecec); - --core-course-image-background-1: var(--custom-course-image-background-1, #74b9ff); - --core-course-image-background-2: var(--custom-course-image-background-2, #a29bfe); - --core-course-image-background-3: var(--custom-course-image-background-3, #dfe6e9); - --core-course-image-background-4: var(--custom-course-image-background-4, #00b894); - --core-course-image-background-5: var(--custom-course-image-background-5, #0984e3); - --core-course-image-background-6: var(--custom-course-image-background-6, #b2bec3); - --core-course-image-background-7: var(--custom-course-image-background-7, #fdcb6e); - --core-course-image-background-8: var(--custom-course-image-background-9, #fd79a8); - --core-course-image-background-9: var(--custom-course-image-background-90, #6c5ce7); + --core-course-color-0: var(--custom-course-color-0, #81ecec); + --core-course-color-1: var(--custom-course-color-1, #74b9ff); + --core-course-color-2: var(--custom-course-color-2, #a29bfe); + --core-course-color-3: var(--custom-course-color-3, #dfe6e9); + --core-course-color-4: var(--custom-course-color-4, #00b894); + --core-course-color-5: var(--custom-course-color-5, #0984e3); + --core-course-color-6: var(--custom-course-color-6, #b2bec3); + --core-course-color-7: var(--custom-course-color-7, #fdcb6e); + --core-course-color-8: var(--custom-course-color-9, #fd79a8); + --core-course-color-9: var(--custom-course-color-90, #6c5ce7); --core-star-color: var(--custom-star-color, var(--core-color)); }