Skip to content

Commit 49736ae

Browse files
authored
Merge pull request #4531 from crazyserver/MOBILE-4860
Mobile 4860
2 parents ef926cd + cfa0ccb commit 49736ae

File tree

32 files changed

+290
-395
lines changed

32 files changed

+290
-395
lines changed

src/addons/mod/assign/tests/behat/single_activity.feature

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ Feature: Test single activity of assign type in app
2222
Given I entered the course "Course 1" as "student1" in the app
2323
Then I should find "Attempt 1" in the app
2424

25-
When I set "page-core-course-index .core-course-thumb" styles to "background" "lightblue"
26-
And I set "page-core-course-index .core-course-thumb img" styles to "display" "none"
25+
When I set "page-core-course-index core-course-image" styles to "background" "lightblue"
26+
And I set "page-core-course-index core-course-image" styles to "--core-image-visibility" "hidden"
2727
Then the UI should match the snapshot
2828

2929
And I press "Add submission" in the app

src/addons/mod/book/tests/behat/single_activity.feature

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ Feature: Test single activity of book type in app
2828
Then I should find "Chapt 1" in the app
2929
And I should find "Chapt 2" in the app
3030

31-
When I set "page-core-course-index .core-course-thumb" styles to "background" "lightblue"
32-
And I set "page-core-course-index .core-course-thumb img" styles to "display" "none"
31+
When I set "page-core-course-index core-course-image" styles to "background" "lightblue"
32+
And I set "page-core-course-index core-course-image" styles to "--core-image-visibility" "hidden"
3333
Then the UI should match the snapshot
3434

3535
Then I press "Chapt 1" in the app

src/addons/mod/scorm/tests/behat/single_activity.feature

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ Feature: Test single activity of scorm type in app
2222
Given I entered the course "Course 1" as "student1" in the app
2323
And I replace "/.*/" within ".addon-scorm-last-sync-date" with "[Date]"
2424

25-
When I set "page-core-course-index .core-course-thumb" styles to "background" "lightblue"
26-
And I set "page-core-course-index .core-course-thumb img" styles to "display" "none"
25+
When I set "page-core-course-index core-course-image" styles to "background" "lightblue"
26+
And I set "page-core-course-index core-course-image" styles to "--core-image-visibility" "hidden"
2727
Then the UI should match the snapshot
2828

2929
When I press "Enter" in the app

src/addons/mod/subsection/services/handlers/index-link.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import { CoreContentLinksAction } from '@features/contentlinks/services/contentl
1818
import { CoreCourse } from '@features/course/services/course';
1919
import { CoreLoadings } from '@services/overlays/loadings';
2020
import { makeSingleton } from '@singletons';
21-
import { CoreSites } from '@services/sites';
2221
import { CoreCourseHelper } from '@features/course/services/course-helper';
2322
import { CoreAlerts } from '@services/overlays/alerts';
2423
import { ADDON_MOD_SUBSECTION_COMPONENT, ADDON_MOD_SUBSECTION_MODNAME } from '../../constants';
@@ -48,14 +47,7 @@ export class AddonModSubsectionIndexLinkHandlerService extends CoreContentLinksM
4847
sectionId,
4948
};
5049

51-
if (
52-
(!siteId || siteId === CoreSites.getCurrentSiteId()) &&
53-
CoreCourse.currentViewIsCourse(courseId)
54-
) {
55-
CoreCourse.selectCourseTab('', pageParams);
56-
} else {
57-
await CoreCourseHelper.getAndOpenCourse(courseId, pageParams, siteId);
58-
}
50+
await CoreCourseHelper.getAndOpenCourse(courseId, pageParams, siteId);
5951
}
6052

