commit
1218621389
|
@ -29,7 +29,7 @@
|
||||||
<ion-card *ngIf="user">
|
<ion-card *ngIf="user">
|
||||||
<ion-item text-wrap>
|
<ion-item text-wrap>
|
||||||
<ion-avatar *ngIf="user.profileimageurl && user.profileimageurl !== true" item-start>
|
<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>
|
</ion-avatar>
|
||||||
<span *ngIf="user.profileimageurl === true" item-start>
|
<span *ngIf="user.profileimageurl === true" item-start>
|
||||||
<ion-icon name="person"></ion-icon>
|
<ion-icon name="person"></ion-icon>
|
||||||
|
|
|
@ -11,6 +11,7 @@ core-empty-box {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
clear: both;
|
clear: both;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
.core-empty-box-content {
|
.core-empty-box-content {
|
||||||
color: $black;
|
color: $black;
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
<!-- Course summary. By default we only display the course progress. -->
|
<!-- Course summary. By default we only display the course progress. -->
|
||||||
<core-dynamic-component [component]="courseSummaryComponent" [data]="data">
|
<core-dynamic-component [component]="courseSummaryComponent" [data]="data">
|
||||||
<ion-list no-lines>
|
<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">
|
<ion-item *ngIf="course.progress != null && course.progress >= 0">
|
||||||
<core-progress-bar [progress]="course.progress"></core-progress-bar>
|
<core-progress-bar [progress]="course.progress"></core-progress-bar>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
|
@ -3,4 +3,23 @@ ion-badge.core-course-download-section-progress {
|
||||||
float: left;
|
float: left;
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
margin-right: 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.
|
* Calculate the status of sections.
|
||||||
*
|
*
|
||||||
* @param {boolean} refresh [description]
|
* @param {boolean} refresh If refresh or not.
|
||||||
*/
|
*/
|
||||||
protected calculateSectionsStatus(refresh?: boolean): void {
|
protected calculateSectionsStatus(refresh?: boolean): void {
|
||||||
this.courseHelper.calculateSectionsStatus(this.sections, this.course.id, refresh).catch(() => {
|
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.
|
// Load the course handlers.
|
||||||
promises.push(this.courseOptionsDelegate.getHandlersToDisplay(this.injector, this.course, refresh, false)
|
promises.push(this.courseOptionsDelegate.getHandlersToDisplay(this.injector, this.course, refresh, false)
|
||||||
.then((handlers) => {
|
.then((handlers) => {
|
||||||
|
@ -265,6 +278,7 @@ export class CoreCourseSectionPage implements OnDestroy {
|
||||||
promises.push(this.courseProvider.invalidateSections(this.course.id));
|
promises.push(this.courseProvider.invalidateSections(this.course.id));
|
||||||
promises.push(this.coursesProvider.invalidateUserCourses());
|
promises.push(this.coursesProvider.invalidateUserCourses());
|
||||||
promises.push(this.courseFormatDelegate.invalidateData(this.course, this.sections));
|
promises.push(this.courseFormatDelegate.invalidateData(this.course, this.sections));
|
||||||
|
promises.push(this.coursesProvider.invalidateCoursesByField('id', this.course.id));
|
||||||
|
|
||||||
if (this.sections) {
|
if (this.sections) {
|
||||||
promises.push(this.prefetchDelegate.invalidateCourseUpdates(this.course.id));
|
promises.push(this.prefetchDelegate.invalidateCourseUpdates(this.course.id));
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
<ion-card>
|
<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">
|
<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>
|
<h2><core-format-text [text]="course.fullname"></core-format-text></h2>
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,32 @@ core-courses-course-progress {
|
||||||
ion-card.card {
|
ion-card.card {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
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 {
|
.core-course-link {
|
||||||
|
padding-top: 8px;
|
||||||
|
padding-bottom: 8px;
|
||||||
.item-inner {
|
.item-inner {
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
<core-loading [hideUntil]="dataLoaded">
|
<core-loading [hideUntil]="dataLoaded">
|
||||||
|
|
||||||
<ion-list *ngIf="course">
|
<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">
|
<a ion-item text-wrap (click)="openCourse()" [title]="course.fullname" [attr.detail-none]="!canAccessCourse">
|
||||||
<ion-icon name="ionic" item-start></ion-icon>
|
<ion-icon name="ionic" item-start></ion-icon>
|
||||||
<h2><core-format-text [text]="course.fullname"></core-format-text></h2>
|
<h2><core-format-text [text]="course.fullname"></core-format-text></h2>
|
||||||
|
|
|
@ -1,3 +1,18 @@
|
||||||
page-core-courses-course-preview {
|
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.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.courseUrl = this.textUtils.concatenatePaths(currentSiteUrl, 'course/view.php?id=' + this.course.id);
|
||||||
this.paypalReturnUrl = this.textUtils.concatenatePaths(currentSiteUrl, 'enrol/paypal/return.php');
|
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.
|
// Initialize the self enrol modal.
|
||||||
this.selfEnrolModal = this.modalCtrl.create('CoreCoursesSelfEnrolPasswordPage');
|
this.selfEnrolModal = this.modalCtrl.create('CoreCoursesSelfEnrolPasswordPage');
|
||||||
|
|
|
@ -17,6 +17,7 @@ import { IonicPage, NavController } from 'ionic-angular';
|
||||||
import { CoreEventsProvider } from '@providers/events';
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { CoreCoursesProvider } from '../../providers/courses';
|
import { CoreCoursesProvider } from '../../providers/courses';
|
||||||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||||
import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate';
|
import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate';
|
||||||
|
@ -43,11 +44,12 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
|
||||||
protected myCoursesObserver;
|
protected myCoursesObserver;
|
||||||
protected siteUpdatedObserver;
|
protected siteUpdatedObserver;
|
||||||
protected isDestroyed = false;
|
protected isDestroyed = false;
|
||||||
|
protected courseIds = '';
|
||||||
|
|
||||||
constructor(private navCtrl: NavController, private coursesProvider: CoreCoursesProvider,
|
constructor(private navCtrl: NavController, private coursesProvider: CoreCoursesProvider,
|
||||||
private domUtils: CoreDomUtilsProvider, private eventsProvider: CoreEventsProvider,
|
private domUtils: CoreDomUtilsProvider, private eventsProvider: CoreEventsProvider,
|
||||||
private sitesProvider: CoreSitesProvider, private courseHelper: CoreCourseHelperProvider,
|
private sitesProvider: CoreSitesProvider, private courseHelper: CoreCourseHelperProvider,
|
||||||
private courseOptionsDelegate: CoreCourseOptionsDelegate) { }
|
private courseOptionsDelegate: CoreCourseOptionsDelegate, private utils: CoreUtilsProvider) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View loaded.
|
* View loaded.
|
||||||
|
@ -85,16 +87,33 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
|
||||||
*/
|
*/
|
||||||
protected fetchCourses(): Promise<any> {
|
protected fetchCourses(): Promise<any> {
|
||||||
return this.coursesProvider.getUserCourses().then((courses) => {
|
return this.coursesProvider.getUserCourses().then((courses) => {
|
||||||
|
const promises = [],
|
||||||
const courseIds = courses.map((course) => {
|
courseIds = courses.map((course) => {
|
||||||
return course.id;
|
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) => {
|
courses.forEach((course) => {
|
||||||
course.navOptions = options.navOptions[course.id];
|
course.navOptions = options.navOptions[course.id];
|
||||||
course.admOptions = options.admOptions[course.id];
|
course.admOptions = options.admOptions[course.id];
|
||||||
});
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
return Promise.all(promises).then(() => {
|
||||||
this.courses = courses;
|
this.courses = courses;
|
||||||
this.filteredCourses = this.courses;
|
this.filteredCourses = this.courses;
|
||||||
this.filter = '';
|
this.filter = '';
|
||||||
|
@ -116,6 +135,7 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
|
||||||
|
|
||||||
promises.push(this.coursesProvider.invalidateUserCourses());
|
promises.push(this.coursesProvider.invalidateUserCourses());
|
||||||
promises.push(this.courseOptionsDelegate.clearAndInvalidateCoursesOptions());
|
promises.push(this.courseOptionsDelegate.clearAndInvalidateCoursesOptions());
|
||||||
|
promises.push(this.coursesProvider.invalidateCoursesByField('ids', this.courseIds));
|
||||||
|
|
||||||
Promise.all(promises).finally(() => {
|
Promise.all(promises).finally(() => {
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import { IonicPage, NavController } from 'ionic-angular';
|
||||||
import { CoreEventsProvider } from '@providers/events';
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { CoreCoursesProvider } from '../../providers/courses';
|
import { CoreCoursesProvider } from '../../providers/courses';
|
||||||
import { CoreCoursesMyOverviewProvider } from '../../providers/my-overview';
|
import { CoreCoursesMyOverviewProvider } from '../../providers/my-overview';
|
||||||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||||
|
@ -70,12 +71,13 @@ export class CoreCoursesMyOverviewPage implements OnDestroy {
|
||||||
protected prefetchIconsInitialized = false;
|
protected prefetchIconsInitialized = false;
|
||||||
protected isDestroyed;
|
protected isDestroyed;
|
||||||
protected updateSiteObserver;
|
protected updateSiteObserver;
|
||||||
|
protected courseIds = '';
|
||||||
|
|
||||||
constructor(private navCtrl: NavController, private coursesProvider: CoreCoursesProvider,
|
constructor(private navCtrl: NavController, private coursesProvider: CoreCoursesProvider,
|
||||||
private domUtils: CoreDomUtilsProvider, private myOverviewProvider: CoreCoursesMyOverviewProvider,
|
private domUtils: CoreDomUtilsProvider, private myOverviewProvider: CoreCoursesMyOverviewProvider,
|
||||||
private courseHelper: CoreCourseHelperProvider, private sitesProvider: CoreSitesProvider,
|
private courseHelper: CoreCourseHelperProvider, private sitesProvider: CoreSitesProvider,
|
||||||
private siteHomeProvider: CoreSiteHomeProvider, private courseOptionsDelegate: CoreCourseOptionsDelegate,
|
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> {
|
protected fetchUserCourses(): Promise<any> {
|
||||||
return this.coursesProvider.getUserCourses().then((courses) => {
|
return this.coursesProvider.getUserCourses().then((courses) => {
|
||||||
const courseIds = courses.map((course) => {
|
const promises = [],
|
||||||
|
courseIds = courses.map((course) => {
|
||||||
return course.id;
|
return course.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load course options of the course.
|
// Load course options of the course.
|
||||||
return this.coursesProvider.getCoursesAdminAndNavOptions(courseIds).then((options) => {
|
promises.push(this.coursesProvider.getCoursesAdminAndNavOptions(courseIds).then((options) => {
|
||||||
courses.forEach((course) => {
|
courses.forEach((course) => {
|
||||||
course.navOptions = options.navOptions[course.id];
|
course.navOptions = options.navOptions[course.id];
|
||||||
course.admOptions = options.admOptions[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) => {
|
return courses.sort((a, b) => {
|
||||||
const compareA = a.fullname.toLowerCase(),
|
const compareA = a.fullname.toLowerCase(),
|
||||||
compareB = b.fullname.toLowerCase();
|
compareB = b.fullname.toLowerCase();
|
||||||
|
@ -260,6 +279,7 @@ export class CoreCoursesMyOverviewPage implements OnDestroy {
|
||||||
|
|
||||||
promises.push(this.coursesProvider.invalidateUserCourses());
|
promises.push(this.coursesProvider.invalidateUserCourses());
|
||||||
promises.push(this.courseOptionsDelegate.clearAndInvalidateCoursesOptions());
|
promises.push(this.courseOptionsDelegate.clearAndInvalidateCoursesOptions());
|
||||||
|
promises.push(this.coursesProvider.invalidateCoursesByField('ids', this.courseIds));
|
||||||
|
|
||||||
return Promise.all(promises).finally(() => {
|
return Promise.all(promises).finally(() => {
|
||||||
switch (this.tabShown) {
|
switch (this.tabShown) {
|
||||||
|
|
|
@ -50,6 +50,8 @@ $core-color: $orange;
|
||||||
$core-color-light: lighten($core-color, 10%);
|
$core-color-light: lighten($core-color, 10%);
|
||||||
$core-color-dark: darken($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
|
// Shared Variables
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// To customize the look and feel of this app, you can override
|
// To customize the look and feel of this app, you can override
|
||||||
|
|
Loading…
Reference in New Issue