diff --git a/src/core/features/course/components/components.module.ts b/src/core/features/course/components/components.module.ts index dcac3d294..72b78780f 100644 --- a/src/core/features/course/components/components.module.ts +++ b/src/core/features/course/components/components.module.ts @@ -16,7 +16,6 @@ import { NgModule } from '@angular/core'; import { CoreSharedModule } from '@/core/shared.module'; import { CoreBlockComponentsModule } from '@features/block/components/components.module'; -import { CoreCourseFormatComponent } from './course-format/course-format'; import { CoreCourseModuleComponent } from './module/module'; import { CoreCourseModuleCompletionComponent } from './module-completion/module-completion'; import { CoreCourseTagAreaComponent } from './tag-area/tag-area'; @@ -30,7 +29,6 @@ import { CoreCourseModuleCompletionDetailsComponent } from './module-completion- @NgModule({ declarations: [ - CoreCourseFormatComponent, CoreCourseModuleComponent, CoreCourseModuleCompletionComponent, CoreCourseModuleCompletionLegacyComponent, @@ -47,7 +45,6 @@ import { CoreCourseModuleCompletionDetailsComponent } from './module-completion- CoreSharedModule, ], exports: [ - CoreCourseFormatComponent, CoreCourseModuleComponent, CoreCourseModuleCompletionComponent, CoreCourseModuleCompletionLegacyComponent, diff --git a/src/core/features/course/components/course-format/course-format.ts b/src/core/features/course/components/course-format/course-format.ts index e89377e26..311864b22 100644 --- a/src/core/features/course/components/course-format/course-format.ts +++ b/src/core/features/course/components/course-format/course-format.ts @@ -53,6 +53,11 @@ import { CoreUserTourDirectiveOptions } from '@directives/user-tour'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { ContextLevel } from '@/core/constants'; import { CoreModals } from '@services/modals'; +import { CoreSharedModule } from '@/core/shared.module'; +import { CoreBlockComponentsModule } from '@features/block/components/components.module'; +import { CoreCourseComponentsModule } from '../components.module'; +import { CoreSites } from '@services/sites'; +import { COURSE_ALL_SECTIONS_PREFERRED_PREFIX } from '@features/course/constants'; /** * Component to display course contents using a certain format. If the format isn't found, use default one. @@ -68,6 +73,12 @@ import { CoreModals } from '@services/modals'; selector: 'core-course-format', templateUrl: 'course-format.html', styleUrls: ['course-format.scss'], + standalone: true, + imports: [ + CoreSharedModule, + CoreBlockComponentsModule, + CoreCourseComponentsModule, + ], }) export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { @@ -307,8 +318,8 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { } else if (this.initialSectionId || this.initialSectionNumber !== undefined) { // We have an input indicating the section ID to load. Search the section. const section = sections.find((section) => - section.id == this.initialSectionId || - (section.section !== undefined && section.section == this.initialSectionNumber)); + section.id === this.initialSectionId || + (section.section !== undefined && section.section === this.initialSectionNumber)); // Don't load the section if it cannot be viewed by the user. if (section && this.canViewSection(section)) { @@ -328,6 +339,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { }); } + const allSectionsPreferred = await this.isAllSectionsPreferred(); if (!this.loaded) { // No section specified, not found or not visible, load current section or the section with last module viewed. const currentSectionData = await CoreCourseFormatDelegate.getCurrentSection(this.course, sections); @@ -336,15 +348,18 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { let section = currentSectionData.section; let moduleId: number | undefined; - if (!currentSectionData.forceSelected && lastModuleViewed) { - // Search the section with the last module viewed. - const lastModuleSection = this.getViewedModuleSection(sections, lastModuleViewed); + // If all sections is not preferred, load the last viewed module section. + if (!allSectionsPreferred && lastModuleViewed) { + if (!currentSectionData.forceSelected) { + // Search the section with the last module viewed. + const lastModuleSection = this.getViewedModuleSection(sections, lastModuleViewed); - section = lastModuleSection || section; - moduleId = lastModuleSection ? lastModuleViewed?.cmId : undefined; - } else if (lastModuleViewed && currentSectionData.section.modules.some(module => module.id === lastModuleViewed.cmId)) { - // Last module viewed is inside the highlighted section. - moduleId = lastModuleViewed.cmId; + section = lastModuleSection || section; + moduleId = lastModuleSection ? lastModuleViewed?.cmId : undefined; + } else if (currentSectionData.section.modules.some(module => module.id === lastModuleViewed.cmId)) { + // Last module viewed is inside the highlighted section. + moduleId = lastModuleViewed.cmId; + } } this.loaded = true; @@ -447,7 +462,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { if (!data) { return; } - const section = this.sections.find((section) => section.id == data.sectionId); + const section = this.sections.find((section) => section.id === data.sectionId); if (!section) { return; } @@ -456,7 +471,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { if (!data.moduleId) { return; } - const module = section.modules.find((module) => module.id == data.moduleId); + const module = section.modules.find((module) => module.id === data.moduleId); if (!module) { return; } @@ -504,7 +519,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { this.selectedSection = newSection; this.data.section = this.selectedSection; - if (newSection.id != this.allSectionsId) { + if (newSection.id !== this.allSectionsId) { // Select next and previous sections to show the arrows. const i = this.sections.findIndex((value) => this.compareSections(value, newSection)); @@ -522,11 +537,13 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { } } this.nextSection = j < this.sections.length ? this.sections[j] : undefined; + this.setAllSectionsPreferred(false); } else { this.previousSection = undefined; this.nextSection = undefined; this.lastShownSectionIndex = -1; this.showMoreActivities(); + this.setAllSectionsPreferred(true); } // Scroll to module if needed. Give more priority to the input. @@ -689,6 +706,31 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { }); } + /** + * Set all sections is preferred for the course. + * + * @param show Whether if all sections is preferred. + */ + async setAllSectionsPreferred(show: boolean): Promise { + const site = CoreSites.getCurrentSite(); + + await site?.setLocalSiteConfig(`${COURSE_ALL_SECTIONS_PREFERRED_PREFIX}${this.course.id}`, show ? 1 : 0); + } + + /** + * Check if all sections is preferred for the course. + * + * @returns Whether if all sections is preferred. + */ + async isAllSectionsPreferred(): Promise { + const site = CoreSites.getCurrentSite(); + + const showAllSections = + await site?.getLocalSiteConfig(`${COURSE_ALL_SECTIONS_PREFERRED_PREFIX}${this.course.id}`, 0); + + return !!showAllSections; + } + } type CoreCourseSectionToDisplay = CoreCourseSection & { diff --git a/src/core/features/course/constants.ts b/src/core/features/course/constants.ts index 1917eb51e..df774a9a8 100644 --- a/src/core/features/course/constants.ts +++ b/src/core/features/course/constants.ts @@ -16,3 +16,5 @@ export const COURSE_INDEX_PATH = ':courseId'; export const COURSE_PAGE_NAME = 'course'; export const CONTENTS_PAGE_NAME = 'contents'; export const COURSE_CONTENTS_PATH = `${COURSE_PAGE_NAME}/${COURSE_INDEX_PATH}/${CONTENTS_PAGE_NAME}`; + +export const COURSE_ALL_SECTIONS_PREFERRED_PREFIX = 'CoreCourseFormatAllSectionsPreferred-'; diff --git a/src/core/features/course/course-contents-lazy.module.ts b/src/core/features/course/course-contents-lazy.module.ts index fbbd96d6d..0d1d84b74 100644 --- a/src/core/features/course/course-contents-lazy.module.ts +++ b/src/core/features/course/course-contents-lazy.module.ts @@ -19,6 +19,7 @@ import { CoreCourseComponentsModule } from '@features/course/components/componen import { CoreSharedModule } from '@/core/shared.module'; import { resolveContentsRoutes } from '@features/course/course-contents-routing.module'; import { CoreCourseContentsPage } from '@features/course/pages/contents/contents'; +import { CoreCourseFormatComponent } from './components/course-format/course-format'; /** * Build module routes. @@ -46,6 +47,7 @@ function buildRoutes(injector: Injector): Routes { imports: [ CoreSharedModule, CoreCourseComponentsModule, + CoreCourseFormatComponent, ], declarations: [ CoreCourseContentsPage, diff --git a/src/core/features/course/course.module.ts b/src/core/features/course/course.module.ts index bddcbe8a4..1cd36f03a 100644 --- a/src/core/features/course/course.module.ts +++ b/src/core/features/course/course.module.ts @@ -99,10 +99,13 @@ export async function getCourseStandaloneComponents(): Promise[]> // eslint-disable-next-line deprecation/deprecation const { CoreCourseModuleManualCompletionComponent } = await import('@features/course/components/module-manual-completion/module-manual-completion'); + const { CoreCourseFormatComponent } = + await import('@features/course/components/course-format/course-format'); return [ CoreCourseModuleDescriptionComponent, CoreCourseModuleManualCompletionComponent, + CoreCourseFormatComponent, ]; } diff --git a/src/core/features/course/services/course.ts b/src/core/features/course/services/course.ts index dfb5e833e..2e6b48830 100644 --- a/src/core/features/course/services/course.ts +++ b/src/core/features/course/services/course.ts @@ -1400,7 +1400,7 @@ export class CoreCourseProvider { }); return; - } catch (error) { + } catch { // The site plugin failed to load. The user needs to restart the app to try loading it again. const message = Translate.instant('core.courses.errorloadplugins'); const reload = Translate.instant('core.courses.reload');