forked from EVOgeek/Vmeda.Online
		
	
						commit
						4e210350e5
					
				| @ -22,7 +22,7 @@ const THRESHOLD = .15; // % of the scroll element height that must be close to t | |||||||
|  * Component to show a infinite loading trigger and spinner while more data is being loaded. |  * Component to show a infinite loading trigger and spinner while more data is being loaded. | ||||||
|  * |  * | ||||||
|  * Usage: |  * Usage: | ||||||
|  * <core-infinite-loading [action]="loadingAction" [enabled]="dataLoaded"></core-inifinite-loading> |  * <core-infinite-loading [action]="loadingAction" [enabled]="dataLoaded"></core-infinite-loading> | ||||||
|  */ |  */ | ||||||
| @Component({ | @Component({ | ||||||
|     selector: 'core-infinite-loading', |     selector: 'core-infinite-loading', | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ | |||||||
|         <div *ngIf="selectedSection && selectedSection.id == allSectionsId"> |         <div *ngIf="selectedSection && selectedSection.id == allSectionsId"> | ||||||
|             <core-dynamic-component [component]="allSectionsComponent" [data]="data"> |             <core-dynamic-component [component]="allSectionsComponent" [data]="data"> | ||||||
|                 <ng-container *ngFor="let section of sections; index as i"> |                 <ng-container *ngFor="let section of sections; index as i"> | ||||||
|                     <ng-container *ngIf="i <= showSectionId"> |                     <ng-container *ngIf="i <= lastShownSectionIndex"> | ||||||
|                         <ng-container *ngTemplateOutlet="sectionTemplate; context: {section: section}"></ng-container> |                         <ng-container *ngTemplateOutlet="sectionTemplate; context: {section: section}"></ng-container> | ||||||
|                     </ng-container> |                     </ng-container> | ||||||
|                 </ng-container> |                 </ng-container> | ||||||
|  | |||||||
| @ -70,7 +70,7 @@ import { CoreBlockSideBlocksComponent } from '@features/block/components/side-bl | |||||||
| }) | }) | ||||||
| export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { | 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 = 10; // 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: CoreCourseSectionToDisplay[] = []; // List of course sections.
 |     @Input() sections: CoreCourseSectionToDisplay[] = []; // List of course sections.
 | ||||||
| @ -89,7 +89,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { | |||||||
|     allSectionsComponent?: Type<unknown>; |     allSectionsComponent?: Type<unknown>; | ||||||
| 
 | 
 | ||||||
|     canLoadMore = false; |     canLoadMore = false; | ||||||
|     showSectionId = 0; |     lastShownSectionIndex = 0; | ||||||
|     data: Record<string, unknown> = {}; // Data to pass to the components.
 |     data: Record<string, unknown> = {}; // Data to pass to the components.
 | ||||||
|     courseIndexTour: CoreUserTourDirectiveOptions = { |     courseIndexTour: CoreUserTourDirectiveOptions = { | ||||||
|         id: 'course-index', |         id: 'course-index', | ||||||
| @ -514,8 +514,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { | |||||||
|         } else { |         } else { | ||||||
|             this.previousSection = undefined; |             this.previousSection = undefined; | ||||||
|             this.nextSection = undefined; |             this.nextSection = undefined; | ||||||
|             this.canLoadMore = false; |             this.lastShownSectionIndex = -1; | ||||||
|             this.showSectionId = 0; |  | ||||||
|             this.showMoreActivities(); |             this.showMoreActivities(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -594,40 +593,22 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { | |||||||
|      * @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading. |      * @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading. | ||||||
|      */ |      */ | ||||||
|     showMoreActivities(infiniteComplete?: () => void): void { |     showMoreActivities(infiniteComplete?: () => void): void { | ||||||
|         this.canLoadMore = false; |  | ||||||
| 
 |  | ||||||
|         const sections = this.sections || []; |  | ||||||
|         let modulesLoaded = 0; |         let modulesLoaded = 0; | ||||||
|         let i: number; |         while (this.lastShownSectionIndex < this.sections.length - 1 && | ||||||
|         for (i = this.showSectionId + 1; i < sections.length; i++) { |             modulesLoaded < CoreCourseFormatComponent.LOAD_MORE_ACTIVITIES) { | ||||||
|             if (!sections[i].hasContent || !sections[i].modules) { |             this.lastShownSectionIndex++; | ||||||
|  | 
 | ||||||
|  |             if (!this.sections[this.lastShownSectionIndex].hasContent || !this.sections[this.lastShownSectionIndex].modules) { | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             modulesLoaded += sections[i].modules.reduce((total, module) => |             modulesLoaded += this.sections[this.lastShownSectionIndex].modules.reduce((total, module) => | ||||||
|                 !CoreCourseHelper.isModuleStealth(module, sections[i]) ? total + 1 : total, 0); |                 !CoreCourseHelper.isModuleStealth(module, this.sections[this.lastShownSectionIndex]) ? total + 1 : total, 0); | ||||||
| 
 |  | ||||||
|             if (modulesLoaded >= CoreCourseFormatComponent.LOAD_MORE_ACTIVITIES) { |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         this.showSectionId = i; |         this.canLoadMore = this.lastShownSectionIndex < this.sections.length - 1; | ||||||
|         this.canLoadMore = i < sections.length; |  | ||||||
| 
 | 
 | ||||||
|         if (this.canLoadMore) { |         infiniteComplete?.(); | ||||||
|             // Check if any of the following sections have any content.
 |  | ||||||
|             let thereAreMore = false; |  | ||||||
|             for (i++; i < sections.length; i++) { |  | ||||||
|                 if (sections[i].hasContent && sections[i].modules && sections[i].modules?.length > 0) { |  | ||||||
|                     thereAreMore = true; |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             this.canLoadMore = thereAreMore; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         infiniteComplete && infiniteComplete(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ | |||||||
|                                 {{ 'core.course.hiddenfromstudents' | translate }} |                                 {{ 'core.course.hiddenfromstudents' | translate }} | ||||||
|                             </ion-badge> |                             </ion-badge> | ||||||
|                             <ion-badge color="secondary" *ngIf="module.visible !== 0 && module.isStealth" class="ion-text-wrap"> |                             <ion-badge color="secondary" *ngIf="module.visible !== 0 && module.isStealth" class="ion-text-wrap"> | ||||||
|                                 <ion-icon name="fas-low-vision" aria-hidden="true"></ion-icon> |                                 <ion-icon name="fas-eye-low-vision" aria-hidden="true"></ion-icon> | ||||||
|                                 {{ 'core.course.hiddenoncoursepage' | translate }} |                                 {{ 'core.course.hiddenoncoursepage' | translate }} | ||||||
|                             </ion-badge> |                             </ion-badge> | ||||||
|                         </div> |                         </div> | ||||||
| @ -80,14 +80,14 @@ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|                 <!-- Description and restrictions --> |                 <!-- Description and restrictions --> | ||||||
|                 <div *ngIf="module.description || module.availabilityinfo" id="activity-{{module.id}}-collapsible" |                 <div *ngIf="module.description || (showAvailability && module.availabilityinfo)" id="activity-{{module.id}}-collapsible" | ||||||
|                     class="ion-text-wrap activity-description-availabilityinfo activity-extra" [collapsible-item]="64"> |                     class="ion-text-wrap activity-description-availabilityinfo activity-extra" [collapsible-item]="64"> | ||||||
|                     <core-format-text class="core-module-description" *ngIf="module.description" [text]="module.description" |                     <core-format-text class="core-module-description" *ngIf="module.description" [text]="module.description" | ||||||
|                         contextLevel="module" [contextInstanceId]="module.id" [courseId]="module.course"> |                         contextLevel="module" [contextInstanceId]="module.id" [courseId]="module.course"> | ||||||
|                     </core-format-text> |                     </core-format-text> | ||||||
| 
 | 
 | ||||||
|                     <!-- Availability info --> |                     <!-- Availability info --> | ||||||
|                     <div *ngIf="module.availabilityinfo" class="core-module-availabilityinfo"> |                     <div *ngIf="showAvailability && module.availabilityinfo" class="core-module-availabilityinfo"> | ||||||
|                         <ion-icon name="fas-lock" [attr.aria-label]="'core.restricted' | translate"></ion-icon> |                         <ion-icon name="fas-lock" [attr.aria-label]="'core.restricted' | translate"></ion-icon> | ||||||
|                         <core-format-text [text]="module.availabilityinfo" contextLevel="module" [contextInstanceId]="module.id" |                         <core-format-text [text]="module.availabilityinfo" contextLevel="module" [contextInstanceId]="module.id" | ||||||
|                             [courseId]="module.course"> |                             [courseId]="module.course"> | ||||||
| @ -95,7 +95,7 @@ | |||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div> | ||||||
| 
 | 
 | ||||||
|                 <div *ngIf="module.handlerData.extraBadge" class="ion-text-wrap activity-extrabadges activity-extra" |                 <div *ngIf="showExtra && module.handlerData.extraBadge" class="ion-text-wrap activity-extrabadges activity-extra" | ||||||
|                     [innerHTML]="module.handlerData.extraBadge"></div> |                     [innerHTML]="module.handlerData.extraBadge"></div> | ||||||
|             </ion-label> |             </ion-label> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -50,6 +50,11 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { | |||||||
|     @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.
 | ||||||
|     @Input() showLegacyCompletion?: boolean; // Whether to show module completion in the old format.
 |     @Input() showLegacyCompletion?: boolean; // Whether to show module completion in the old format.
 | ||||||
|  |     @Input() showCompletion = true; // Whether to show module completion.
 | ||||||
|  |     @Input() showAvailability = true; // Whether to show module availability.
 | ||||||
|  |     @Input() showExtra = true; // Whether to show extra badges.
 | ||||||
|  |     @Input() showDownloadStatus = true; // Whether to show download status.
 | ||||||
|  |     @Input() showIndentation = true; // Whether to show indentation
 | ||||||
|     @Input() isLastViewed = false; // Whether it's the last module viewed in a course.
 |     @Input() isLastViewed = false; // Whether it's the last module viewed in a course.
 | ||||||
|     @Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>(); // Notify when module completion changes.
 |     @Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>(); // Notify when module completion changes.
 | ||||||
|     @HostBinding('class.indented') indented = false; |     @HostBinding('class.indented') indented = false; | ||||||
| @ -70,14 +75,24 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { | |||||||
|      */ |      */ | ||||||
|     async ngOnInit(): Promise<void> { |     async ngOnInit(): Promise<void> { | ||||||
|         const site = CoreSites.getRequiredCurrentSite(); |         const site = CoreSites.getRequiredCurrentSite(); | ||||||
|         const enableIndentation = await CoreCourse.isCourseIndentationEnabled(site, this.module.course); |  | ||||||
| 
 | 
 | ||||||
|         this.indented = enableIndentation && this.module.indent > 0; |         if (this.showIndentation && this.module.indent > 0) { | ||||||
|  |             this.indented = await CoreCourse.isCourseIndentationEnabled(site, this.module.course); | ||||||
|  |         } else { | ||||||
|  |             this.indented = false; | ||||||
|  |         } | ||||||
|         this.modNameTranslated = CoreCourse.translateModuleName(this.module.modname, this.module.modplural); |         this.modNameTranslated = CoreCourse.translateModuleName(this.module.modname, this.module.modplural); | ||||||
|         this.showLegacyCompletion = this.showLegacyCompletion ?? |         if (this.showCompletion) { | ||||||
|             CoreConstants.CONFIG.uselegacycompletion ?? |             this.showLegacyCompletion = this.showLegacyCompletion ?? | ||||||
|             !site.isVersionGreaterEqualThan('3.11'); |                 CoreConstants.CONFIG.uselegacycompletion ?? | ||||||
|         this.checkShowCompletion(); |                 !site.isVersionGreaterEqualThan('3.11'); | ||||||
|  |             this.checkShowCompletion(); | ||||||
|  |         } else { | ||||||
|  |             this.showLegacyCompletion = false; | ||||||
|  |             this.showCompletionConditions = false; | ||||||
|  |             this.showManualCompletion = false; | ||||||
|  |             this.hasCompletion = false; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (!this.module.handlerData) { |         if (!this.module.handlerData) { | ||||||
|             return; |             return; | ||||||
| @ -86,7 +101,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { | |||||||
|         this.module.handlerData.a11yTitle = this.module.handlerData.a11yTitle ?? this.module.handlerData.title; |         this.module.handlerData.a11yTitle = this.module.handlerData.a11yTitle ?? this.module.handlerData.title; | ||||||
|         this.moduleHasView = CoreCourse.moduleHasView(this.module); |         this.moduleHasView = CoreCourse.moduleHasView(this.module); | ||||||
| 
 | 
 | ||||||
|         if (this.module.handlerData?.showDownloadButton) { |         if (this.showDownloadStatus && this.module.handlerData.showDownloadButton) { | ||||||
|             const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(this.module, this.module.course); |             const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(this.module, this.module.course); | ||||||
|             this.updateModuleStatus(status); |             this.updateModuleStatus(status); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -298,7 +298,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy, CoreRefreshCon | |||||||
|             await this.loadData(true, true); |             await this.loadData(true, true); | ||||||
|         } finally { |         } finally { | ||||||
|             // Do not call doRefresh on the format component if the refresher is defined in the format component
 |             // Do not call doRefresh on the format component if the refresher is defined in the format component
 | ||||||
|             // to prevent an inifinite loop.
 |             // to prevent an infinite loop.
 | ||||||
|             if (this.displayRefresher && this.formatComponent) { |             if (this.displayRefresher && this.formatComponent) { | ||||||
|                 await CoreUtils.ignoreErrors(this.formatComponent.doRefresh(refresher)); |                 await CoreUtils.ignoreErrors(this.formatComponent.doRefresh(refresher)); | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -17,12 +17,24 @@ | |||||||
|         </core-empty-box> |         </core-empty-box> | ||||||
| 
 | 
 | ||||||
|         <ion-list class="core-course-module-list-wrapper"> |         <ion-list class="core-course-module-list-wrapper"> | ||||||
|             <ng-container *ngFor="let section of sections"> |             <ng-container *ngFor="let section of sections; index as i"> | ||||||
|                 <ng-container *ngFor="let module of section.modules"> |                 <ng-container *ngIf="i <= lastShownSectionIndex"> | ||||||
|                     <core-course-module *ngIf="module.visibleoncoursepage !== 0" [module]="module" [section]="section"> |                     <ion-item-divider class="course-section ion-text-wrap" *ngIf="section.name"> | ||||||
|                     </core-course-module> |                         <ion-label> | ||||||
|  |                             <h2> | ||||||
|  |                                 <core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="courseId"> | ||||||
|  |                                 </core-format-text> | ||||||
|  |                             </h2> | ||||||
|  |                         </ion-label> | ||||||
|  |                     </ion-item-divider> | ||||||
|  |                     <ng-container *ngFor="let module of section.modules"> | ||||||
|  |                         <core-course-module [module]="module" [section]="section" [showActivityDates]="false" [showAvailability]="false" | ||||||
|  |                             [showExtra]="false" [showDownloadStatus]="false" [showCompletion]="false" [showIndentation]="false"> | ||||||
|  |                         </core-course-module> | ||||||
|  |                     </ng-container> | ||||||
|                 </ng-container> |                 </ng-container> | ||||||
|             </ng-container> |             </ng-container> | ||||||
|         </ion-list> |         </ion-list> | ||||||
|  |         <core-infinite-loading [enabled]="canLoadMore" (action)="showMoreActivities($event)"></core-infinite-loading> | ||||||
|     </core-loading> |     </core-loading> | ||||||
| </ion-content> | </ion-content> | ||||||
|  | |||||||
| @ -34,10 +34,14 @@ import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; | |||||||
| }) | }) | ||||||
| export class CoreCourseListModTypePage implements OnInit { | export class CoreCourseListModTypePage implements OnInit { | ||||||
| 
 | 
 | ||||||
|  |     private static readonly PAGE_LENGTH = 10; // How many activities should load each time showMoreActivities is called.
 | ||||||
|  | 
 | ||||||
|     sections: CoreCourseSection[] = []; |     sections: CoreCourseSection[] = []; | ||||||
|     title = ''; |     title = ''; | ||||||
|     loaded = false; |     loaded = false; | ||||||
|     courseId?: number; |     courseId = 0; | ||||||
|  |     canLoadMore = false; | ||||||
|  |     lastShownSectionIndex = -1; | ||||||
| 
 | 
 | ||||||
|     protected modName?: string; |     protected modName?: string; | ||||||
|     protected archetypes: Record<string, number> = {}; // To speed up the check of modules.
 |     protected archetypes: Record<string, number> = {}; // To speed up the check of modules.
 | ||||||
| @ -64,9 +68,16 @@ export class CoreCourseListModTypePage implements OnInit { | |||||||
|      * @inheritdoc |      * @inheritdoc | ||||||
|      */ |      */ | ||||||
|     async ngOnInit(): Promise<void> { |     async ngOnInit(): Promise<void> { | ||||||
|         this.title = CoreNavigator.getRouteParam('title') || ''; |         try { | ||||||
|         this.courseId = CoreNavigator.getRouteNumberParam('courseId'); |             this.title = CoreNavigator.getRouteParam('title') || ''; | ||||||
|         this.modName = CoreNavigator.getRouteParam('modName'); |             this.courseId = CoreNavigator.getRequiredRouteParam('courseId'); | ||||||
|  |             this.modName = CoreNavigator.getRequiredRouteParam('modName'); | ||||||
|  |         } catch (error) { | ||||||
|  |             CoreDomUtils.showErrorModal(error); | ||||||
|  |             CoreNavigator.back(); | ||||||
|  | 
 | ||||||
|  |             return; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             await this.fetchData(); |             await this.fetchData(); | ||||||
| @ -77,8 +88,6 @@ export class CoreCourseListModTypePage implements OnInit { | |||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Fetches the data. |      * Fetches the data. | ||||||
|      * |  | ||||||
|      * @returns Resolved when done. |  | ||||||
|      */ |      */ | ||||||
|     protected async fetchData(): Promise<void> { |     protected async fetchData(): Promise<void> { | ||||||
|         if (!this.courseId) { |         if (!this.courseId) { | ||||||
| @ -90,12 +99,14 @@ export class CoreCourseListModTypePage implements OnInit { | |||||||
|             let sections = await CoreCourse.getSections(this.courseId, false, true); |             let sections = await CoreCourse.getSections(this.courseId, false, true); | ||||||
| 
 | 
 | ||||||
|             sections = sections.filter((section) => { |             sections = sections.filter((section) => { | ||||||
|                 if (!section.modules) { |                 if (!section.modules.length || section.hiddenbynumsections) { | ||||||
|                     return false; |                     return false; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 section.modules = section.modules.filter((mod) => { |                 section.modules = section.modules.filter((mod) => { | ||||||
|                     if (!CoreCourseHelper.canUserViewModule(mod, section) || !CoreCourse.moduleHasView(mod)) { |                     if (!CoreCourseHelper.canUserViewModule(mod, section) || | ||||||
|  |                         !CoreCourse.moduleHasView(mod) || | ||||||
|  |                         mod.visibleoncoursepage === 0) { | ||||||
|                         // Ignore this module.
 |                         // Ignore this module.
 | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
| @ -110,11 +121,11 @@ export class CoreCourseListModTypePage implements OnInit { | |||||||
|                             ); |                             ); | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                         if (this.archetypes[mod.modname] == CoreConstants.MOD_ARCHETYPE_RESOURCE) { |                         if (this.archetypes[mod.modname] === CoreConstants.MOD_ARCHETYPE_RESOURCE) { | ||||||
|                             return true; |                             return true; | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                     } else if (mod.modname == this.modName) { |                     } else if (mod.modname === this.modName) { | ||||||
|                         return true; |                         return true; | ||||||
|                     } |                     } | ||||||
|                 }); |                 }); | ||||||
| @ -125,19 +136,39 @@ export class CoreCourseListModTypePage implements OnInit { | |||||||
|             const result = await CoreCourseHelper.addHandlerDataForModules(sections, this.courseId); |             const result = await CoreCourseHelper.addHandlerDataForModules(sections, this.courseId); | ||||||
| 
 | 
 | ||||||
|             this.sections = result.sections; |             this.sections = result.sections; | ||||||
|  | 
 | ||||||
|  |             this.lastShownSectionIndex = -1; | ||||||
|  |             this.showMoreActivities(); | ||||||
|         } catch (error) { |         } catch (error) { | ||||||
|             CoreDomUtils.showErrorModalDefault(error, 'Error getting data'); |             CoreDomUtils.showErrorModalDefault(error, 'Error getting data'); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Show more activities. | ||||||
|  |      * | ||||||
|  |      * @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading. | ||||||
|  |      */ | ||||||
|  |     showMoreActivities(infiniteComplete?: () => void): void { | ||||||
|  |         let modulesLoaded = 0; | ||||||
|  |         while (this.lastShownSectionIndex < this.sections.length - 1 && modulesLoaded < CoreCourseListModTypePage.PAGE_LENGTH) { | ||||||
|  |             this.lastShownSectionIndex++; | ||||||
|  | 
 | ||||||
|  |             modulesLoaded += this.sections[this.lastShownSectionIndex].modules.length; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         this.canLoadMore = this.lastShownSectionIndex < this.sections.length - 1; | ||||||
|  | 
 | ||||||
|  |         infiniteComplete?.(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Refresh the data. |      * Refresh the data. | ||||||
|      * |      * | ||||||
|      * @param refresher Refresher. |      * @param refresher Refresher. | ||||||
|      * @returns Promise resolved when done. |  | ||||||
|      */ |      */ | ||||||
|     async refreshData(refresher: IonRefresher): Promise<void> { |     async refreshData(refresher: IonRefresher): Promise<void> { | ||||||
|         await CoreUtils.ignoreErrors(CoreCourse.invalidateSections(this.courseId || 0)); |         await CoreUtils.ignoreErrors(CoreCourse.invalidateSections(this.courseId)); | ||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             await this.fetchData(); |             await this.fetchData(); | ||||||
|  | |||||||
| @ -40,7 +40,7 @@ | |||||||
|                     {{ 'core.course.hiddenfromstudents' | translate }} |                     {{ 'core.course.hiddenfromstudents' | translate }} | ||||||
|                 </ion-badge> |                 </ion-badge> | ||||||
|                 <ion-badge color="secondary" *ngIf="module.visible !== 0 && module.isStealth" class="ion-text-wrap"> |                 <ion-badge color="secondary" *ngIf="module.visible !== 0 && module.isStealth" class="ion-text-wrap"> | ||||||
|                     <ion-icon name="fas-low-vision" aria-hidden="true"></ion-icon> |                     <ion-icon name="fas-eye-low-vision" aria-hidden="true"></ion-icon> | ||||||
|                     {{ 'core.course.hiddenoncoursepage' | translate }} |                     {{ 'core.course.hiddenoncoursepage' | translate }} | ||||||
|                 </ion-badge> |                 </ion-badge> | ||||||
|             </div> |             </div> | ||||||
|  | |||||||
| @ -85,20 +85,20 @@ Feature: Test basic usage of one course in app | |||||||
|     And I press "OK" in the app |     And I press "OK" in the app | ||||||
|     And I wait loading to finish in the app |     And I wait loading to finish in the app | ||||||
|     Then the header should be "Course 1" in the app |     Then the header should be "Course 1" in the app | ||||||
|  |     And I should find "Test forum name" in the app | ||||||
|  |     And I should find "Test wiki name" in the app | ||||||
|     And I should find "Choice course 1" in the app |     And I should find "Choice course 1" in the app | ||||||
|     And I should find "assignment" in the app |     And I should find "assignment" in the app | ||||||
|     And I should find "Test forum name" in the app |  | ||||||
|     And I should find "Test chat name" in the app |  | ||||||
|     And I should find "Web links" in the app |  | ||||||
|     And I should find "Test external name" in the app |     And I should find "Test external name" in the app | ||||||
|     And I should find "Test feedback name" in the app |  | ||||||
|     And I should find "Test glossary" in the app |  | ||||||
|     And I should find "Quiz 1" in the app |  | ||||||
|     And I should find "Test survey name" in the app |     And I should find "Test survey name" in the app | ||||||
|     And I should find "Test wiki name" in the app |     And I should find "Test chat name" in the app | ||||||
|     And I should find "Test lesson name" in the app |     And I should find "Quiz 1" in the app | ||||||
|     And I should find "Test scorm name" in the app |     And I should find "Test scorm name" in the app | ||||||
|  |     And I should find "Test feedback name" in the app | ||||||
|  |     And I should find "Test lesson name" in the app | ||||||
|     And I should find "Test workshop name" in the app |     And I should find "Test workshop name" in the app | ||||||
|  |     And I should not find "Web links" in the app | ||||||
|  |     And I should not find "Test glossary" in the app | ||||||
| 
 | 
 | ||||||
|   Scenario: Guest access |   Scenario: Guest access | ||||||
|     Given I entered the course "Course 1" as "teacher1" in the app |     Given I entered the course "Course 1" as "teacher1" in the app | ||||||
| @ -122,16 +122,16 @@ Feature: Test basic usage of one course in app | |||||||
| 
 | 
 | ||||||
|     When I press "View course" "ion-button" in the app |     When I press "View course" "ion-button" in the app | ||||||
|     Then the header should be "Course 1" in the app |     Then the header should be "Course 1" in the app | ||||||
|  |     And I should find "Test forum name" in the app | ||||||
|  |     And I should find "Test wiki name" in the app | ||||||
|     And I should find "Choice course 1" in the app |     And I should find "Choice course 1" in the app | ||||||
|     And I should find "assignment" in the app |     And I should find "assignment" in the app | ||||||
|     And I should find "Test forum name" in the app |  | ||||||
|     And I should find "Test chat name" in the app |  | ||||||
|     And I should find "Web links" in the app |  | ||||||
|     And I should find "Test feedback name" in the app |  | ||||||
|     And I should find "Test glossary" in the app |  | ||||||
|     And I should find "Quiz 1" in the app |  | ||||||
|     And I should find "Test survey name" in the app |     And I should find "Test survey name" in the app | ||||||
|     And I should find "Test wiki name" in the app |     And I should find "Test chat name" in the app | ||||||
|     And I should find "Test lesson name" in the app |     And I should find "Quiz 1" in the app | ||||||
|     And I should find "Test scorm name" in the app |     And I should find "Test scorm name" in the app | ||||||
|  |     And I should find "Test feedback name" in the app | ||||||
|  |     And I should find "Test lesson name" in the app | ||||||
|     And I should find "Test workshop name" in the app |     And I should find "Test workshop name" in the app | ||||||
|  |     And I should not find "Web links" in the app | ||||||
|  |     And I should not find "Test glossary" in the app | ||||||
|  | |||||||
| @ -83,25 +83,33 @@ Feature: Test basic usage of one course in app | |||||||
|   Scenario: View course contents |   Scenario: View course contents | ||||||
|     When I entered the course "Course 1" as "student1" in the app |     When I entered the course "Course 1" as "student1" in the app | ||||||
|     Then the header should be "Course 1" in the app |     Then the header should be "Course 1" in the app | ||||||
|  |     And I should find "Test forum name" in the app | ||||||
|  |     And I should find "Test wiki name" in the app | ||||||
|     And I should find "Choice course 1" in the app |     And I should find "Choice course 1" in the app | ||||||
|     And I should find "assignment" in the app |     And I should find "assignment" in the app | ||||||
|     And I should find "Test forum name" in the app |  | ||||||
|     And I should find "Test chat name" in the app |  | ||||||
|     And I should find "Web links" in the app |  | ||||||
|     And I should find "Test external name" in the app |     And I should find "Test external name" in the app | ||||||
|     And I should find "Test feedback name" in the app |  | ||||||
|     And I should find "Test glossary" in the app |  | ||||||
|     And I should find "Quiz 1" in the app |  | ||||||
|     And I should find "Test survey name" in the app |     And I should find "Test survey name" in the app | ||||||
|     And I should find "Test wiki name" in the app |     And I should find "Test chat name" in the app | ||||||
|     And I should find "Test lesson name" in the app |     And I should find "Quiz 1" in the app | ||||||
|     And I should find "Test scorm name" in the app |     And I should find "Test scorm name" in the app | ||||||
|  |     And I should find "Test feedback name" in the app | ||||||
|  |     And I should find "Test lesson name" in the app | ||||||
|     And I should find "Test workshop name" in the app |     And I should find "Test workshop name" in the app | ||||||
|  |     And I should not find "Web links" in the app | ||||||
|  |     And I should not find "Test glossary" in the app | ||||||
| 
 | 
 | ||||||
|     When I set "page-core-course-index .core-course-thumb" styles to "background" "lightblue" |     When I set "page-core-course-index .core-course-thumb" styles to "background" "lightblue" | ||||||
|     And I set "page-core-course-index .core-course-thumb img" styles to "display" "none" |     And I set "page-core-course-index .core-course-thumb img" styles to "display" "none" | ||||||
|     Then the UI should match the snapshot |     Then the UI should match the snapshot | ||||||
| 
 | 
 | ||||||
|  |     # Test infinite scroll on course | ||||||
|  |     When I scroll to "Test workshop name" in the app | ||||||
|  |     Then I should find "Web links" in the app | ||||||
|  |     And I should find "Test glossary" in the app | ||||||
|  | 
 | ||||||
|  |     # Test Collapsible header | ||||||
|  |     And the UI should match the snapshot | ||||||
|  | 
 | ||||||
|     When I press "Choice course 1" in the app |     When I press "Choice course 1" in the app | ||||||
|     Then the header should be "Choice course 1" in the app |     Then the header should be "Choice course 1" in the app | ||||||
| 
 | 
 | ||||||
| @ -161,20 +169,20 @@ Feature: Test basic usage of one course in app | |||||||
|   Scenario: View section contents |   Scenario: View section contents | ||||||
|     When I entered the course "Course 1" as "student1" in the app |     When I entered the course "Course 1" as "student1" in the app | ||||||
|     Then the header should be "Course 1" in the app |     Then the header should be "Course 1" in the app | ||||||
|  |     And I should find "Test forum name" in the app | ||||||
|  |     And I should find "Test wiki name" in the app | ||||||
|     And I should find "Choice course 1" in the app |     And I should find "Choice course 1" in the app | ||||||
|     And I should find "assignment" in the app |     And I should find "assignment" in the app | ||||||
|     And I should find "Test forum name" in the app |  | ||||||
|     And I should find "Test chat name" in the app |  | ||||||
|     And I should find "Web links" in the app |  | ||||||
|     And I should find "Test external name" in the app |     And I should find "Test external name" in the app | ||||||
|     And I should find "Test feedback name" in the app |  | ||||||
|     And I should find "Test glossary" in the app |  | ||||||
|     And I should find "Quiz 1" in the app |  | ||||||
|     And I should find "Test survey name" in the app |     And I should find "Test survey name" in the app | ||||||
|     And I should find "Test wiki name" in the app |     And I should find "Test chat name" in the app | ||||||
|     And I should find "Test lesson name" in the app |     And I should find "Quiz 1" in the app | ||||||
|     And I should find "Test scorm name" in the app |     And I should find "Test scorm name" in the app | ||||||
|  |     And I should find "Test feedback name" in the app | ||||||
|  |     And I should find "Test lesson name" in the app | ||||||
|     And I should find "Test workshop name" in the app |     And I should find "Test workshop name" in the app | ||||||
|  |     And I should not find "Web links" in the app | ||||||
|  |     And I should not find "Test glossary" in the app | ||||||
| 
 | 
 | ||||||
|     When I press "Course index" in the app |     When I press "Course index" in the app | ||||||
|     And I press "General" in the app |     And I press "General" in the app | ||||||
| @ -337,20 +345,20 @@ Feature: Test basic usage of one course in app | |||||||
|   Scenario: Navigation between sections using the bottom arrows |   Scenario: Navigation between sections using the bottom arrows | ||||||
|     When I entered the course "Course 1" as "student1" in the app |     When I entered the course "Course 1" as "student1" in the app | ||||||
|     Then the header should be "Course 1" in the app |     Then the header should be "Course 1" in the app | ||||||
|  |    And I should find "Test forum name" in the app | ||||||
|  |     And I should find "Test wiki name" in the app | ||||||
|     And I should find "Choice course 1" in the app |     And I should find "Choice course 1" in the app | ||||||
|     And I should find "assignment" in the app |     And I should find "assignment" in the app | ||||||
|     And I should find "Test forum name" in the app |  | ||||||
|     And I should find "Test chat name" in the app |  | ||||||
|     And I should find "Web links" in the app |  | ||||||
|     And I should find "Test external name" in the app |     And I should find "Test external name" in the app | ||||||
|     And I should find "Test feedback name" in the app |  | ||||||
|     And I should find "Test glossary" in the app |  | ||||||
|     And I should find "Quiz 1" in the app |  | ||||||
|     And I should find "Test survey name" in the app |     And I should find "Test survey name" in the app | ||||||
|     And I should find "Test wiki name" in the app |     And I should find "Test chat name" in the app | ||||||
|     And I should find "Test lesson name" in the app |     And I should find "Quiz 1" in the app | ||||||
|     And I should find "Test scorm name" in the app |     And I should find "Test scorm name" in the app | ||||||
|  |     And I should find "Test feedback name" in the app | ||||||
|  |     And I should find "Test lesson name" in the app | ||||||
|     And I should find "Test workshop name" in the app |     And I should find "Test workshop name" in the app | ||||||
|  |     And I should not find "Web links" in the app | ||||||
|  |     And I should not find "Test glossary" in the app | ||||||
| 
 | 
 | ||||||
|     When I press "Course index" in the app |     When I press "Course index" in the app | ||||||
|     And I press "General" in the app |     And I press "General" in the app | ||||||
| @ -425,20 +433,20 @@ Feature: Test basic usage of one course in app | |||||||
|     And I press "OK" in the app |     And I press "OK" in the app | ||||||
|     And I wait loading to finish in the app |     And I wait loading to finish in the app | ||||||
|     Then the header should be "Course 1" in the app |     Then the header should be "Course 1" in the app | ||||||
|  |     And I should find "Test forum name" in the app | ||||||
|  |     And I should find "Test wiki name" in the app | ||||||
|     And I should find "Choice course 1" in the app |     And I should find "Choice course 1" in the app | ||||||
|     And I should find "assignment" in the app |     And I should find "assignment" in the app | ||||||
|     And I should find "Test forum name" in the app |  | ||||||
|     And I should find "Test chat name" in the app |  | ||||||
|     And I should find "Web links" in the app |  | ||||||
|     And I should find "Test external name" in the app |     And I should find "Test external name" in the app | ||||||
|     And I should find "Test feedback name" in the app |  | ||||||
|     And I should find "Test glossary" in the app |  | ||||||
|     And I should find "Quiz 1" in the app |  | ||||||
|     And I should find "Test survey name" in the app |     And I should find "Test survey name" in the app | ||||||
|     And I should find "Test wiki name" in the app |     And I should find "Test chat name" in the app | ||||||
|     And I should find "Test lesson name" in the app |     And I should find "Quiz 1" in the app | ||||||
|     And I should find "Test scorm name" in the app |     And I should find "Test scorm name" in the app | ||||||
|  |     And I should find "Test feedback name" in the app | ||||||
|  |     And I should find "Test lesson name" in the app | ||||||
|     And I should find "Test workshop name" in the app |     And I should find "Test workshop name" in the app | ||||||
|  |     And I should not find "Web links" in the app | ||||||
|  |     And I should not find "Test glossary" in the app | ||||||
| 
 | 
 | ||||||
|   Scenario: View blocks on drawer |   Scenario: View blocks on drawer | ||||||
|     Given the following "blocks" exist: |     Given the following "blocks" exist: | ||||||
| @ -447,20 +455,20 @@ Feature: Test basic usage of one course in app | |||||||
|       | activity_modules | Course       | C1        | course-view-*   | site-pre      |                                                                                                              | |       | activity_modules | Course       | C1        | course-view-*   | site-pre      |                                                                                                              | | ||||||
|     And I entered the course "Course 1" as "student1" in the app |     And I entered the course "Course 1" as "student1" in the app | ||||||
|     Then the header should be "Course 1" in the app |     Then the header should be "Course 1" in the app | ||||||
|  |     And I should find "Test forum name" in the app | ||||||
|  |     And I should find "Test wiki name" in the app | ||||||
|     And I should find "Choice course 1" in the app |     And I should find "Choice course 1" in the app | ||||||
|     And I should find "assignment" in the app |     And I should find "assignment" in the app | ||||||
|     And I should find "Test forum name" in the app |  | ||||||
|     And I should find "Test chat name" in the app |  | ||||||
|     And I should find "Web links" in the app |  | ||||||
|     And I should find "Test external name" in the app |     And I should find "Test external name" in the app | ||||||
|     And I should find "Test feedback name" in the app |  | ||||||
|     And I should find "Test glossary" in the app |  | ||||||
|     And I should find "Quiz 1" in the app |  | ||||||
|     And I should find "Test survey name" in the app |     And I should find "Test survey name" in the app | ||||||
|     And I should find "Test wiki name" in the app |     And I should find "Test chat name" in the app | ||||||
|     And I should find "Test lesson name" in the app |     And I should find "Quiz 1" in the app | ||||||
|     And I should find "Test scorm name" in the app |     And I should find "Test scorm name" in the app | ||||||
|  |     And I should find "Test feedback name" in the app | ||||||
|  |     And I should find "Test lesson name" in the app | ||||||
|     And I should find "Test workshop name" in the app |     And I should find "Test workshop name" in the app | ||||||
|  |     And I should not find "Web links" in the app | ||||||
|  |     And I should not find "Test glossary" in the app | ||||||
|     Then I press "Open block drawer" in the app |     Then I press "Open block drawer" in the app | ||||||
|     And I should find "HTML title test" in the app |     And I should find "HTML title test" in the app | ||||||
|     And I should find "body test" in the app |     And I should find "body test" in the app | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB | 
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 38 KiB | 
| @ -1898,10 +1898,12 @@ ion-popover { | |||||||
|     &.md { |     &.md { | ||||||
|         margin-top: 2px; |         margin-top: 2px; | ||||||
|         margin-bottom: 2px; |         margin-bottom: 2px; | ||||||
|     } | 
 | ||||||
|     // Never show backdrop on popovers |         // Never show backdrop on popovers on Android | ||||||
|     ion-backdrop { |         // @todo Apply box shadow on ios and make it transparent too. The main problem is the box arrow. | ||||||
|         background: transparent; |         ion-backdrop { | ||||||
|  |             background: transparent; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user