6153
/**

src/core/components/course-image/course-image.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
<img [url]="course().courseimage" core-external-content alt="" (error)="loadFallbackCourseIcon()" />
44
</ion-avatar>
55
} @else {
6-
<ion-icon name="fas-graduation-cap" slot="start" aria-hidden="true" />
6+
<ion-icon name="fas-graduation-cap" slot="start" aria-hidden="true" class="course-icon-fallback" />
77
}

src/core/components/course-image/course-image.scss

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
:host {
55
--core-image-radius: var(--core-courseimage-radius);
66
--core-image-size: 60px;
7+
--core-card-top-padding: 40%;
8+
--core-image-visibility: visible;
79

810
display: flex;
911
justify-content: center;
1012
align-items: center;
1113
background: var(--course-color, white);
1214
border-radius: var(--core-image-radius);
15+
background-position: center;
16+
background-size: cover;
1317

1418
@for $i from 0 to list.length($core-course-image-background) {
1519
&.course-color-#{$i} {
@@ -18,12 +22,13 @@
1822
}
1923
}
2024

21-
ion-icon {
25+
ion-icon.course-icon-fallback {
2226
--padding: 12px;
2327

2428
padding: var(--padding);
2529
font-size: calc(var(--core-image-size) - var(--padding) * 2);
2630
color: var(--course-color-tint);
31+
visibility: var(--core-image-visibility);
2732
}
2833

2934
ion-avatar {
@@ -33,6 +38,7 @@
3338

3439
img {
3540
background: transparent;
41+
visibility: var(--core-image-visibility);
3642
}
3743

3844
}
@@ -51,14 +57,71 @@
5157
--core-image-radius: 0px;
5258
--core-image-size: 100%;
5359

54-
ion-icon {
60+
ion-icon.course-icon-fallback {
5561
opacity: 0.5;
5662
width: 80px;
5763
height: 80px;
5864
}
5965

6066
}
6167

68+
&.card-top {
69+
--core-image-size: auto;
70+
--core-image-radius: none;
71+
72+
padding-top: var(--core-card-top-padding);
73+
overflow: hidden;
74+
cursor: pointer;
75+
pointer-events: auto;
76+
position: relative;
77+
78+
79+
ion-icon.course-icon-fallback {
80+
color: white;
81+
opacity: 0.5;
82+
position: absolute;
83+
left: 0;
84+
right: 0;
85+
top: 50%;
86+
bottom: 0;
87+
width: 80px;
88+
height: 80px;
89+
margin: 0 auto;
90+
transform: translateY(-50%);
91+
}
92+
93+
ion-avatar img {
94+
position: absolute;
95+
top: 0;
96+
bottom: 0;
97+
right: 0;
98+
left: 0;
99+
margin: auto;
100+
width: auto;
101+
height: auto;
102+
}
103+
}
104+
105+
&.page-top {
106+
--core-image-radius: none;
107+
108+
overflow: hidden;
109+
text-align: center;
110+
height: var(--core-image-size);
111+
position: fixed;
112+
z-index: -1;
113+
width: 100%;
114+
115+
ion-avatar img {
116+
width: 100%;
117+
height: 100%;
118+
object-fit: cover;
119+
}
120+
ion-icon.course-icon-fallback {
121+
--padding: 24px;
122+
}
123+
}
124+
62125
}
63126

64127
:host-context(ion-item) {

src/core/components/course-image/course-image.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// limitations under the License.
1414

1515
import { toBoolean } from '@/core/transforms/boolean';
16-
import { Component, ElementRef, HostBinding, input, effect, inject } from '@angular/core';
16+
import { Component, ElementRef, input, effect, inject } from '@angular/core';
1717
import { CoreCourseListItem } from '@features/courses/services/courses';
1818
import { CoreCoursesHelper } from '@features/courses/services/courses-helper';
1919
import { CoreColors } from '@singletons/colors';
@@ -44,11 +44,6 @@ export class CoreCourseImageComponent {
4444
});
4545
}
4646

47-
@HostBinding('class.fill-container')
48-
get fillContainer(): boolean {
49-
return this.fill();
50-
}
51-
5247
/**
5348
* Removes the course image set because it cannot be loaded and set the fallback icon color.
5449
*/
@@ -65,15 +60,33 @@ export class CoreCourseImageComponent {
6560
protected async setCourseColor(): Promise<void> {
6661
const course = this.course();
6762

68-
await CoreCoursesHelper.loadCourseColorAndImage(course);
63+
// Moodle 4.1 downwards geopatterns are embedded in b64 in only some WS, remove them to keep it coherent.
64+
if (course.courseimage?.startsWith('data')) {
65+
course.courseimage = undefined;
66+
}
67+
68+
if (course.courseimage !== undefined) {
69+
return;
70+
}
71+
72+
if (course.overviewfiles && course.overviewfiles[0]) {
73+
course.courseimage = course.overviewfiles[0].fileurl;
74+
75+
return;
76+
}
77+
78+
// If no image, set the color.
79+
const colors = await CoreCoursesHelper.getCourseSiteColors();
80+
const colorNumber = course.id % 10;
81+
const color = colors.length ? colors[colorNumber] : undefined;
6982

70-
if (course.color) {
71-
this.element.style.setProperty('--course-color', course.color);
83+
if (color) {
84+
this.element.style.setProperty('--course-color', color);
7285

73-
const tint = CoreColors.lighter(course.color, 50);
86+
const tint = CoreColors.lighter(color, 50);
7487
this.element.style.setProperty('--course-color-tint', tint);
75-
} else if (course.colorNumber !== undefined) {
76-
this.element.classList.add(`course-color-${course.colorNumber}`);
88+
} else {
89+
this.element.classList.add(`course-color-${colorNumber}`);
7790
}
7891
}
7992

src/core/features/course/components/course-format/course-format.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,9 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
180180
let section: CoreCourseSection | undefined;
181181

182182
if (data.sectionId !== undefined && this.sections) {
183-
section = this.sections.find((section) => section.id == data.sectionId);
183+
section = this.sections.find((section) => section.id === data.sectionId);
184184
} else if (data.sectionNumber !== undefined && this.sections) {
185-
section = this.sections.find((section) => section.section == data.sectionNumber);
185+
section = this.sections.find((section) => section.section === data.sectionNumber);
186186
}
187187

188188
if (section) {

src/core/features/course/pages/course-summary/course-summary.html

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,7 @@
2121
</ion-refresher>
2222
<core-loading [hideUntil]="dataLoaded">
2323
@if (course) {
24-
<div class="core-course-thumb" #courseThumb>
25-
@if (course.courseimage) {
26-
<img [url]="course.courseimage" core-external-content alt="" (error)="loadFallbackCourseIcon()" />
27-
} @else {
28-
<ion-icon name="fas-graduation-cap" class="course-icon" aria-hidden="true" />
29-
}
30-
</div>
24+
<core-course-image [course]="course" class="page-top" />
3125

3226
<div class="course-container">
3327
<div class="list-item-limited-width">
@@ -113,16 +107,16 @@ <h2 class="item-heading">
113107
</ion-label>
114108
</ion-item>
115109
@if (contactsExpanded || course.contacts.length < 5) {
116-
117-
<ion-item button class="ion-text-wrap" *ngFor="let contact of course.contacts" core-user-link
118-
[userId]="contact.id" [courseId]="isEnrolled ? course.id : null" [detail]="true">
119-
<core-user-avatar [user]="contact" slot="start" [userId]="contact.id"
120-
[courseId]="isEnrolled ? course.id : null" [linkProfile]="false" />
121-
<ion-label>
122-
<p class="item-heading">{{contact.fullname}}</p>
123-
</ion-label>
124-
</ion-item>
125-
110+
@for (contact of course.contacts; track contact.id) {
111+
<ion-item button class="ion-text-wrap" core-user-link
112+
[userId]="contact.id" [courseId]="isEnrolled ? course.id : null" [detail]="true">
113+
<core-user-avatar [user]="contact" slot="start" [userId]="contact.id"
114+
[courseId]="isEnrolled ? course.id : null" [linkProfile]="false" />
115+
<ion-label>
116+
<p class="item-heading">{{contact.fullname}}</p>
117+
</ion-label>
118+
</ion-item>
119+
}
126120
}
127121
<core-spacer />
128122
</ion-list>
@@ -131,7 +125,7 @@ <h2 class="item-heading">
131125
@if (course.customfields) {
132126
<ion-item class="ion-text-wrap">
133127
<ion-label>
134-
<ng-container *ngFor="let field of course.customfields">
128+
@for (field of course.customfields; track field.shortname) {
135129
@if (field.value) {
136130
<div class="core-customfield core-customfield_{{field.type}} core-customfield_{{field.shortname}}">
137131
<span class="core-customfieldname">
@@ -146,7 +140,7 @@ <h2 class="item-heading">
146140
</span>
147141
</div>
148142
}
149-
</ng-container>
143+
}
150144
</ion-label>
151145
</ion-item>
152146
}
@@ -160,15 +154,15 @@ <h2 class="item-heading">
160154
<ion-footer>
161155
<div class="list-item-limited-width">
162156
@if (canAccessCourse) {
163-
164-
<ion-button *ngFor="let item of courseMenuHandlers" (click)="openMenuItem(item)" [class]="'ion-text-wrap '+ item.data.class"
165-
expand="block">
166-
@if (item.data.icon) {
167-
<ion-icon [name]="item.data.icon" slot="start" aria-hidden="true" />
168-
}
169-
<ion-label>{{item.data.title | translate }}</ion-label>
170-
</ion-button>
171-
157+
@for (item of courseMenuHandlers; track item.name) {
158+
<ion-button (click)="openMenuItem(item)" [class]="'ion-text-wrap '+ item.data.class"
159+
expand="block">
160+
@if (item.data.icon) {
161+
<ion-icon [name]="item.data.icon" slot="start" aria-hidden="true" />
162+
}
163+
<ion-label>{{item.data.title | translate }}</ion-label>
164+
</ion-button>
165+
}
172166
}
173167
@if (!isEnrolled) {
174168

src/core/features/course/pages/course-summary/course-summary.scss

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
@use "theme/globals" as *;
2-
@use "sass:list";
32

43
:host {
54
--thumb-height: 180px;
@@ -8,39 +7,8 @@
87
position: absolute;
98
}
109

11-
.core-course-thumb {
12-
background: var(--course-color, white);
13-
overflow: hidden;
14-
text-align: center;
15-
height: var(--thumb-height);
16-
position: fixed;
17-
z-index: -1;
18-
width: 100%;
19-
20-
@for $i from 0 to list.length($core-course-image-background) {
21-
&.course-color-#{$i} {
22-
--course-color: var(--core-course-color-#{$i});
23-
--course-color-tint: var(--core-course-color-#{$i}-tint);
24-
}
25-
}
26-
27-
img {
28-
width: 100%;
29-
height: 100%;
30-
object-fit: cover;
31-
32-
// Fill geopaterns
33-
&[src$=".svg"] {
34-
min-width: 100%;
35-
}
36-
}
37-
38-
/** Deprecated icon */
39-
ion-icon.course-icon {
40-
padding: 24px;
41-
font-size: calc(var(--thumb-height) - 48px);
42-
color: var(--course-color-tint);
43-
}
10+
core-course-image {
11+
--core-image-size: var(--thumb-height);
4412
}
4513

4614
.course-container {

0 commit comments

Comments
 (0)