MOBILE-3686 courses: Add download options to course list item
parent
8acb8b74e2
commit
ad45289f4b
|
@ -34,4 +34,14 @@
|
||||||
slot="end">
|
slot="end">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<div class="core-button-spinner" *ngIf="isEnrolled && showDownload" slot="end">
|
||||||
|
<core-download-refresh
|
||||||
|
[status]="prefetchCourseData.status"
|
||||||
|
[statusTranslatable]="prefetchCourseData.statusTranslatable"
|
||||||
|
[enabled]="true"
|
||||||
|
canTrustDownload="false"
|
||||||
|
[loading]="prefetchCourseData.loading"
|
||||||
|
(action)="prefetchCourse()"></core-download-refresh>
|
||||||
|
</div>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
|
@ -12,8 +12,9 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
import { CoreCourseProvider, CoreCourse } from '@features/course/services/course';
|
||||||
|
import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
@ -33,15 +34,26 @@ import { CoreCoursesHelper } from '../../services/courses-helper';
|
||||||
templateUrl: 'core-courses-course-list-item.html',
|
templateUrl: 'core-courses-course-list-item.html',
|
||||||
styleUrls: ['course-list-item.scss'],
|
styleUrls: ['course-list-item.scss'],
|
||||||
})
|
})
|
||||||
export class CoreCoursesCourseListItemComponent implements OnInit {
|
export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, OnChanges {
|
||||||
|
|
||||||
@Input() course!: CoreCourseListItem; // The course to render.
|
@Input() course!: CoreCourseListItem; // The course to render.
|
||||||
|
|
||||||
|
@Input() showDownload = false; // If true, will show download button.
|
||||||
|
|
||||||
icons: CoreCoursesEnrolmentIcons[] = [];
|
icons: CoreCoursesEnrolmentIcons[] = [];
|
||||||
isEnrolled = false;
|
isEnrolled = false;
|
||||||
|
prefetchCourseData: CorePrefetchStatusInfo = {
|
||||||
|
icon: '',
|
||||||
|
statusTranslatable: 'core.loading',
|
||||||
|
status: '',
|
||||||
|
loading: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
protected courseStatusObserver?: CoreEventObserver;
|
||||||
|
protected isDestroyed = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component being initialized.
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
CoreCoursesHelper.loadCourseColorAndImage(this.course);
|
CoreCoursesHelper.loadCourseColorAndImage(this.course);
|
||||||
|
@ -55,6 +67,10 @@ export class CoreCoursesCourseListItemComponent implements OnInit {
|
||||||
this.course.completionusertracked = course.completionusertracked;
|
this.course.completionusertracked = course.completionusertracked;
|
||||||
|
|
||||||
this.isEnrolled = true;
|
this.isEnrolled = true;
|
||||||
|
|
||||||
|
if (this.showDownload) {
|
||||||
|
this.initPrefetchCourse();
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
this.isEnrolled = false;
|
this.isEnrolled = false;
|
||||||
}
|
}
|
||||||
|
@ -91,6 +107,15 @@ export class CoreCoursesCourseListItemComponent implements OnInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
ngOnChanges(): void {
|
||||||
|
if (this.showDownload && this.isEnrolled) {
|
||||||
|
this.initPrefetchCourse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a course.
|
* Open a course.
|
||||||
*
|
*
|
||||||
|
@ -107,6 +132,85 @@ export class CoreCoursesCourseListItemComponent implements OnInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize prefetch course.
|
||||||
|
*/
|
||||||
|
async initPrefetchCourse(): Promise<void> {
|
||||||
|
if (this.courseStatusObserver !== undefined) {
|
||||||
|
// Already initialized.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for status change in course.
|
||||||
|
this.courseStatusObserver = CoreEvents.on(CoreEvents.COURSE_STATUS_CHANGED, (data: CoreEventCourseStatusChanged) => {
|
||||||
|
if (data.courseId == this.course.id || data.courseId == CoreCourseProvider.ALL_COURSES_CLEARED) {
|
||||||
|
this.updateCourseStatus(data.status);
|
||||||
|
}
|
||||||
|
}, CoreSites.getCurrentSiteId());
|
||||||
|
|
||||||
|
// Determine course prefetch icon.
|
||||||
|
const status = await CoreCourse.getCourseStatus(this.course.id);
|
||||||
|
|
||||||
|
this.updateCourseStatus(status);
|
||||||
|
|
||||||
|
if (this.prefetchCourseData.loading) {
|
||||||
|
// Course is being downloaded. Get the download promise.
|
||||||
|
const promise = CoreCourseHelper.getCourseDownloadPromise(this.course.id);
|
||||||
|
if (promise) {
|
||||||
|
// There is a download promise. If it fails, show an error.
|
||||||
|
promise.catch((error) => {
|
||||||
|
if (!this.isDestroyed) {
|
||||||
|
CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// No download, this probably means that the app was closed while downloading. Set previous status.
|
||||||
|
CoreCourse.setCoursePreviousStatus(this.course.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the course status icon and title.
|
||||||
|
*
|
||||||
|
* @param status Status to show.
|
||||||
|
*/
|
||||||
|
protected updateCourseStatus(status: string): void {
|
||||||
|
const statusData = CoreCourseHelper.getCoursePrefetchStatusInfo(status);
|
||||||
|
|
||||||
|
this.prefetchCourseData.status = statusData.status;
|
||||||
|
this.prefetchCourseData.icon = statusData.icon;
|
||||||
|
this.prefetchCourseData.statusTranslatable = statusData.statusTranslatable;
|
||||||
|
this.prefetchCourseData.loading = statusData.loading;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefetch the course.
|
||||||
|
*
|
||||||
|
* @param e Click event.
|
||||||
|
*/
|
||||||
|
async prefetchCourse(e?: Event): Promise<void> {
|
||||||
|
e?.preventDefault();
|
||||||
|
e?.stopPropagation();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await CoreCourseHelper.confirmAndPrefetchCourse(this.prefetchCourseData, this.course);
|
||||||
|
} catch (error) {
|
||||||
|
if (!this.isDestroyed) {
|
||||||
|
CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.isDestroyed = true;
|
||||||
|
this.courseStatusObserver?.off();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -48,8 +48,6 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy, On
|
||||||
@Input() showAll = false; // If true, will show all actions, options, star and progress.
|
@Input() showAll = false; // If true, will show all actions, options, star and progress.
|
||||||
@Input() showDownload = true; // If true, will show download button. Only works if the options menu is not shown.
|
@Input() showDownload = true; // If true, will show download button. Only works if the options menu is not shown.
|
||||||
|
|
||||||
courseStatus = CoreConstants.NOT_DOWNLOADED;
|
|
||||||
isDownloading = false;
|
|
||||||
prefetchCourseData: CorePrefetchStatusInfo = {
|
prefetchCourseData: CorePrefetchStatusInfo = {
|
||||||
icon: '',
|
icon: '',
|
||||||
statusTranslatable: 'core.loading',
|
statusTranslatable: 'core.loading',
|
||||||
|
@ -64,6 +62,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy, On
|
||||||
progress = -1;
|
progress = -1;
|
||||||
completionUserTracked: boolean | undefined = false;
|
completionUserTracked: boolean | undefined = false;
|
||||||
|
|
||||||
|
protected courseStatus = CoreConstants.NOT_DOWNLOADED;
|
||||||
protected isDestroyed = false;
|
protected isDestroyed = false;
|
||||||
protected courseStatusObserver?: CoreEventObserver;
|
protected courseStatusObserver?: CoreEventObserver;
|
||||||
protected siteUpdatedObserver?: CoreEventObserver;
|
protected siteUpdatedObserver?: CoreEventObserver;
|
||||||
|
@ -109,7 +108,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy, On
|
||||||
* Initialize prefetch course.
|
* Initialize prefetch course.
|
||||||
*/
|
*/
|
||||||
async initPrefetchCourse(): Promise<void> {
|
async initPrefetchCourse(): Promise<void> {
|
||||||
if (typeof this.courseStatusObserver != 'undefined') {
|
if (this.courseStatusObserver !== undefined) {
|
||||||
// Already initialized.
|
// Already initialized.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,8 @@
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<core-courses-course-list-item *ngFor="let course of courses" [course]="course"></core-courses-course-list-item>
|
<core-courses-course-list-item *ngFor="let course of courses" [course]="course" [showDownload]="downloadEnabled">
|
||||||
|
</core-courses-course-list-item>
|
||||||
|
|
||||||
<core-infinite-loading [enabled]="searchMode && searchCanLoadMore" (action)="loadMoreResults($event)" [error]="searchLoadMoreError">
|
<core-infinite-loading [enabled]="searchMode && searchCanLoadMore" (action)="loadMoreResults($event)" [error]="searchLoadMoreError">
|
||||||
</core-infinite-loading>
|
</core-infinite-loading>
|
||||||
|
|
Loading…
Reference in New Issue