MOBILE-2406 courses: Add course image
parent
0ec3f9fcab
commit
c6956250fa
|
@ -29,7 +29,7 @@
|
|||
<ion-card *ngIf="user">
|
||||
<ion-item text-wrap>
|
||||
<ion-avatar *ngIf="user.profileimageurl && user.profileimageurl !== true" item-start>
|
||||
<img [src]="user.profileimageurl" [alt]="'core.pictureof' | translate:{$a: user.fullname}" core-external-content>
|
||||
<img [src]="user.profileimageurl" [alt]="'core.pictureof' | translate:{$a: user.fullname}" core-external-content>
|
||||
</ion-avatar>
|
||||
<span *ngIf="user.profileimageurl === true" item-start>
|
||||
<ion-icon name="person"></ion-icon>
|
||||
|
|
|
@ -11,6 +11,7 @@ core-empty-box {
|
|||
margin: 0;
|
||||
padding: 0;
|
||||
clear: both;
|
||||
pointer-events: none;
|
||||
|
||||
.core-empty-box-content {
|
||||
color: $black;
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
<!-- Course summary. By default we only display the course progress. -->
|
||||
<core-dynamic-component [component]="courseSummaryComponent" [data]="data">
|
||||
<ion-list no-lines>
|
||||
<div *ngIf="course.imageThumb" class="core-course-thumb">
|
||||
<img [src]="course.imageThumb" core-external-content alt=""/>
|
||||
</div>
|
||||
<ion-item *ngIf="course.progress != null && course.progress >= 0">
|
||||
<core-progress-bar [progress]="course.progress"></core-progress-bar>
|
||||
</ion-item>
|
||||
|
|
|
@ -3,4 +3,23 @@ ion-badge.core-course-download-section-progress {
|
|||
float: left;
|
||||
margin-top: 12px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
core-course-format {
|
||||
.core-course-thumb {
|
||||
height: 150px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
position: relative;
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -252,7 +252,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
/**
|
||||
* Calculate the status of sections.
|
||||
*
|
||||
* @param {boolean} refresh [description]
|
||||
* @param {boolean} refresh If refresh or not.
|
||||
*/
|
||||
protected calculateSectionsStatus(refresh?: boolean): void {
|
||||
this.courseHelper.calculateSectionsStatus(this.sections, this.course.id, refresh).catch(() => {
|
||||
|
|
|
@ -204,6 +204,19 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
});
|
||||
}));
|
||||
|
||||
// Get the overview files.
|
||||
if (this.course.overviewfiles) {
|
||||
this.course.imageThumb = this.course.overviewfiles[0] && this.course.overviewfiles[0].fileurl;
|
||||
} else {
|
||||
promises.push(this.coursesProvider.getCoursesByField('id', this.course.id).then((coursesInfo) => {
|
||||
if (coursesInfo[0] && coursesInfo[0].overviewfiles && coursesInfo[0].overviewfiles[0]) {
|
||||
this.course.imageThumb = coursesInfo[0].overviewfiles[0].fileurl;
|
||||
} else {
|
||||
this.course.imageThumb = false;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// Load the course handlers.
|
||||
promises.push(this.courseOptionsDelegate.getHandlersToDisplay(this.injector, this.course, refresh, false)
|
||||
.then((handlers) => {
|
||||
|
@ -265,6 +278,7 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
promises.push(this.courseProvider.invalidateSections(this.course.id));
|
||||
promises.push(this.coursesProvider.invalidateUserCourses());
|
||||
promises.push(this.courseFormatDelegate.invalidateData(this.course, this.sections));
|
||||
promises.push(this.coursesProvider.invalidateCoursesByField('id', this.course.id));
|
||||
|
||||
if (this.sections) {
|
||||
promises.push(this.prefetchDelegate.invalidateCourseUpdates(this.course.id));
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
<ion-card>
|
||||
<div (click)="openCourse(course)" class="core-course-thumb core-course-color-{{course.id % 10}}">
|
||||
<img *ngIf="course.imageThumb" [src]="course.imageThumb" core-external-content alt=""/>
|
||||
</div>
|
||||
<ion-item tappable text-wrap detail-none (click)="openCourse(course)" [title]="course.fullname" class="core-course-link">
|
||||
<h2><core-format-text [text]="course.fullname"></core-format-text></h2>
|
||||
|
||||
|
|
|
@ -2,9 +2,32 @@ core-courses-course-progress {
|
|||
ion-card.card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.core-course-thumb {
|
||||
height: 150px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
position: relative;
|
||||
|
||||
@for $i from 0 to length($core-course-image-background) {
|
||||
&.core-course-color-#{$i} {
|
||||
background: nth($core-course-image-background, $i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.core-course-link {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
.item-inner {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
<core-loading [hideUntil]="dataLoaded">
|
||||
|
||||
<ion-list *ngIf="course">
|
||||
<div *ngIf="course.imageThumb" (click)="openCourse()" class="core-course-thumb">
|
||||
<img [src]="course.imageThumb" core-external-content alt=""/>
|
||||
</div>
|
||||
<a ion-item text-wrap (click)="openCourse()" [title]="course.fullname" [attr.detail-none]="!canAccessCourse">
|
||||
<ion-icon name="ionic" item-start></ion-icon>
|
||||
<h2><core-format-text [text]="course.fullname"></core-format-text></h2>
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
page-core-courses-course-preview {
|
||||
.core-course-thumb {
|
||||
height: 150px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
position: relative;
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,6 +96,9 @@ export class CoreCoursesCoursePreviewPage implements OnDestroy {
|
|||
this.enrolUrl = this.textUtils.concatenatePaths(currentSiteUrl, 'enrol/index.php?id=' + this.course.id);
|
||||
this.courseUrl = this.textUtils.concatenatePaths(currentSiteUrl, 'course/view.php?id=' + this.course.id);
|
||||
this.paypalReturnUrl = this.textUtils.concatenatePaths(currentSiteUrl, 'enrol/paypal/return.php');
|
||||
if (this.course.overviewfiles && this.course.overviewfiles.length > 0) {
|
||||
this.course.imageThumb = this.course.overviewfiles[0].fileurl;
|
||||
}
|
||||
|
||||
// Initialize the self enrol modal.
|
||||
this.selfEnrolModal = this.modalCtrl.create('CoreCoursesSelfEnrolPasswordPage');
|
||||
|
|
|
@ -17,6 +17,7 @@ import { IonicPage, NavController } from 'ionic-angular';
|
|||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreCoursesProvider } from '../../providers/courses';
|
||||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||
import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate';
|
||||
|
@ -43,11 +44,12 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
|
|||
protected myCoursesObserver;
|
||||
protected siteUpdatedObserver;
|
||||
protected isDestroyed = false;
|
||||
protected courseIds = '';
|
||||
|
||||
constructor(private navCtrl: NavController, private coursesProvider: CoreCoursesProvider,
|
||||
private domUtils: CoreDomUtilsProvider, private eventsProvider: CoreEventsProvider,
|
||||
private sitesProvider: CoreSitesProvider, private courseHelper: CoreCourseHelperProvider,
|
||||
private courseOptionsDelegate: CoreCourseOptionsDelegate) { }
|
||||
private courseOptionsDelegate: CoreCourseOptionsDelegate, private utils: CoreUtilsProvider) { }
|
||||
|
||||
/**
|
||||
* View loaded.
|
||||
|
@ -85,16 +87,33 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
|
|||
*/
|
||||
protected fetchCourses(): Promise<any> {
|
||||
return this.coursesProvider.getUserCourses().then((courses) => {
|
||||
|
||||
const courseIds = courses.map((course) => {
|
||||
const promises = [],
|
||||
courseIds = courses.map((course) => {
|
||||
return course.id;
|
||||
});
|
||||
|
||||
return this.coursesProvider.getCoursesAdminAndNavOptions(courseIds).then((options) => {
|
||||
this.courseIds = courseIds.join(',');
|
||||
|
||||
// Load course image of all the courses.
|
||||
promises.push(this.coursesProvider.getCoursesByField('ids', this.courseIds).then((coursesInfo) => {
|
||||
coursesInfo = this.utils.arrayToObject(coursesInfo, 'id');
|
||||
courses.forEach((course) => {
|
||||
if (coursesInfo[course.id] && coursesInfo[course.id].overviewfiles && coursesInfo[course.id].overviewfiles[0]) {
|
||||
course.imageThumb = coursesInfo[course.id].overviewfiles[0].fileurl;
|
||||
} else {
|
||||
course.imageThumb = false;
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
promises.push(this.coursesProvider.getCoursesAdminAndNavOptions(courseIds).then((options) => {
|
||||
courses.forEach((course) => {
|
||||
course.navOptions = options.navOptions[course.id];
|
||||
course.admOptions = options.admOptions[course.id];
|
||||
});
|
||||
}));
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
this.courses = courses;
|
||||
this.filteredCourses = this.courses;
|
||||
this.filter = '';
|
||||
|
@ -116,6 +135,7 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
|
|||
|
||||
promises.push(this.coursesProvider.invalidateUserCourses());
|
||||
promises.push(this.courseOptionsDelegate.clearAndInvalidateCoursesOptions());
|
||||
promises.push(this.coursesProvider.invalidateCoursesByField('ids', this.courseIds));
|
||||
|
||||
Promise.all(promises).finally(() => {
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import { IonicPage, NavController } from 'ionic-angular';
|
|||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreCoursesProvider } from '../../providers/courses';
|
||||
import { CoreCoursesMyOverviewProvider } from '../../providers/my-overview';
|
||||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||
|
@ -70,12 +71,13 @@ export class CoreCoursesMyOverviewPage implements OnDestroy {
|
|||
protected prefetchIconsInitialized = false;
|
||||
protected isDestroyed;
|
||||
protected updateSiteObserver;
|
||||
protected courseIds = '';
|
||||
|
||||
constructor(private navCtrl: NavController, private coursesProvider: CoreCoursesProvider,
|
||||
private domUtils: CoreDomUtilsProvider, private myOverviewProvider: CoreCoursesMyOverviewProvider,
|
||||
private courseHelper: CoreCourseHelperProvider, private sitesProvider: CoreSitesProvider,
|
||||
private siteHomeProvider: CoreSiteHomeProvider, private courseOptionsDelegate: CoreCourseOptionsDelegate,
|
||||
private eventsProvider: CoreEventsProvider) {
|
||||
private eventsProvider: CoreEventsProvider, private utils: CoreUtilsProvider) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -198,17 +200,34 @@ export class CoreCoursesMyOverviewPage implements OnDestroy {
|
|||
*/
|
||||
protected fetchUserCourses(): Promise<any> {
|
||||
return this.coursesProvider.getUserCourses().then((courses) => {
|
||||
const courseIds = courses.map((course) => {
|
||||
const promises = [],
|
||||
courseIds = courses.map((course) => {
|
||||
return course.id;
|
||||
});
|
||||
|
||||
// Load course options of the course.
|
||||
return this.coursesProvider.getCoursesAdminAndNavOptions(courseIds).then((options) => {
|
||||
promises.push(this.coursesProvider.getCoursesAdminAndNavOptions(courseIds).then((options) => {
|
||||
courses.forEach((course) => {
|
||||
course.navOptions = options.navOptions[course.id];
|
||||
course.admOptions = options.admOptions[course.id];
|
||||
});
|
||||
}));
|
||||
|
||||
this.courseIds = courseIds.join(',');
|
||||
|
||||
// Load course image of all the courses.
|
||||
promises.push(this.coursesProvider.getCoursesByField('ids', this.courseIds).then((coursesInfo) => {
|
||||
coursesInfo = this.utils.arrayToObject(coursesInfo, 'id');
|
||||
courses.forEach((course) => {
|
||||
if (coursesInfo[course.id] && coursesInfo[course.id].overviewfiles && coursesInfo[course.id].overviewfiles[0]) {
|
||||
course.imageThumb = coursesInfo[course.id].overviewfiles[0].fileurl;
|
||||
} else {
|
||||
course.imageThumb = false;
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
return courses.sort((a, b) => {
|
||||
const compareA = a.fullname.toLowerCase(),
|
||||
compareB = b.fullname.toLowerCase();
|
||||
|
@ -260,6 +279,7 @@ export class CoreCoursesMyOverviewPage implements OnDestroy {
|
|||
|
||||
promises.push(this.coursesProvider.invalidateUserCourses());
|
||||
promises.push(this.courseOptionsDelegate.clearAndInvalidateCoursesOptions());
|
||||
promises.push(this.coursesProvider.invalidateCoursesByField('ids', this.courseIds));
|
||||
|
||||
return Promise.all(promises).finally(() => {
|
||||
switch (this.tabShown) {
|
||||
|
|
|
@ -50,6 +50,8 @@ $core-color: $orange;
|
|||
$core-color-light: lighten($core-color, 10%);
|
||||
$core-color-dark: darken($core-color, 10%);
|
||||
|
||||
$core-course-image-background: #81ecec, #74b9ff, #a29bfe, #dfe6e9, #00b894, #0984e3, #b2bec3, #fdcb6e, #fd79a8, #6c5ce7;
|
||||
|
||||
// Shared Variables
|
||||
// --------------------------------------------------
|
||||
// To customize the look and feel of this app, you can override
|
||||
|
|
Loading…
Reference in New Issue