MOBILE-3954 course: Remove prefetch module from course and blocks
parent
255e987412
commit
018ebd6bb2
|
@ -12,7 +12,6 @@
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<core-course-module *ngFor="let module of mainMenuBlock.modules" [module]="module" [courseId]="siteHomeId"
|
<core-course-module *ngFor="let module of mainMenuBlock.modules" [module]="module" [section]="mainMenuBlock"></core-course-module>
|
||||||
[downloadEnabled]="downloadEnabled" [section]="mainMenuBlock"></core-course-module>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
|
|
|
@ -27,7 +27,6 @@ import { CoreBlockSideBlocksComponent } from '../side-blocks/side-blocks';
|
||||||
export class CoreBlockSideBlocksButtonComponent {
|
export class CoreBlockSideBlocksButtonComponent {
|
||||||
|
|
||||||
@Input() courseId!: number;
|
@Input() courseId!: number;
|
||||||
@Input() downloadEnabled = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open side blocks.
|
* Open side blocks.
|
||||||
|
@ -37,7 +36,6 @@ export class CoreBlockSideBlocksButtonComponent {
|
||||||
component: CoreBlockSideBlocksComponent,
|
component: CoreBlockSideBlocksComponent,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
courseId: this.courseId,
|
courseId: this.courseId,
|
||||||
downloadEnabled: this.downloadEnabled,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<ion-list *ngIf="blocks.length > 0">
|
<ion-list *ngIf="blocks.length > 0">
|
||||||
<ng-container *ngFor="let block of blocks">
|
<ng-container *ngFor="let block of blocks">
|
||||||
<core-block *ngIf="block.visible" [block]="block" contextLevel="course" [instanceId]="courseId"
|
<core-block *ngIf="block.visible" [block]="block" contextLevel="course" [instanceId]="courseId"></core-block>
|
||||||
[extraData]="{'downloadEnabled': downloadEnabled}"></core-block>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@ import { CoreCoursesDashboard } from '@features/courses/services/dashboard';
|
||||||
export class CoreBlockSideBlocksComponent implements OnInit {
|
export class CoreBlockSideBlocksComponent implements OnInit {
|
||||||
|
|
||||||
@Input() courseId?: number;
|
@Input() courseId?: number;
|
||||||
@Input() downloadEnabled = false;
|
|
||||||
|
|
||||||
@ViewChildren(CoreBlockComponent) blocksComponents?: QueryList<CoreBlockComponent>;
|
@ViewChildren(CoreBlockComponent) blocksComponents?: QueryList<CoreBlockComponent>;
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,8 @@
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<!-- Section selector. -->
|
<!-- Section selector. -->
|
||||||
<core-dynamic-component [component]="sectionSelectorComponent" [data]="data">
|
<core-dynamic-component [component]="sectionSelectorComponent" [data]="data">
|
||||||
|
|
||||||
<div *ngIf="displaySectionSelector && sections && hasSeveralSections"
|
<div *ngIf="displaySectionSelector && sections && hasSeveralSections"
|
||||||
class="ion-text-wrap ion-justify-content-between ion-align-items-center core-button-selector-row"
|
class="ion-text-wrap ion-justify-content-between ion-align-items-center core-button-selector-row">
|
||||||
[class.core-section-download]="downloadEnabled">
|
|
||||||
<core-combobox [modalOptions]="sectionSelectorModalOptions" interface="modal" listboxId="core-course-section-button"
|
<core-combobox [modalOptions]="sectionSelectorModalOptions" interface="modal" listboxId="core-course-section-button"
|
||||||
icon="fas-folder" [label]="'core.course.section' | translate"
|
icon="fas-folder" [label]="'core.course.section' | translate"
|
||||||
[selection]="selectedSection ? selectedSection.name : 'core.course.sections' | translate"
|
[selection]="selectedSection ? selectedSection.name : 'core.course.sections' | translate"
|
||||||
|
@ -26,16 +24,14 @@
|
||||||
<ng-container *ngIf="!selectedSection">{{ 'core.course.sections' | translate }}</ng-container>
|
<ng-container *ngIf="!selectedSection">{{ 'core.course.sections' | translate }}</ng-container>
|
||||||
</span>
|
</span>
|
||||||
</core-combobox>
|
</core-combobox>
|
||||||
<!-- Section download. -->
|
|
||||||
<ng-container *ngTemplateOutlet="sectionDownloadTemplate; context: {section: selectedSection}"></ng-container>
|
|
||||||
</div>
|
</div>
|
||||||
</core-dynamic-component>
|
</core-dynamic-component>
|
||||||
|
|
||||||
<!-- 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 lines="none" class="core-format-progress-list" *ngIf="imageThumb || (selectedSection?.id == allSectionsId && progress !== undefined) ||
|
<ion-list *ngIf="imageThumb || (selectedSection?.id == allSectionsId && progress !== undefined) ||
|
||||||
(selectedSection && selectedSection.id != allSectionsId &&
|
(selectedSection && selectedSection.id != allSectionsId &&
|
||||||
(selectedSection.availabilityinfo || selectedSection.visible === 0))">
|
(selectedSection.availabilityinfo || selectedSection.visible === 0))" lines="none" class="core-format-progress-list">
|
||||||
<div *ngIf="imageThumb" class="core-course-thumb">
|
<div *ngIf="imageThumb" class="core-course-thumb">
|
||||||
<img [src]="imageThumb" core-external-content alt="" />
|
<img [src]="imageThumb" core-external-content alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -103,8 +99,7 @@
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
|
|
||||||
<core-block-side-blocks-button *ngIf="course && displayBlocks && hasBlocks" [courseId]="course.id"
|
<core-block-side-blocks-button *ngIf="course && displayBlocks && hasBlocks" [courseId]="course.id">
|
||||||
[downloadEnabled]="downloadEnabled">
|
|
||||||
</core-block-side-blocks-button>
|
</core-block-side-blocks-button>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</core-dynamic-component>
|
</core-dynamic-component>
|
||||||
|
@ -114,7 +109,7 @@
|
||||||
<section *ngIf="!section.hiddenbynumsections && section.id != allSectionsId && section.id != stealthModulesSectionId">
|
<section *ngIf="!section.hiddenbynumsections && section.id != allSectionsId && section.id != stealthModulesSectionId">
|
||||||
<!-- Title is only displayed when viewing all sections. -->
|
<!-- Title is only displayed when viewing all sections. -->
|
||||||
<ion-item-divider *ngIf="selectedSection?.id == allSectionsId && section.name" class="ion-text-wrap" color="light"
|
<ion-item-divider *ngIf="selectedSection?.id == allSectionsId && section.name" class="ion-text-wrap" color="light"
|
||||||
[class.core-section-download]="downloadEnabled" [class.item-dimmed]="section.visible === 0 || section.uservisible === false">
|
[class.item-dimmed]="section.visible === 0 || section.uservisible === false">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>
|
<h2>
|
||||||
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id">
|
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id">
|
||||||
|
@ -133,8 +128,6 @@
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
</p>
|
</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<!-- Section download. -->
|
|
||||||
<ng-container *ngTemplateOutlet="sectionDownloadTemplate; context: {section: section}"></ng-container>
|
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
|
|
||||||
<ion-item class="ion-text-wrap" *ngIf="section.summary">
|
<ion-item class="ion-text-wrap" *ngIf="section.summary">
|
||||||
|
@ -145,28 +138,10 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ng-container *ngFor="let module of section.modules">
|
<ng-container *ngFor="let module of section.modules">
|
||||||
<core-course-module *ngIf="module.visibleoncoursepage !== 0" [module]="module" [courseId]="course?.id"
|
<core-course-module *ngIf="module.visibleoncoursepage !== 0" [module]="module" [section]="section"
|
||||||
[downloadEnabled]="downloadEnabled" [section]="section" (completionChanged)="onCompletionChange($event)"
|
(completionChanged)="onCompletionChange($event)" [showActivityDates]="course?.showactivitydates"
|
||||||
(statusChanged)="onModuleStatusChange()" [showActivityDates]="course?.showactivitydates"
|
|
||||||
[showCompletionConditions]="course?.showcompletionconditions">
|
[showCompletionConditions]="course?.showcompletionconditions">
|
||||||
</core-course-module>
|
</core-course-module>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</section>
|
</section>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<!-- Template to render a section download button/progress. -->
|
|
||||||
<ng-template #sectionDownloadTemplate let-section="section">
|
|
||||||
<div *ngIf="section && downloadEnabled" slot="end" class="core-button-spinner">
|
|
||||||
<!-- Download progress. -->
|
|
||||||
<ion-badge class="core-course-download-section-progress"
|
|
||||||
*ngIf="section.isDownloading && section.total > 0 && section.count < section.total" role="progressbar"
|
|
||||||
[attr.aria-valuemax]="section.total" [attr.aria-valuenow]="section.count"
|
|
||||||
[attr.aria-valuetext]="'core.course.downloadsectionprogressdescription' | translate:section">
|
|
||||||
{{section.count}} / {{section.total}}
|
|
||||||
</ion-badge>
|
|
||||||
|
|
||||||
<core-download-refresh [status]="section.downloadStatus" [enabled]="downloadEnabled" (action)="prefetch(section)"
|
|
||||||
[loading]="section.isDownloading || section.isCalculating" [canTrustDownload]="true" size="small">
|
|
||||||
</core-download-refresh>
|
|
||||||
</div>
|
|
||||||
</ng-template>
|
|
||||||
|
|
|
@ -55,21 +55,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.core-section-download {
|
|
||||||
core-combobox {
|
|
||||||
max-width: calc(100% - 64px);
|
|
||||||
}
|
|
||||||
.core-button-spinner {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
@include margin-horizontal(10px);
|
|
||||||
|
|
||||||
ion-badge.core-course-download-courses-progress {
|
|
||||||
@include margin(null, 12px, null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-course-section-nav-buttons {
|
.core-course-section-nav-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|
|
@ -27,7 +27,6 @@ import {
|
||||||
ElementRef,
|
ElementRef,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { ModalOptions } from '@ionic/core';
|
import { ModalOptions } from '@ionic/core';
|
||||||
import { CoreSites } from '@services/sites';
|
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-component';
|
import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-component';
|
||||||
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
||||||
|
@ -37,17 +36,14 @@ import {
|
||||||
CoreCourseProvider,
|
CoreCourseProvider,
|
||||||
} from '@features/course/services/course';
|
} from '@features/course/services/course';
|
||||||
import {
|
import {
|
||||||
CoreCourseHelper,
|
|
||||||
CoreCourseModuleData,
|
CoreCourseModuleData,
|
||||||
CoreCourseModuleCompletionData,
|
CoreCourseModuleCompletionData,
|
||||||
CoreCourseSection,
|
CoreCourseSection,
|
||||||
CoreCourseSectionWithStatus,
|
|
||||||
} from '@features/course/services/course-helper';
|
} from '@features/course/services/course-helper';
|
||||||
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { IonContent, IonRefresher } from '@ionic/angular';
|
import { IonContent, IonRefresher } from '@ionic/angular';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
|
||||||
import { CoreCourseSectionSelectorComponent } from '../section-selector/section-selector';
|
import { CoreCourseSectionSelectorComponent } from '../section-selector/section-selector';
|
||||||
import { CoreBlockHelper } from '@features/block/services/block-helper';
|
import { CoreBlockHelper } from '@features/block/services/block-helper';
|
||||||
|
|
||||||
|
@ -71,8 +67,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
static readonly LOAD_MORE_ACTIVITIES = 20; // How many activities should load each time showMoreActivities is called.
|
static readonly LOAD_MORE_ACTIVITIES = 20; // How many activities should load each time showMoreActivities is called.
|
||||||
|
|
||||||
@Input() course?: CoreCourseAnyCourseData; // The course to render.
|
@Input() course?: CoreCourseAnyCourseData; // The course to render.
|
||||||
@Input() sections?: CoreCourseSectionWithStatus[]; // List of course sections. The status will be calculated in this component.
|
@Input() sections?: CoreCourseSection[]; // List of course sections.
|
||||||
@Input() downloadEnabled?: boolean; // Whether the download of sections and modules is enabled.
|
|
||||||
@Input() initialSectionId?: number; // The section to load first (by ID).
|
@Input() initialSectionId?: number; // The section to load first (by ID).
|
||||||
@Input() initialSectionNumber?: number; // The section to load first (by number).
|
@Input() initialSectionNumber?: number; // The section to load first (by number).
|
||||||
@Input() moduleId?: number; // The module ID to scroll to. Must be inside the initial selected section.
|
@Input() moduleId?: number; // The module ID to scroll to. Must be inside the initial selected section.
|
||||||
|
@ -108,7 +103,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
componentProps: {},
|
componentProps: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
protected sectionStatusObserver?: CoreEventObserver;
|
|
||||||
protected selectTabObserver?: CoreEventObserver;
|
protected selectTabObserver?: CoreEventObserver;
|
||||||
protected lastCourseFormat?: string;
|
protected lastCourseFormat?: string;
|
||||||
protected sectionSelectorExpanded = false;
|
protected sectionSelectorExpanded = false;
|
||||||
|
@ -125,38 +119,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
* Component being initialized.
|
* Component being initialized.
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
// Listen for section status changes.
|
|
||||||
this.sectionStatusObserver = CoreEvents.on(
|
|
||||||
CoreEvents.SECTION_STATUS_CHANGED,
|
|
||||||
async (data) => {
|
|
||||||
if (!this.downloadEnabled || !this.sections?.length || !data.sectionId || data.courseId != this.course?.id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the affected section is being downloaded.
|
|
||||||
// If so, we don't update section status because it'll already be updated when the download finishes.
|
|
||||||
const downloadId = CoreCourseHelper.getSectionDownloadId({ id: data.sectionId });
|
|
||||||
if (CoreCourseModulePrefetchDelegate.isBeingDownloaded(downloadId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the affected section.
|
|
||||||
const section = this.sections.find(section => section.id == data.sectionId);
|
|
||||||
if (!section) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recalculate the status.
|
|
||||||
await CoreCourseHelper.calculateSectionStatus(section, this.course.id, false);
|
|
||||||
|
|
||||||
if (section.isDownloading && !CoreCourseModulePrefetchDelegate.isBeingDownloaded(downloadId)) {
|
|
||||||
// All the modules are now downloading, set a download all promise.
|
|
||||||
this.prefetch(section);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
CoreSites.getCurrentSiteId(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Listen for select course tab events to select the right section if needed.
|
// Listen for select course tab events to select the right section if needed.
|
||||||
this.selectTabObserver = CoreEvents.on(CoreEvents.SELECT_COURSE_TAB, (data) => {
|
this.selectTabObserver = CoreEvents.on(CoreEvents.SELECT_COURSE_TAB, (data) => {
|
||||||
if (data.name) {
|
if (data.name) {
|
||||||
|
@ -205,10 +167,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
this.sectionSelectorModalOptions.componentProps!.sections = this.sections;
|
this.sectionSelectorModalOptions.componentProps!.sections = this.sections;
|
||||||
this.treatSections(this.sections);
|
this.treatSections(this.sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.downloadEnabled && (changes.downloadEnabled || changes.sections)) {
|
|
||||||
this.calculateSectionsStatus(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -219,7 +177,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
this.data.sections = this.sections;
|
this.data.sections = this.sections;
|
||||||
this.data.initialSectionId = this.initialSectionId;
|
this.data.initialSectionId = this.initialSectionId;
|
||||||
this.data.initialSectionNumber = this.initialSectionNumber;
|
this.data.initialSectionNumber = this.initialSectionNumber;
|
||||||
this.data.downloadEnabled = this.downloadEnabled;
|
|
||||||
this.data.moduleId = this.moduleId;
|
this.data.moduleId = this.moduleId;
|
||||||
this.data.completionChanged = this.completionChanged;
|
this.data.completionChanged = this.completionChanged;
|
||||||
}
|
}
|
||||||
|
@ -394,9 +351,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
this.canLoadMore = false;
|
this.canLoadMore = false;
|
||||||
this.showSectionId = 0;
|
this.showSectionId = 0;
|
||||||
this.showMoreActivities();
|
this.showMoreActivities();
|
||||||
if (this.downloadEnabled) {
|
|
||||||
this.calculateSectionsStatus(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.moduleId && previousValue === undefined) {
|
if (this.moduleId && previousValue === undefined) {
|
||||||
|
@ -432,62 +386,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
return section1 && section2 ? section1.id === section2.id : section1 === section2;
|
return section1 && section2 ? section1.id === section2.id : section1 === section2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate the status of sections.
|
|
||||||
*
|
|
||||||
* @param refresh If refresh or not.
|
|
||||||
*/
|
|
||||||
protected calculateSectionsStatus(refresh?: boolean): void {
|
|
||||||
if (!this.sections || !this.course) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreUtils.ignoreErrors(CoreCourseHelper.calculateSectionsStatus(this.sections, this.course.id, refresh));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Confirm and prefetch a section. If the section is "all sections", prefetch all the sections.
|
|
||||||
*
|
|
||||||
* @param section Section to download.
|
|
||||||
* @param refresh Refresh clicked (not used).
|
|
||||||
*/
|
|
||||||
async prefetch(section: CoreCourseSectionWithStatus): Promise<void> {
|
|
||||||
section.isCalculating = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await CoreCourseHelper.confirmDownloadSizeSection(this.course!.id, section, this.sections);
|
|
||||||
|
|
||||||
await this.prefetchSection(section, true);
|
|
||||||
} catch (error) {
|
|
||||||
// User cancelled or there was an error calculating the size.
|
|
||||||
if (error) {
|
|
||||||
CoreDomUtils.showErrorModal(error);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
section.isCalculating = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prefetch a section.
|
|
||||||
*
|
|
||||||
* @param section The section to download.
|
|
||||||
* @param manual Whether the prefetch was started manually or it was automatically started because all modules
|
|
||||||
* are being downloaded.
|
|
||||||
*/
|
|
||||||
protected async prefetchSection(section: CoreCourseSectionWithStatus, manual?: boolean): Promise<void> {
|
|
||||||
try {
|
|
||||||
await CoreCourseHelper.prefetchSection(section, this.course!.id, this.sections);
|
|
||||||
} catch (error) {
|
|
||||||
// Don't show error message if it's an automatic download.
|
|
||||||
if (!manual) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingsection', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh the data.
|
* Refresh the data.
|
||||||
*
|
*
|
||||||
|
@ -580,7 +478,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
* Component destroyed.
|
* Component destroyed.
|
||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.sectionStatusObserver && this.sectionStatusObserver.off();
|
|
||||||
this.selectTabObserver && this.selectTabObserver.off();
|
this.selectTabObserver && this.selectTabObserver.off();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,17 +488,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
this.dynamicComponents?.forEach((component) => {
|
this.dynamicComponents?.forEach((component) => {
|
||||||
component.callComponentFunction('ionViewDidEnter');
|
component.callComponentFunction('ionViewDidEnter');
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!this.downloadEnabled || !this.course || !this.sections) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The download status of a section might have been changed from within a module page.
|
|
||||||
if (this.selectedSection && this.selectedSection.id !== CoreCourseProvider.ALL_SECTIONS_ID) {
|
|
||||||
CoreCourseHelper.calculateSectionStatus(this.selectedSection, this.course.id, false, false);
|
|
||||||
} else {
|
|
||||||
CoreCourseHelper.calculateSectionsStatus(this.sections, this.course.id, false, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -653,17 +539,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
this.updateProgress();
|
this.updateProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Recalculate the download status of each section, in response to a module being downloaded.
|
|
||||||
*/
|
|
||||||
onModuleStatusChange(): void {
|
|
||||||
if (!this.downloadEnabled || !this.sections || !this.course) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreCourseHelper.calculateSectionsStatus(this.sections, this.course.id, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update course progress.
|
* Update course progress.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<ion-label class="core-module-title">
|
<ion-label class="core-module-title">
|
||||||
<p class="item-heading">
|
<p class="item-heading">
|
||||||
<core-format-text [text]="module.handlerData.title" contextLevel="module" [contextInstanceId]="module.id"
|
<core-format-text [text]="module.handlerData.title" contextLevel="module" [contextInstanceId]="module.id"
|
||||||
[courseId]="courseId" [attr.aria-label]="module.handlerData.a11yTitle + ', ' + modNameTranslated">
|
[courseId]="module.course" [attr.aria-label]="module.handlerData.a11yTitle + ', ' + modNameTranslated">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</p>
|
</p>
|
||||||
<ion-badge *ngIf="module.handlerData.extraBadge" [color]="module.handlerData.extraBadgeColor"
|
<ion-badge *ngIf="module.handlerData.extraBadge" [color]="module.handlerData.extraBadgeColor"
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
<div class="core-module-availabilityinfo" *ngIf="module.availabilityinfo">
|
<div class="core-module-availabilityinfo" *ngIf="module.availabilityinfo">
|
||||||
<ion-badge class="ion-text-wrap">{{ 'core.restricted' | translate }}</ion-badge>
|
<ion-badge class="ion-text-wrap">{{ 'core.restricted' | translate }}</ion-badge>
|
||||||
<core-format-text [text]="module.availabilityinfo" contextLevel="module" [contextInstanceId]="module.id"
|
<core-format-text [text]="module.availabilityinfo" contextLevel="module" [contextInstanceId]="module.id"
|
||||||
[courseId]="courseId" class="ion-text-wrap">
|
[courseId]="module.course" class="ion-text-wrap">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</div>
|
</div>
|
||||||
<ion-badge *ngIf="module.completiondata?.offline" color="warning" class="ion-text-wrap">
|
<ion-badge *ngIf="module.completiondata?.offline" color="warning" class="ion-text-wrap">
|
||||||
|
@ -48,13 +48,9 @@
|
||||||
</core-course-module-completion-legacy>
|
</core-course-module-completion-legacy>
|
||||||
|
|
||||||
<div class="core-module-buttons-more">
|
<div class="core-module-buttons-more">
|
||||||
<core-download-refresh [status]="downloadStatus" [enabled]="downloadEnabled" [canTrustDownload]="true"
|
|
||||||
[loading]="spinner || module.handlerData.spinner" (action)="download($event)" size="small">
|
|
||||||
</core-download-refresh>
|
|
||||||
|
|
||||||
<!-- Buttons defined by the module handler. -->
|
<!-- Buttons defined by the module handler. -->
|
||||||
<ion-button fill="clear" *ngFor="let button of module.handlerData.buttons" color="dark" size="small"
|
<ion-button fill="clear" *ngFor="let button of module.handlerData.buttons" color="dark" size="small"
|
||||||
[hidden]="button.hidden || spinner || module.handlerData.spinner" class="core-animate-show-hide"
|
[hidden]="button.hidden || module.handlerData.spinner" class="core-animate-show-hide"
|
||||||
(click)="buttonClicked($event, button)" [attr.aria-label]="button.label | translate:{$a: module.handlerData.title}">
|
(click)="buttonClicked($event, button)" [attr.aria-label]="button.label | translate:{$a: module.handlerData.title}">
|
||||||
<ion-icon [name]="button.icon" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon [name]="button.icon" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
@ -81,7 +77,7 @@
|
||||||
</core-course-module-completion>
|
</core-course-module-completion>
|
||||||
|
|
||||||
<core-format-text class="core-module-description" *ngIf="module.description" [maxHeight]="80" [text]="module.description"
|
<core-format-text class="core-module-description" *ngIf="module.description" [maxHeight]="80" [text]="module.description"
|
||||||
contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
|
contextLevel="module" [contextInstanceId]="module.id" [courseId]="module.course">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
|
@ -15,20 +15,13 @@
|
||||||
import { Component, Input, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core';
|
import { Component, Input, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
|
||||||
import {
|
import {
|
||||||
CoreCourseHelper,
|
|
||||||
CoreCourseModuleData,
|
CoreCourseModuleData,
|
||||||
CoreCourseModuleCompletionData,
|
CoreCourseModuleCompletionData,
|
||||||
CoreCourseSection,
|
CoreCourseSection,
|
||||||
} from '@features/course/services/course-helper';
|
} from '@features/course/services/course-helper';
|
||||||
import { CoreCourse } from '@features/course/services/course';
|
import { CoreCourse } from '@features/course/services/course';
|
||||||
import { CoreCourseModuleDelegate, CoreCourseModuleHandlerButton } from '@features/course/services/module-delegate';
|
import { CoreCourseModuleDelegate, CoreCourseModuleHandlerButton } from '@features/course/services/module-delegate';
|
||||||
import {
|
|
||||||
CoreCourseModulePrefetchDelegate,
|
|
||||||
CoreCourseModulePrefetchHandler,
|
|
||||||
} from '@features/course/services/module-prefetch-delegate';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component to display a module entry in a list of modules.
|
* Component to display a module entry in a list of modules.
|
||||||
|
@ -45,47 +38,20 @@ import {
|
||||||
export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
@Input() module!: CoreCourseModuleData; // The module to render.
|
@Input() module!: CoreCourseModuleData; // The module to render.
|
||||||
@Input() courseId?: number; // The course the module belongs to.
|
|
||||||
@Input() section?: CoreCourseSection; // The section the module belongs to.
|
@Input() section?: CoreCourseSection; // The section the module belongs to.
|
||||||
@Input() showActivityDates = false; // Whether to show activity dates.
|
@Input() showActivityDates = false; // Whether to show activity dates.
|
||||||
@Input() showCompletionConditions = false; // Whether to show activity completion conditions.
|
@Input() showCompletionConditions = false; // Whether to show activity completion conditions.
|
||||||
// eslint-disable-next-line @angular-eslint/no-input-rename
|
|
||||||
@Input('downloadEnabled') set enabled(value: boolean) {
|
|
||||||
this.downloadEnabled = value;
|
|
||||||
|
|
||||||
if (!this.module.handlerData?.showDownloadButton || !this.downloadEnabled || this.statusCalculated) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// First time that the download is enabled. Initialize the data.
|
|
||||||
this.statusCalculated = true;
|
|
||||||
this.spinner = true; // Show spinner while calculating the status.
|
|
||||||
|
|
||||||
// Get current status to decide which icon should be shown.
|
|
||||||
this.calculateAndShowStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>(); // Notify when module completion changes.
|
@Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>(); // Notify when module completion changes.
|
||||||
@Output() statusChanged = new EventEmitter<CoreCourseModuleStatusChangedData>(); // Notify when the download status changes.
|
|
||||||
|
|
||||||
downloadStatus?: string;
|
|
||||||
spinner?: boolean; // Whether to display a loading spinner.
|
|
||||||
downloadEnabled?: boolean; // Whether the download of sections and modules is enabled.
|
|
||||||
modNameTranslated = '';
|
modNameTranslated = '';
|
||||||
hasInfo = false;
|
hasInfo = false;
|
||||||
showLegacyCompletion = false; // Whether to show module completion in the old format.
|
showLegacyCompletion = false; // Whether to show module completion in the old format.
|
||||||
showManualCompletion = false; // Whether to show manual completion when completion conditions are disabled.
|
showManualCompletion = false; // Whether to show manual completion when completion conditions are disabled.
|
||||||
|
|
||||||
protected prefetchHandler?: CoreCourseModulePrefetchHandler;
|
|
||||||
protected statusObserver?: CoreEventObserver;
|
|
||||||
protected statusCalculated = false;
|
|
||||||
protected isDestroyed = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component being initialized.
|
* Component being initialized.
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.courseId = this.courseId || this.module.course;
|
|
||||||
this.modNameTranslated = CoreCourse.translateModuleName(this.module.modname) || '';
|
this.modNameTranslated = CoreCourse.translateModuleName(this.module.modname) || '';
|
||||||
this.showLegacyCompletion = !CoreSites.getCurrentSite()?.isVersionGreaterEqualThan('3.11');
|
this.showLegacyCompletion = !CoreSites.getCurrentSite()?.isVersionGreaterEqualThan('3.11');
|
||||||
this.checkShowManualCompletion();
|
this.checkShowManualCompletion();
|
||||||
|
@ -103,29 +69,6 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
||||||
(this.showCompletionConditions && this.module.completiondata.isautomatic))
|
(this.showCompletionConditions && this.module.completiondata.isautomatic))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.module.handlerData.showDownloadButton) {
|
|
||||||
// Listen for changes on this module status, even if download isn't enabled.
|
|
||||||
this.prefetchHandler = CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor(this.module.modname);
|
|
||||||
|
|
||||||
this.statusObserver = CoreEvents.on(CoreEvents.PACKAGE_STATUS_CHANGED, (data) => {
|
|
||||||
if (!this.module || data.componentId != this.module.id || !this.prefetchHandler ||
|
|
||||||
data.component != this.prefetchHandler.component) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call determineModuleStatus to get the right status to display.
|
|
||||||
const status = CoreCourseModulePrefetchDelegate.determineModuleStatus(this.module, data.status);
|
|
||||||
|
|
||||||
if (this.downloadEnabled) {
|
|
||||||
// Download is enabled, show the status.
|
|
||||||
this.showStatus(status);
|
|
||||||
} else if (this.module.handlerData?.updateStatus) {
|
|
||||||
// Download isn't enabled but the handler defines a updateStatus function, call it anyway.
|
|
||||||
this.module.handlerData.updateStatus(status);
|
|
||||||
}
|
|
||||||
}, CoreSites.getCurrentSiteId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -143,7 +86,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
||||||
*/
|
*/
|
||||||
moduleClicked(event: Event): void {
|
moduleClicked(event: Event): void {
|
||||||
if (this.module.uservisible !== false && this.module.handlerData?.action) {
|
if (this.module.uservisible !== false && this.module.handlerData?.action) {
|
||||||
this.module.handlerData.action(event, this.module, this.courseId!);
|
this.module.handlerData.action(event, this.module, this.module.course);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,91 +104,14 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
button.action(event, this.module, this.courseId!);
|
button.action(event, this.module, this.module.course);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Download the module.
|
|
||||||
*
|
|
||||||
* @param refresh Whether it's refreshing.
|
|
||||||
* @return Promise resolved when done.
|
|
||||||
*/
|
|
||||||
async download(refresh: boolean): Promise<void> {
|
|
||||||
if (!this.prefetchHandler || !this.module) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show spinner since this operation might take a while.
|
|
||||||
this.spinner = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Get download size to ask for confirm if it's high.
|
|
||||||
const size = await this.prefetchHandler.getDownloadSize(this.module, this.module.course, true);
|
|
||||||
|
|
||||||
await CoreCourseHelper.prefetchModule(this.prefetchHandler, this.module, size, this.module.course, refresh);
|
|
||||||
|
|
||||||
const eventData = {
|
|
||||||
sectionId: this.section?.id,
|
|
||||||
moduleId: this.module.id,
|
|
||||||
courseId: this.module.course,
|
|
||||||
};
|
|
||||||
this.statusChanged.emit(eventData);
|
|
||||||
} catch (error) {
|
|
||||||
// Error, hide spinner.
|
|
||||||
this.spinner = false;
|
|
||||||
if (!this.isDestroyed) {
|
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show download buttons according to module status.
|
|
||||||
*
|
|
||||||
* @param status Module status.
|
|
||||||
*/
|
|
||||||
protected showStatus(status: string): void {
|
|
||||||
if (!status) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.spinner = false;
|
|
||||||
this.downloadStatus = status;
|
|
||||||
|
|
||||||
this.module.handlerData?.updateStatus?.(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate and show module status.
|
|
||||||
*
|
|
||||||
* @return Promise resolved when done.
|
|
||||||
*/
|
|
||||||
protected async calculateAndShowStatus(): Promise<void> {
|
|
||||||
if (!this.module || !this.courseId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(this.module, this.courseId);
|
|
||||||
|
|
||||||
this.showStatus(status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component destroyed.
|
* Component destroyed.
|
||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
// this.statusObserver?.off();
|
|
||||||
this.module.handlerData?.onDestroy?.();
|
this.module.handlerData?.onDestroy?.();
|
||||||
this.isDestroyed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Data sent to the status changed output.
|
|
||||||
*/
|
|
||||||
export type CoreCourseModuleStatusChangedData = {
|
|
||||||
moduleId: number;
|
|
||||||
courseId: number;
|
|
||||||
sectionId?: number;
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<core-dynamic-component [component]="componentClass" [data]="data"></core-dynamic-component>
|
<core-dynamic-component [component]="componentClass" [data]="data"></core-dynamic-component>
|
||||||
|
|
||||||
<core-block-side-blocks-button *ngIf="course && hasBlocks" [courseId]="course.id" [downloadEnabled]="downloadEnabled">
|
<core-block-side-blocks-button *ngIf="course && hasBlocks" [courseId]="course.id">
|
||||||
</core-block-side-blocks-button>
|
</core-block-side-blocks-button>
|
||||||
|
|
|
@ -36,7 +36,6 @@ export class CoreCourseFormatSingleActivityComponent implements OnChanges {
|
||||||
|
|
||||||
@Input() course?: CoreCourseAnyCourseData; // The course to render.
|
@Input() course?: CoreCourseAnyCourseData; // The course to render.
|
||||||
@Input() sections?: CoreCourseSectionWithStatus[]; // List of course sections.
|
@Input() sections?: CoreCourseSectionWithStatus[]; // List of course sections.
|
||||||
@Input() downloadEnabled?: boolean; // Whether the download of sections and modules is enabled.
|
|
||||||
@Input() initialSectionId?: number; // The section to load first (by ID).
|
@Input() initialSectionId?: number; // The section to load first (by ID).
|
||||||
@Input() initialSectionNumber?: number; // The section to load first (by number).
|
@Input() initialSectionNumber?: number; // The section to load first (by number).
|
||||||
@Input() moduleId?: number; // The module ID to scroll to. Must be inside the initial selected section.
|
@Input() moduleId?: number; // The module ID to scroll to. Must be inside the initial selected section.
|
||||||
|
|
|
@ -68,13 +68,6 @@ export class CoreCourseFormatSingleActivityHandlerService implements CoreCourseF
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
displayEnableDownload(): boolean {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
<core-navbar-buttons slot="end">
|
<core-navbar-buttons slot="end">
|
||||||
<core-context-menu>
|
<core-context-menu>
|
||||||
<core-context-menu-item [hidden]="!displayEnableDownload" [priority]="2000" iconAction="toggle" [(toggle)]="downloadEnabled"
|
|
||||||
[content]="'core.settings.showdownloadoptions' | translate" (action)="toggleDownload()">
|
|
||||||
</core-context-menu-item>
|
|
||||||
<core-context-menu-item [hidden]="!downloadCourseEnabled" [priority]="1900"
|
|
||||||
[content]="prefetchCourseData.statusTranslatable | translate" (action)="prefetchCourse()" [iconAction]="prefetchCourseData.icon"
|
|
||||||
[closeOnClick]="false">
|
|
||||||
</core-context-menu-item>
|
|
||||||
<core-context-menu-item [priority]="1800" [content]="'core.course.coursesummary' | translate" (action)="openCourseSummary()"
|
<core-context-menu-item [priority]="1800" [content]="'core.course.coursesummary' | translate" (action)="openCourseSummary()"
|
||||||
iconAction="fas-graduation-cap">
|
iconAction="fas-graduation-cap">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
|
@ -22,8 +15,7 @@
|
||||||
|
|
||||||
<core-loading [hideUntil]="dataLoaded">
|
<core-loading [hideUntil]="dataLoaded">
|
||||||
<core-course-format [course]="course" [sections]="sections" [initialSectionId]="sectionId" [initialSectionNumber]="sectionNumber"
|
<core-course-format [course]="course" [sections]="sections" [initialSectionId]="sectionId" [initialSectionNumber]="sectionNumber"
|
||||||
[downloadEnabled]="downloadEnabled" [moduleId]="moduleId" (completionChanged)="onCompletionChange($event)"
|
[moduleId]="moduleId" (completionChanged)="onCompletionChange($event)" class="core-course-format-{{course.format}}">
|
||||||
class="core-course-format-{{course.format}}">
|
|
||||||
</core-course-format>
|
</core-course-format>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
|
@ -15,20 +15,17 @@
|
||||||
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
|
import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
|
||||||
import { IonContent, IonRefresher } from '@ionic/angular';
|
import { IonContent, IonRefresher } from '@ionic/angular';
|
||||||
|
|
||||||
import { CoreSites } from '@services/sites';
|
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreCourses, CoreCourseAnyCourseData, CoreCoursesProvider } from '@features/courses/services/courses';
|
import { CoreCourses, CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
||||||
import {
|
import {
|
||||||
CoreCourse,
|
CoreCourse,
|
||||||
CoreCourseCompletionActivityStatus,
|
CoreCourseCompletionActivityStatus,
|
||||||
CoreCourseProvider,
|
|
||||||
} from '@features/course/services/course';
|
} from '@features/course/services/course';
|
||||||
import {
|
import {
|
||||||
CoreCourseHelper,
|
CoreCourseHelper,
|
||||||
CoreCourseModuleCompletionData,
|
CoreCourseModuleCompletionData,
|
||||||
CoreCourseSection,
|
CoreCourseSection,
|
||||||
CorePrefetchStatusInfo,
|
|
||||||
} from '@features/course/services/course-helper';
|
} from '@features/course/services/course-helper';
|
||||||
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
||||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||||
|
@ -43,7 +40,6 @@ import {
|
||||||
CoreEventObserver,
|
CoreEventObserver,
|
||||||
} from '@singletons/events';
|
} from '@singletons/events';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreConstants } from '@/core/constants';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays the contents of a course.
|
* Page that displays the contents of a course.
|
||||||
|
@ -63,47 +59,19 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
sectionNumber?: number;
|
sectionNumber?: number;
|
||||||
courseMenuHandlers: CoreCourseOptionsMenuHandlerToDisplay[] = [];
|
courseMenuHandlers: CoreCourseOptionsMenuHandlerToDisplay[] = [];
|
||||||
dataLoaded = false;
|
dataLoaded = false;
|
||||||
downloadEnabled = false;
|
|
||||||
downloadCourseEnabled = false;
|
downloadCourseEnabled = false;
|
||||||
moduleId?: number;
|
moduleId?: number;
|
||||||
displayEnableDownload = false;
|
displayEnableDownload = false;
|
||||||
displayRefresher = false;
|
displayRefresher = false;
|
||||||
prefetchCourseData: CorePrefetchStatusInfo = {
|
|
||||||
icon: CoreConstants.ICON_LOADING,
|
|
||||||
statusTranslatable: 'core.course.downloadcourse',
|
|
||||||
status: '',
|
|
||||||
loading: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
protected formatOptions?: Record<string, unknown>;
|
protected formatOptions?: Record<string, unknown>;
|
||||||
protected completionObserver?: CoreEventObserver;
|
protected completionObserver?: CoreEventObserver;
|
||||||
protected courseStatusObserver?: CoreEventObserver;
|
|
||||||
protected siteUpdatedObserver?: CoreEventObserver;
|
|
||||||
protected downloadEnabledObserver?: CoreEventObserver;
|
|
||||||
protected syncObserver?: CoreEventObserver;
|
protected syncObserver?: CoreEventObserver;
|
||||||
protected isDestroyed = false;
|
protected isDestroyed = false;
|
||||||
protected modulesHaveCompletion = false;
|
protected modulesHaveCompletion = false;
|
||||||
protected isGuest?: boolean;
|
protected isGuest = false;
|
||||||
protected debouncedUpdateCachedCompletion?: () => void; // Update the cached completion after a certain time.
|
protected debouncedUpdateCachedCompletion?: () => void; // Update the cached completion after a certain time.
|
||||||
|
|
||||||
constructor() {
|
|
||||||
// Refresh the enabled flags if site is updated.
|
|
||||||
this.siteUpdatedObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => {
|
|
||||||
this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite();
|
|
||||||
|
|
||||||
this.displayEnableDownload = !CoreSites.getRequiredCurrentSite().isOfflineDisabled() &&
|
|
||||||
CoreCourseFormatDelegate.displayEnableDownload(this.course);
|
|
||||||
|
|
||||||
this.downloadEnabled = this.displayEnableDownload && this.downloadEnabled;
|
|
||||||
|
|
||||||
this.initListeners();
|
|
||||||
}, CoreSites.getCurrentSiteId());
|
|
||||||
|
|
||||||
this.downloadEnabledObserver = CoreEvents.on(CoreCoursesProvider.EVENT_DASHBOARD_DOWNLOAD_ENABLED_CHANGED, (data) => {
|
|
||||||
this.downloadEnabled = this.displayEnableDownload && data.enabled;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
|
@ -121,13 +89,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
this.sectionId = CoreNavigator.getRouteNumberParam('sectionId');
|
this.sectionId = CoreNavigator.getRouteNumberParam('sectionId');
|
||||||
this.sectionNumber = CoreNavigator.getRouteNumberParam('sectionNumber');
|
this.sectionNumber = CoreNavigator.getRouteNumberParam('sectionNumber');
|
||||||
this.moduleId = CoreNavigator.getRouteNumberParam('moduleId');
|
this.moduleId = CoreNavigator.getRouteNumberParam('moduleId');
|
||||||
this.isGuest = CoreNavigator.getRouteBooleanParam('isGuest');
|
this.isGuest = !!CoreNavigator.getRouteBooleanParam('isGuest');
|
||||||
|
|
||||||
this.displayEnableDownload = !CoreSites.getRequiredCurrentSite().isOfflineDisabled() &&
|
|
||||||
CoreCourseFormatDelegate.displayEnableDownload(this.course);
|
|
||||||
this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite();
|
|
||||||
|
|
||||||
this.downloadEnabled = this.displayEnableDownload && CoreCourses.getCourseDownloadOptionsEnabled();
|
|
||||||
|
|
||||||
this.debouncedUpdateCachedCompletion = CoreUtils.debounce(() => {
|
this.debouncedUpdateCachedCompletion = CoreUtils.debounce(() => {
|
||||||
if (this.modulesHaveCompletion) {
|
if (this.modulesHaveCompletion) {
|
||||||
|
@ -149,8 +111,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
await this.loadData(false, true);
|
await this.loadData(false, true);
|
||||||
|
|
||||||
this.dataLoaded = true;
|
this.dataLoaded = true;
|
||||||
|
|
||||||
this.initPrefetch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -159,15 +119,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
protected async initListeners(): Promise<void> {
|
protected async initListeners(): Promise<void> {
|
||||||
if (this.downloadCourseEnabled && !this.courseStatusObserver) {
|
|
||||||
// Listen for changes in course status.
|
|
||||||
this.courseStatusObserver = CoreEvents.on(CoreEvents.COURSE_STATUS_CHANGED, (data) => {
|
|
||||||
if (data.courseId == this.course.id || data.courseId == CoreCourseProvider.ALL_COURSES_CLEARED) {
|
|
||||||
this.updateCourseStatus(data.status);
|
|
||||||
}
|
|
||||||
}, CoreSites.getCurrentSiteId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the course format requires the view to be refreshed when completion changes.
|
// Check if the course format requires the view to be refreshed when completion changes.
|
||||||
const shouldRefresh = await CoreCourseFormatDelegate.shouldRefreshWhenCompletionChanges(this.course);
|
const shouldRefresh = await CoreCourseFormatDelegate.shouldRefreshWhenCompletionChanges(this.course);
|
||||||
if (!shouldRefresh) {
|
if (!shouldRefresh) {
|
||||||
|
@ -200,41 +151,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Init prefetch data if needed.
|
|
||||||
*
|
|
||||||
* @return Promise resolved when done.
|
|
||||||
*/
|
|
||||||
protected async initPrefetch(): Promise<void> {
|
|
||||||
if (!this.downloadCourseEnabled) {
|
|
||||||
// Cannot download the whole course, stop.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the course prefetch status.
|
|
||||||
await this.determineCoursePrefetchIcon();
|
|
||||||
|
|
||||||
if (this.prefetchCourseData.icon != CoreConstants.ICON_LOADING) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Course is being downloaded. Get the download promise.
|
|
||||||
const promise = CoreCourseHelper.getCourseDownloadPromise(this.course.id);
|
|
||||||
if (promise) {
|
|
||||||
// There is a download promise. Show an error if it fails.
|
|
||||||
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.
|
|
||||||
const status = await CoreCourse.setCoursePreviousStatus(this.course.id);
|
|
||||||
|
|
||||||
this.updateCourseStatus(status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch and load all the data required for the view.
|
* Fetch and load all the data required for the view.
|
||||||
*
|
*
|
||||||
|
@ -463,59 +379,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines the prefetch icon of the course.
|
|
||||||
*
|
|
||||||
* @return Promise resolved when done.
|
|
||||||
*/
|
|
||||||
protected async determineCoursePrefetchIcon(): Promise<void> {
|
|
||||||
this.prefetchCourseData = await CoreCourseHelper.getCourseStatusIconAndTitle(this.course.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prefetch the whole course.
|
|
||||||
*/
|
|
||||||
async prefetchCourse(): Promise<void> {
|
|
||||||
try {
|
|
||||||
await CoreCourseHelper.confirmAndPrefetchCourse(
|
|
||||||
this.prefetchCourseData,
|
|
||||||
this.course,
|
|
||||||
{
|
|
||||||
sections: this.sections,
|
|
||||||
menuHandlers: this.courseMenuHandlers,
|
|
||||||
isGuest: this.isGuest,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
if (this.isDestroyed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle download enabled.
|
|
||||||
*/
|
|
||||||
toggleDownload(): void {
|
|
||||||
CoreCourses.setCourseDownloadOptionsEnabled(this.downloadEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the course summary
|
* Open the course summary
|
||||||
*/
|
*/
|
||||||
|
@ -542,10 +405,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.isDestroyed = true;
|
this.isDestroyed = true;
|
||||||
this.completionObserver?.off();
|
this.completionObserver?.off();
|
||||||
this.courseStatusObserver?.off();
|
|
||||||
this.syncObserver?.off();
|
this.syncObserver?.off();
|
||||||
this.siteUpdatedObserver?.off();
|
|
||||||
this.downloadEnabledObserver?.off();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,8 +19,7 @@
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ng-container *ngFor="let section of sections">
|
<ng-container *ngFor="let section of sections">
|
||||||
<ng-container *ngFor="let module of section.modules">
|
<ng-container *ngFor="let module of section.modules">
|
||||||
<core-course-module *ngIf="module.visibleoncoursepage !== 0" [module]="module" [section]="section" [courseId]="courseId"
|
<core-course-module *ngIf="module.visibleoncoursepage !== 0" [module]="module" [section]="section">
|
||||||
[downloadEnabled]="downloadEnabled">
|
|
||||||
</core-course-module>
|
</core-course-module>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
import { CoreSites } from '@services/sites';
|
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreCourse } from '@features/course/services/course';
|
import { CoreCourse } from '@features/course/services/course';
|
||||||
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
|
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
|
||||||
|
@ -36,7 +35,6 @@ export class CoreCourseListModTypePage implements OnInit {
|
||||||
sections: CoreCourseSection[] = [];
|
sections: CoreCourseSection[] = [];
|
||||||
title = '';
|
title = '';
|
||||||
loaded = false;
|
loaded = false;
|
||||||
downloadEnabled = false;
|
|
||||||
courseId?: number;
|
courseId?: number;
|
||||||
|
|
||||||
protected modName?: string;
|
protected modName?: string;
|
||||||
|
@ -49,7 +47,6 @@ export class CoreCourseListModTypePage implements OnInit {
|
||||||
this.title = CoreNavigator.getRouteParam('title') || '';
|
this.title = CoreNavigator.getRouteParam('title') || '';
|
||||||
this.courseId = CoreNavigator.getRouteNumberParam('courseId');
|
this.courseId = CoreNavigator.getRouteNumberParam('courseId');
|
||||||
this.modName = CoreNavigator.getRouteParam('modName');
|
this.modName = CoreNavigator.getRouteParam('modName');
|
||||||
this.downloadEnabled = !CoreSites.getCurrentSite()?.isOfflineDisabled();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.fetchData();
|
await this.fetchData();
|
||||||
|
|
|
@ -58,8 +58,9 @@ export interface CoreCourseFormatHandler extends CoreDelegateHandler {
|
||||||
displayBlocks?(course: CoreCourseAnyCourseData): boolean;
|
displayBlocks?(course: CoreCourseAnyCourseData): boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the option to enable section/module download should be displayed. Defaults to true.
|
* Whether the option to enable section/module download should be displayed.
|
||||||
*
|
*
|
||||||
|
* @deprecated on 4.0 Not used anymore because prefetch has been moved to storage manager.
|
||||||
* @param course The course to check.
|
* @param course The course to check.
|
||||||
* @return Whether the option to enable section/module download should be displayed.
|
* @return Whether the option to enable section/module download should be displayed.
|
||||||
*/
|
*/
|
||||||
|
@ -204,16 +205,6 @@ export class CoreCourseFormatDelegateService extends CoreDelegate<CoreCourseForm
|
||||||
return !!this.executeFunctionOnEnabled<boolean>(course.format || '', 'displayBlocks', [course]);
|
return !!this.executeFunctionOnEnabled<boolean>(course.format || '', 'displayBlocks', [course]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the option to enable section/module download should be displayed. Defaults to true.
|
|
||||||
*
|
|
||||||
* @param course The course to check.
|
|
||||||
* @return Whether the option to enable section/module download should be displayed
|
|
||||||
*/
|
|
||||||
displayEnableDownload(course: CoreCourseAnyCourseData): boolean {
|
|
||||||
return !!this.executeFunctionOnEnabled<boolean>(course.format || '', 'displayEnableDownload', [course]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the course refresher should be displayed. If it returns false, a refresher must be included in the course format,
|
* Whether the course refresher should be displayed. If it returns false, a refresher must be included in the course format,
|
||||||
* and the doRefresh method of CoreCourseSectionPage must be called on refresh. Defaults to true.
|
* and the doRefresh method of CoreCourseSectionPage must be called on refresh. Defaults to true.
|
||||||
|
|
|
@ -78,17 +78,6 @@ export class CoreCourseFormatDefaultHandler implements CoreCourseFormatHandler {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the option to enable section/module download should be displayed. Defaults to true.
|
|
||||||
*
|
|
||||||
* @param course The course to check.
|
|
||||||
* @return Whether the option to enable section/module download should be displayed
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
displayEnableDownload(course: CoreCourseAnyCourseData): boolean {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the default section selector should be displayed. Defaults to true.
|
* Whether the default section selector should be displayed. Defaults to true.
|
||||||
*
|
*
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
||||||
<core-block-side-blocks-button *ngIf="hasSideBlocks" [downloadEnabled]="downloadEnabled"></core-block-side-blocks-button>
|
<core-block-side-blocks-button *ngIf="hasSideBlocks"></core-block-side-blocks-button>
|
||||||
|
|
||||||
<core-empty-box *ngIf="blocks.length == 0" icon="fas-cubes" [message]="'core.course.nocontentavailable' | translate">
|
<core-empty-box *ngIf="blocks.length == 0" icon="fas-cubes" [message]="'core.course.nocontentavailable' | translate">
|
||||||
</core-empty-box>
|
</core-empty-box>
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
<ion-icon name="fas-search" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-search" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<core-context-menu>
|
<core-context-menu>
|
||||||
<core-context-menu-item [priority]="1000" *ngIf="displayEnableDownload" [content]="'core.settings.showdownloadoptions' | translate"
|
|
||||||
(action)="switchDownload()" iconAction="toggle" [(toggle)]="downloadEnabled"></core-context-menu-item>
|
|
||||||
<core-context-menu-item [priority]="500" [content]="'addon.storagemanager.managestorage' | translate"
|
<core-context-menu-item [priority]="500" [content]="'addon.storagemanager.managestorage' | translate"
|
||||||
(action)="manageCoursesStorage()" iconAction="fas-archive"></core-context-menu-item>
|
(action)="manageCoursesStorage()" iconAction="fas-archive"></core-context-menu-item>
|
||||||
<core-context-menu-item [priority]="400" [content]="'addon.storagemanager.managecoursestorage' | translate"
|
<core-context-menu-item [priority]="400" [content]="'addon.storagemanager.managecoursestorage' | translate"
|
||||||
|
@ -26,8 +24,7 @@
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<core-course-module *ngFor="let module of section.modules" [module]="module" [courseId]="siteHomeId"
|
<core-course-module *ngFor="let module of section.modules" [module]="module" [section]="section"></core-course-module>
|
||||||
[downloadEnabled]="downloadEnabled" [section]="section"></core-course-module>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Site home items: news, categories, courses, etc. -->
|
<!-- Site home items: news, categories, courses, etc. -->
|
||||||
|
@ -54,7 +51,7 @@
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
<core-block-side-blocks-button *ngIf="hasBlocks" [courseId]="siteHomeId" [downloadEnabled]="downloadEnabled">
|
<core-block-side-blocks-button *ngIf="hasBlocks" [courseId]="siteHomeId">
|
||||||
</core-block-side-blocks-button>
|
</core-block-side-blocks-button>
|
||||||
|
|
||||||
<core-empty-box *ngIf="!hasContent" icon="fas-box-open" [message]="'core.course.nocontentavailable' | translate">
|
<core-empty-box *ngIf="!hasContent" icon="fas-box-open" [message]="'core.course.nocontentavailable' | translate">
|
||||||
|
@ -73,8 +70,7 @@
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #news>
|
<ng-template #news>
|
||||||
<core-course-module class="core-sitehome-news" *ngIf="newsForumModule" [module]="newsForumModule" [courseId]="siteHomeId"
|
<core-course-module class="core-sitehome-news" *ngIf="newsForumModule" [module]="newsForumModule">
|
||||||
[downloadEnabled]="downloadEnabled">
|
|
||||||
</core-course-module>
|
</core-course-module>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { CoreCourse, CoreCourseWSSection } from '@features/course/services/cours
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreSiteHome } from '@features/sitehome/services/sitehome';
|
import { CoreSiteHome } from '@features/sitehome/services/sitehome';
|
||||||
import { CoreCourses, CoreCoursesProvider } from '@features//courses/services/courses';
|
import { CoreCourses } from '@features//courses/services/courses';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper';
|
import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper';
|
||||||
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
|
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
|
||||||
|
@ -50,24 +50,15 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy {
|
||||||
siteHomeId = 1;
|
siteHomeId = 1;
|
||||||
currentSite!: CoreSite;
|
currentSite!: CoreSite;
|
||||||
searchEnabled = false;
|
searchEnabled = false;
|
||||||
displayEnableDownload = false;
|
|
||||||
downloadEnabled = false;
|
|
||||||
newsForumModule?: CoreCourseModuleData;
|
newsForumModule?: CoreCourseModuleData;
|
||||||
|
|
||||||
protected updateSiteObserver: CoreEventObserver;
|
protected updateSiteObserver: CoreEventObserver;
|
||||||
protected downloadEnabledObserver: CoreEventObserver;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// Refresh the enabled flags if site is updated.
|
// Refresh the enabled flags if site is updated.
|
||||||
this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => {
|
this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => {
|
||||||
this.searchEnabled = !CoreCourses.isSearchCoursesDisabledInSite();
|
this.searchEnabled = !CoreCourses.isSearchCoursesDisabledInSite();
|
||||||
|
|
||||||
this.displayEnableDownload = !CoreSites.getRequiredCurrentSite().isOfflineDisabled();
|
|
||||||
}, CoreSites.getCurrentSiteId());
|
}, CoreSites.getCurrentSiteId());
|
||||||
|
|
||||||
this.downloadEnabledObserver = CoreEvents.on(CoreCoursesProvider.EVENT_DASHBOARD_DOWNLOAD_ENABLED_CHANGED, (data) => {
|
|
||||||
this.downloadEnabled = data.enabled;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,9 +76,6 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy {
|
||||||
CoreCourseHelper.openModule(module, this.siteHomeId, undefined, modParams);
|
CoreCourseHelper.openModule(module, this.siteHomeId, undefined, modParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.displayEnableDownload = !CoreSites.getRequiredCurrentSite().isOfflineDisabled();
|
|
||||||
this.downloadEnabled = CoreCourses.getCourseDownloadOptionsEnabled();
|
|
||||||
|
|
||||||
this.loadContent().finally(() => {
|
this.loadContent().finally(() => {
|
||||||
this.dataLoaded = true;
|
this.dataLoaded = true;
|
||||||
});
|
});
|
||||||
|
@ -186,13 +174,6 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Switch download enabled.
|
|
||||||
*/
|
|
||||||
switchDownload(): void {
|
|
||||||
CoreCourses.setCourseDownloadOptionsEnabled(this.downloadEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open page to manage courses storage.
|
* Open page to manage courses storage.
|
||||||
*/
|
*/
|
||||||
|
@ -240,7 +221,6 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy {
|
||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.updateSiteObserver.off();
|
this.updateSiteObserver.off();
|
||||||
this.downloadEnabledObserver.off();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,13 +35,6 @@ export class CoreSitePluginsCourseFormatHandler extends CoreSitePluginsBaseHandl
|
||||||
return this.handlerSchema.canviewallsections ?? true;
|
return this.handlerSchema.canviewallsections ?? true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
displayEnableDownload(): boolean {
|
|
||||||
return this.handlerSchema.displayenabledownload ?? true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,6 +9,7 @@ information provided here is intended especially for developers.
|
||||||
- CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor now admits module name instead of full module object.
|
- CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor now admits module name instead of full module object.
|
||||||
- CoreCourse.getModuleBasicInfoByInstance and CoreCourse.getModuleBasicInfo have been modified to accept an "options" parameter instead of only siteId.
|
- CoreCourse.getModuleBasicInfoByInstance and CoreCourse.getModuleBasicInfo have been modified to accept an "options" parameter instead of only siteId.
|
||||||
- The function CoreFilepool.isFileDownloadingByUrl now returns Promise<boolean> instead of relying on resolve/reject.
|
- The function CoreFilepool.isFileDownloadingByUrl now returns Promise<boolean> instead of relying on resolve/reject.
|
||||||
|
- downloadEnabled input has been removed from CoreBlockSideBlocksComponent, CoreCourseFormatComponent, CoreCourseFormatSingleActivityComponent and CoreCourseModuleComponent.
|
||||||
|
|
||||||
=== 3.9.5 ===
|
=== 3.9.5 ===
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue