Merge pull request #4132 from crazyserver/MOBILE-4389

Mobile 4389
main
Dani Palou 2024-07-30 08:35:44 +02:00 committed by GitHub
commit 23da49dbb6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 63 additions and 17 deletions

View File

@ -16,7 +16,6 @@ import { NgModule } from '@angular/core';
import { CoreSharedModule } from '@/core/shared.module'; import { CoreSharedModule } from '@/core/shared.module';
import { CoreBlockComponentsModule } from '@features/block/components/components.module'; import { CoreBlockComponentsModule } from '@features/block/components/components.module';
import { CoreCourseFormatComponent } from './course-format/course-format';
import { CoreCourseModuleComponent } from './module/module'; import { CoreCourseModuleComponent } from './module/module';
import { CoreCourseModuleCompletionComponent } from './module-completion/module-completion'; import { CoreCourseModuleCompletionComponent } from './module-completion/module-completion';
import { CoreCourseTagAreaComponent } from './tag-area/tag-area'; import { CoreCourseTagAreaComponent } from './tag-area/tag-area';
@ -30,7 +29,6 @@ import { CoreCourseModuleCompletionDetailsComponent } from './module-completion-
@NgModule({ @NgModule({
declarations: [ declarations: [
CoreCourseFormatComponent,
CoreCourseModuleComponent, CoreCourseModuleComponent,
CoreCourseModuleCompletionComponent, CoreCourseModuleCompletionComponent,
CoreCourseModuleCompletionLegacyComponent, CoreCourseModuleCompletionLegacyComponent,
@ -47,7 +45,6 @@ import { CoreCourseModuleCompletionDetailsComponent } from './module-completion-
CoreSharedModule, CoreSharedModule,
], ],
exports: [ exports: [
CoreCourseFormatComponent,
CoreCourseModuleComponent, CoreCourseModuleComponent,
CoreCourseModuleCompletionComponent, CoreCourseModuleCompletionComponent,
CoreCourseModuleCompletionLegacyComponent, CoreCourseModuleCompletionLegacyComponent,

View File

@ -53,6 +53,11 @@ import { CoreUserTourDirectiveOptions } from '@directives/user-tour';
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
import { ContextLevel } from '@/core/constants'; import { ContextLevel } from '@/core/constants';
import { CoreModals } from '@services/modals'; 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. * 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', selector: 'core-course-format',
templateUrl: 'course-format.html', templateUrl: 'course-format.html',
styleUrls: ['course-format.scss'], styleUrls: ['course-format.scss'],
standalone: true,
imports: [
CoreSharedModule,
CoreBlockComponentsModule,
CoreCourseComponentsModule,
],
}) })
export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { 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) { } else if (this.initialSectionId || this.initialSectionNumber !== undefined) {
// We have an input indicating the section ID to load. Search the section. // We have an input indicating the section ID to load. Search the section.
const section = sections.find((section) => const section = sections.find((section) =>
section.id == this.initialSectionId || section.id === this.initialSectionId ||
(section.section !== undefined && section.section == this.initialSectionNumber)); (section.section !== undefined && section.section === this.initialSectionNumber));
// Don't load the section if it cannot be viewed by the user. // Don't load the section if it cannot be viewed by the user.
if (section && this.canViewSection(section)) { if (section && this.canViewSection(section)) {
@ -328,6 +339,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
}); });
} }
const allSectionsPreferred = await this.isAllSectionsPreferred();
if (!this.loaded) { if (!this.loaded) {
// No section specified, not found or not visible, load current section or the section with last module viewed. // 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); const currentSectionData = await CoreCourseFormatDelegate.getCurrentSection(this.course, sections);
@ -336,16 +348,19 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
let section = currentSectionData.section; let section = currentSectionData.section;
let moduleId: number | undefined; let moduleId: number | undefined;
if (!currentSectionData.forceSelected && 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. // Search the section with the last module viewed.
const lastModuleSection = this.getViewedModuleSection(sections, lastModuleViewed); const lastModuleSection = this.getViewedModuleSection(sections, lastModuleViewed);
section = lastModuleSection || section; section = lastModuleSection || section;
moduleId = lastModuleSection ? lastModuleViewed?.cmId : undefined; moduleId = lastModuleSection ? lastModuleViewed?.cmId : undefined;
} else if (lastModuleViewed && currentSectionData.section.modules.some(module => module.id === lastModuleViewed.cmId)) { } else if (currentSectionData.section.modules.some(module => module.id === lastModuleViewed.cmId)) {
// Last module viewed is inside the highlighted section. // Last module viewed is inside the highlighted section.
moduleId = lastModuleViewed.cmId; moduleId = lastModuleViewed.cmId;
} }
}
this.loaded = true; this.loaded = true;
this.sectionChanged(section, moduleId); this.sectionChanged(section, moduleId);
@ -447,7 +462,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
if (!data) { if (!data) {
return; return;
} }
const section = this.sections.find((section) => section.id == data.sectionId); const section = this.sections.find((section) => section.id === data.sectionId);
if (!section) { if (!section) {
return; return;
} }
@ -456,7 +471,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
if (!data.moduleId) { if (!data.moduleId) {
return; return;
} }
const module = section.modules.find((module) => module.id == data.moduleId); const module = section.modules.find((module) => module.id === data.moduleId);
if (!module) { if (!module) {
return; return;
} }
@ -504,7 +519,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
this.selectedSection = newSection; this.selectedSection = newSection;
this.data.section = this.selectedSection; this.data.section = this.selectedSection;
if (newSection.id != this.allSectionsId) { if (newSection.id !== this.allSectionsId) {
// Select next and previous sections to show the arrows. // Select next and previous sections to show the arrows.
const i = this.sections.findIndex((value) => this.compareSections(value, newSection)); 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.nextSection = j < this.sections.length ? this.sections[j] : undefined;
this.setAllSectionsPreferred(false);
} else { } else {
this.previousSection = undefined; this.previousSection = undefined;
this.nextSection = undefined; this.nextSection = undefined;
this.lastShownSectionIndex = -1; this.lastShownSectionIndex = -1;
this.showMoreActivities(); this.showMoreActivities();
this.setAllSectionsPreferred(true);
} }
// Scroll to module if needed. Give more priority to the input. // 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<void> {
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<boolean> {
const site = CoreSites.getCurrentSite();
const showAllSections =
await site?.getLocalSiteConfig<number>(`${COURSE_ALL_SECTIONS_PREFERRED_PREFIX}${this.course.id}`, 0);
return !!showAllSections;
}
} }
type CoreCourseSectionToDisplay = CoreCourseSection & { type CoreCourseSectionToDisplay = CoreCourseSection & {

View File

@ -16,3 +16,5 @@ export const COURSE_INDEX_PATH = ':courseId';
export const COURSE_PAGE_NAME = 'course'; export const COURSE_PAGE_NAME = 'course';
export const CONTENTS_PAGE_NAME = 'contents'; export const CONTENTS_PAGE_NAME = 'contents';
export const COURSE_CONTENTS_PATH = `${COURSE_PAGE_NAME}/${COURSE_INDEX_PATH}/${CONTENTS_PAGE_NAME}`; export const COURSE_CONTENTS_PATH = `${COURSE_PAGE_NAME}/${COURSE_INDEX_PATH}/${CONTENTS_PAGE_NAME}`;
export const COURSE_ALL_SECTIONS_PREFERRED_PREFIX = 'CoreCourseFormatAllSectionsPreferred-';

View File

@ -19,6 +19,7 @@ import { CoreCourseComponentsModule } from '@features/course/components/componen
import { CoreSharedModule } from '@/core/shared.module'; import { CoreSharedModule } from '@/core/shared.module';
import { resolveContentsRoutes } from '@features/course/course-contents-routing.module'; import { resolveContentsRoutes } from '@features/course/course-contents-routing.module';
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents'; import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
import { CoreCourseFormatComponent } from './components/course-format/course-format';
/** /**
* Build module routes. * Build module routes.
@ -46,6 +47,7 @@ function buildRoutes(injector: Injector): Routes {
imports: [ imports: [
CoreSharedModule, CoreSharedModule,
CoreCourseComponentsModule, CoreCourseComponentsModule,
CoreCourseFormatComponent,
], ],
declarations: [ declarations: [
CoreCourseContentsPage, CoreCourseContentsPage,

View File

@ -99,10 +99,13 @@ export async function getCourseStandaloneComponents(): Promise<Type<unknown>[]>
// eslint-disable-next-line deprecation/deprecation // eslint-disable-next-line deprecation/deprecation
const { CoreCourseModuleManualCompletionComponent } = const { CoreCourseModuleManualCompletionComponent } =
await import('@features/course/components/module-manual-completion/module-manual-completion'); await import('@features/course/components/module-manual-completion/module-manual-completion');
const { CoreCourseFormatComponent } =
await import('@features/course/components/course-format/course-format');
return [ return [
CoreCourseModuleDescriptionComponent, CoreCourseModuleDescriptionComponent,
CoreCourseModuleManualCompletionComponent, CoreCourseModuleManualCompletionComponent,
CoreCourseFormatComponent,
]; ];
} }

View File

@ -1400,7 +1400,7 @@ export class CoreCourseProvider {
}); });
return; return;
} catch (error) { } catch {
// The site plugin failed to load. The user needs to restart the app to try loading it again. // 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 message = Translate.instant('core.courses.errorloadplugins');
const reload = Translate.instant('core.courses.reload'); const reload = Translate.instant('core.courses.reload');