MOBILE-2380 course: Allow disabling download course and all courses

main
Dani Palou 2018-05-18 15:32:43 +02:00
parent a340c28cbf
commit de410c89b4
11 changed files with 161 additions and 31 deletions

View File

@ -13,7 +13,7 @@
<core-navbar-buttons>
<core-context-menu>
<core-context-menu-item *ngIf="displayEnableDownload" [priority]="2000" [content]="'core.settings.enabledownloadsection' | translate" (action)="toggleDownload()" [iconAction]="downloadEnabledIcon"></core-context-menu-item>
<core-context-menu-item [priority]="1900" [content]="prefetchCourseData.title | translate" (action)="prefetchCourse()" [iconAction]="prefetchCourseData.prefetchCourseIcon" [closeOnClick]="false"></core-context-menu-item>
<core-context-menu-item [hidden]="!downloadCourseEnabled" [priority]="1900" [content]="prefetchCourseData.title | translate" (action)="prefetchCourse()" [iconAction]="prefetchCourseData.prefetchCourseIcon" [closeOnClick]="false"></core-context-menu-item>
</core-context-menu>
</core-navbar-buttons>
<ion-content>

View File

@ -52,6 +52,7 @@ export class CoreCourseSectionPage implements OnDestroy {
prefetchCourseIcon: 'spinner',
title: 'core.course.downloadcourse'
};
downloadCourseEnabled: boolean;
moduleId: number;
displayEnableDownload: boolean;
displayRefresher: boolean;
@ -75,6 +76,7 @@ export class CoreCourseSectionPage implements OnDestroy {
// Get the title to display. We dont't have sections yet.
this.title = courseFormatDelegate.getCourseTitle(this.course);
this.displayEnableDownload = courseFormatDelegate.displayEnableDownload(this.course);
this.downloadCourseEnabled = !this.coursesProvider.isDownloadCourseDisabledInSite();
this.completionObserver = eventsProvider.on(CoreEventsProvider.COMPLETION_MODULE_VIEWED, (data) => {
if (data && data.courseId == this.course.id) {
@ -82,12 +84,14 @@ export class CoreCourseSectionPage implements OnDestroy {
}
});
// Listen for changes in course status.
this.courseStatusObserver = eventsProvider.on(CoreEventsProvider.COURSE_STATUS_CHANGED, (data) => {
if (data.courseId == this.course.id) {
this.updateCourseStatus(data.status);
}
}, sitesProvider.getCurrentSiteId());
if (this.downloadCourseEnabled) {
// Listen for changes in course status.
this.courseStatusObserver = eventsProvider.on(CoreEventsProvider.COURSE_STATUS_CHANGED, (data) => {
if (data.courseId == this.course.id) {
this.updateCourseStatus(data.status);
}
}, sitesProvider.getCurrentSiteId());
}
}
/**
@ -103,6 +107,11 @@ export class CoreCourseSectionPage implements OnDestroy {
this.loadData().finally(() => {
this.dataLoaded = true;
if (!this.downloadCourseEnabled) {
// Cannot download the whole course, stop.
return;
}
// Determine the course prefetch status.
this.determineCoursePrefetchIcon().then(() => {
if (this.prefetchCourseData.prefetchCourseIcon == 'spinner') {

View File

@ -2,7 +2,7 @@
<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>
<div class="core-button-spinner">
<div class="core-button-spinner" *ngIf="downloadCourseEnabled">
<!-- Download course. -->
<button *ngIf="prefetchCourseData.prefetchCourseIcon != 'spinner'" ion-button icon-only clear color="dark" (click)="prefetchCourse($event)" [attr.aria-label]="prefetchCourseData.title | translate">
<ion-icon [name]="prefetchCourseData.prefetchCourseIcon"></ion-icon>

View File

@ -17,6 +17,7 @@ import { NavController } from 'ionic-angular';
import { CoreEventsProvider } from '@providers/events';
import { CoreSitesProvider } from '@providers/sites';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreCoursesProvider } from '@core/courses/providers/courses';
import { CoreCourseFormatDelegate } from '@core/course/providers/format-delegate';
import { CoreCourseProvider } from '@core/course/providers/course';
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
@ -41,25 +42,56 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
prefetchCourseIcon: 'spinner',
title: 'core.course.downloadcourse'
};
downloadCourseEnabled: boolean;
protected isDestroyed = false;
protected courseStatusObserver;
protected siteUpdatedObserver;
constructor(@Optional() private navCtrl: NavController, private courseHelper: CoreCourseHelperProvider,
private courseFormatDelegate: CoreCourseFormatDelegate, private domUtils: CoreDomUtilsProvider,
private courseProvider: CoreCourseProvider, eventsProvider: CoreEventsProvider, sitesProvider: CoreSitesProvider) {
// Listen for status change in course.
this.courseStatusObserver = eventsProvider.on(CoreEventsProvider.COURSE_STATUS_CHANGED, (data) => {
if (data.courseId == this.course.id) {
this.updateCourseStatus(data.status);
}
}, sitesProvider.getCurrentSiteId());
}
private courseProvider: CoreCourseProvider, private eventsProvider: CoreEventsProvider,
private sitesProvider: CoreSitesProvider, private coursesProvider: CoreCoursesProvider) { }
/**
* Component being initialized.
*/
ngOnInit(): void {
this.downloadCourseEnabled = !this.coursesProvider.isDownloadCourseDisabledInSite();
if (this.downloadCourseEnabled) {
this.initPrefetchCourse();
}
// Refresh the enabled flag if site is updated.
this.siteUpdatedObserver = this.eventsProvider.on(CoreEventsProvider.SITE_UPDATED, () => {
const wasEnabled = this.downloadCourseEnabled;
this.downloadCourseEnabled = !this.coursesProvider.isDownloadCourseDisabledInSite();
if (!wasEnabled && this.downloadCourseEnabled) {
// Download course is enabled now, initialize it.
this.initPrefetchCourse();
}
}, this.sitesProvider.getCurrentSiteId());
}
/**
* Initialize prefetch course.
*/
initPrefetchCourse(): void {
if (typeof this.courseStatusObserver != 'undefined') {
// Already initialized.
return;
}
// Listen for status change in course.
this.courseStatusObserver = this.eventsProvider.on(CoreEventsProvider.COURSE_STATUS_CHANGED, (data) => {
if (data.courseId == this.course.id) {
this.updateCourseStatus(data.status);
}
}, this.sitesProvider.getCurrentSiteId());
// Determine course prefetch icon.
this.courseHelper.getCourseStatusIconAndTitle(this.course.id).then((data) => {
this.prefetchCourseData.prefetchCourseIcon = data.icon;
@ -81,6 +113,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
}
}
});
}
/**
@ -126,8 +159,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
ngOnDestroy(): void {
this.isDestroyed = true;
if (this.courseStatusObserver) {
this.courseStatusObserver.off();
}
this.siteUpdatedObserver && this.siteUpdatedObserver.off();
this.courseStatusObserver && this.courseStatusObserver.off();
}
}

View File

@ -41,7 +41,7 @@
<ion-item *ngIf="!isEnrolled && !selfEnrolInstances.length && !paypalEnabled">
<p>{{ 'core.courses.notenrollable' | translate }}</p>
</ion-item>
<a ion-item *ngIf="canAccessCourse" (click)="prefetchCourse()" detail-none [attr.aria-label]="prefetchCourseData.title | translate">
<a ion-item *ngIf="canAccessCourse && downloadCourseEnabled" (click)="prefetchCourse()" detail-none [attr.aria-label]="prefetchCourseData.title | translate">
<ion-icon *ngIf="prefetchCourseData.prefetchCourseIcon != 'spinner'" [name]="prefetchCourseData.prefetchCourseIcon" item-start></ion-icon>
<ion-spinner *ngIf="prefetchCourseData.prefetchCourseIcon == 'spinner'" item-start></ion-spinner>
<h2>{{ 'core.course.downloadcourse' | translate }}</h2>

View File

@ -45,6 +45,7 @@ export class CoreCoursesCoursePreviewPage implements OnDestroy {
prefetchCourseIcon: 'spinner',
title: 'core.course.downloadcourse'
};
downloadCourseEnabled: boolean;
protected guestWSAvailable: boolean;
protected isGuestEnabled = false;
@ -67,16 +68,20 @@ export class CoreCoursesCoursePreviewPage implements OnDestroy {
private translate: TranslateService, private eventsProvider: CoreEventsProvider,
private courseOptionsDelegate: CoreCourseOptionsDelegate, private courseHelper: CoreCourseHelperProvider,
private courseProvider: CoreCourseProvider) {
this.course = navParams.get('course');
this.isMobile = appProvider.isMobile();
this.isDesktop = appProvider.isDesktop();
this.downloadCourseEnabled = !this.coursesProvider.isDownloadCourseDisabledInSite();
// Listen for status change in course.
this.courseStatusObserver = eventsProvider.on(CoreEventsProvider.COURSE_STATUS_CHANGED, (data) => {
if (data.courseId == this.course.id) {
this.updateCourseStatus(data.status);
}
}, sitesProvider.getCurrentSiteId());
if (this.downloadCourseEnabled) {
// Listen for status change in course.
this.courseStatusObserver = this.eventsProvider.on(CoreEventsProvider.COURSE_STATUS_CHANGED, (data) => {
if (data.courseId == this.course.id) {
this.updateCourseStatus(data.status);
}
}, this.sitesProvider.getCurrentSiteId());
}
}
/**
@ -101,6 +106,11 @@ export class CoreCoursesCoursePreviewPage implements OnDestroy {
});
this.getCourse().finally(() => {
if (!this.downloadCourseEnabled) {
// Cannot download the whole course, stop.
return;
}
// Determine course prefetch icon.
this.courseHelper.getCourseStatusIconAndTitle(this.course.id).then((data) => {
this.prefetchCourseData.prefetchCourseIcon = data.icon;

View File

@ -7,7 +7,7 @@
<ion-icon name="search"></ion-icon>
</button>
<core-context-menu>
<core-context-menu-item [hidden]="!courses || courses.length < 2" [priority]="800" [content]="'core.courses.downloadcourses' | translate" (action)="prefetchCourses()" [iconAction]="prefetchCoursesData.icon" [closeOnClick]="false" [badge]="prefetchCoursesData.badge"></core-context-menu-item>
<core-context-menu-item [hidden]="!downloadAllCoursesEnabled || !courses || courses.length < 2" [priority]="800" [content]="'core.courses.downloadcourses' | translate" (action)="prefetchCourses()" [iconAction]="prefetchCoursesData.icon" [closeOnClick]="false" [badge]="prefetchCoursesData.badge"></core-context-menu-item>
<core-context-menu-item [hidden]="!courses || courses.length <= 5" [priority]="700" [content]="'core.courses.filtermycourses' | translate" (action)="switchFilter()" [iconAction]="'funnel'"></core-context-menu-item>
</core-context-menu>
</ion-buttons>

View File

@ -37,6 +37,7 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
showFilter = false;
coursesLoaded = false;
prefetchCoursesData: any = {};
downloadAllCoursesEnabled: boolean;
protected prefetchIconInitialized = false;
protected myCoursesObserver;
@ -53,6 +54,7 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
*/
ionViewDidLoad(): void {
this.searchEnabled = !this.coursesProvider.isSearchCoursesDisabledInSite();
this.downloadAllCoursesEnabled = !this.coursesProvider.isDownloadCoursesDisabledInSite();
this.fetchCourses().finally(() => {
this.coursesLoaded = true;
@ -62,8 +64,17 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
this.fetchCourses();
}, this.sitesProvider.getCurrentSiteId());
// Refresh the enabled flags if site is updated.
this.siteUpdatedObserver = this.eventsProvider.on(CoreEventsProvider.SITE_UPDATED, () => {
const wasEnabled = this.downloadAllCoursesEnabled;
this.searchEnabled = !this.coursesProvider.isSearchCoursesDisabledInSite();
this.downloadAllCoursesEnabled = !this.coursesProvider.isDownloadCoursesDisabledInSite();
if (!wasEnabled && this.downloadAllCoursesEnabled && this.coursesLoaded) {
// Download all courses is enabled now, initialize it.
this.initPrefetchCoursesIcon();
}
}, this.sitesProvider.getCurrentSiteId());
}
@ -176,7 +187,7 @@ export class CoreCoursesMyCoursesPage implements OnDestroy {
* Initialize the prefetch icon for the list of courses.
*/
protected initPrefetchCoursesIcon(): void {
if (this.prefetchIconInitialized) {
if (this.prefetchIconInitialized || !this.downloadAllCoursesEnabled) {
// Already initialized.
return;
}

View File

@ -71,7 +71,7 @@
<ion-option value="past">{{ 'core.courses.past' | translate }}</ion-option>
</ion-select>
<!-- Download all courses. -->
<div *ngIf="courses[courses.selected] && courses[courses.selected].length > 1" class="core-button-spinner" float-end>
<div *ngIf="downloadAllCoursesEnabled && courses[courses.selected] && courses[courses.selected].length > 1" class="core-button-spinner" float-end>
<button *ngIf="prefetchCoursesData[courses.selected].icon && prefetchCoursesData[courses.selected].icon != 'spinner'" ion-button icon-only clear color="dark" (click)="prefetchCourses()">
<ion-icon [name]="prefetchCoursesData[courses.selected].icon"></ion-icon>
</button>

View File

@ -14,6 +14,7 @@
import { Component, OnDestroy } from '@angular/core';
import { IonicPage, NavController } from 'ionic-angular';
import { CoreEventsProvider } from '@providers/events';
import { CoreSitesProvider } from '@providers/sites';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreCoursesProvider } from '../../providers/courses';
@ -64,20 +65,38 @@ export class CoreCoursesMyOverviewPage implements OnDestroy {
past: {},
future: {}
};
downloadAllCoursesEnabled: boolean;
protected prefetchIconsInitialized = false;
protected isDestroyed;
protected updateSiteObserver;
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 siteHomeProvider: CoreSiteHomeProvider, private courseOptionsDelegate: CoreCourseOptionsDelegate,
private eventsProvider: CoreEventsProvider) {
}
/**
* View loaded.
*/
ionViewDidLoad(): void {
this.searchEnabled = !this.coursesProvider.isSearchCoursesDisabledInSite();
this.downloadAllCoursesEnabled = !this.coursesProvider.isDownloadCoursesDisabledInSite();
// Refresh the enabled flags if site is updated.
this.updateSiteObserver = this.eventsProvider.on(CoreEventsProvider.SITE_UPDATED, () => {
const wasEnabled = this.downloadAllCoursesEnabled;
this.searchEnabled = !this.coursesProvider.isSearchCoursesDisabledInSite();
this.downloadAllCoursesEnabled = !this.coursesProvider.isDownloadCoursesDisabledInSite();
if (!wasEnabled && this.downloadAllCoursesEnabled && this.courses.loaded) {
// Download all courses is enabled now, initialize it.
this.initPrefetchCoursesIcons();
}
});
// Decide which tab to load first.
this.siteHomeProvider.isAvailable().then((enabled) => {
@ -378,7 +397,7 @@ export class CoreCoursesMyOverviewPage implements OnDestroy {
* Initialize the prefetch icon for selected courses.
*/
protected initPrefetchCoursesIcons(): void {
if (this.prefetchIconsInitialized) {
if (this.prefetchIconsInitialized || !this.downloadAllCoursesEnabled) {
// Already initialized.
return;
}
@ -410,5 +429,6 @@ export class CoreCoursesMyOverviewPage implements OnDestroy {
*/
ngOnDestroy(): void {
this.isDestroyed = true;
this.updateSiteObserver && this.updateSiteObserver.off();
}
}

View File

@ -120,6 +120,54 @@ export class CoreCoursesProvider {
});
}
/**
* Check if download a whole course is disabled in a certain site.
*
* @param {string} [siteId] Site Id. If not defined, use current site.
* @return {Promise<boolean>} Promise resolved with true if disabled, rejected or resolved with false otherwise.
*/
isDownloadCourseDisabled(siteId?: string): Promise<boolean> {
return this.sitesProvider.getSite(siteId).then((site) => {
return this.isDownloadCoursesDisabledInSite(site);
});
}
/**
* Check if download a whole course is disabled in a certain site.
*
* @param {CoreSite} [site] Site. If not defined, use current site.
* @return {boolean} Whether it's disabled.
*/
isDownloadCourseDisabledInSite(site?: CoreSite): boolean {
site = site || this.sitesProvider.getCurrentSite();
return site.isFeatureDisabled('NoDelegate_CoreCourseDownload');
}
/**
* Check if download all courses is disabled in a certain site.
*
* @param {string} [siteId] Site Id. If not defined, use current site.
* @return {Promise<boolean>} Promise resolved with true if disabled, rejected or resolved with false otherwise.
*/
isDownloadCoursesDisabled(siteId?: string): Promise<boolean> {
return this.sitesProvider.getSite(siteId).then((site) => {
return this.isDownloadCoursesDisabledInSite(site);
});
}
/**
* Check if download all courses is disabled in a certain site.
*
* @param {CoreSite} [site] Site. If not defined, use current site.
* @return {boolean} Whether it's disabled.
*/
isDownloadCoursesDisabledInSite(site?: CoreSite): boolean {
site = site || this.sitesProvider.getCurrentSite();
return site.isFeatureDisabled('NoDelegate_CoreCoursesDownload');
}
/**
* Check if My Courses is disabled in a certain site.
*