MOBILE-3833 course: Display loading in course index
This improves performance in old deviced or big coursesmain
parent
8c41be3520
commit
d4695dd845
|
@ -11,74 +11,79 @@
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-list id="core-course-section-selector" role="listbox" aria-labelledby="core-course-section-selector-label">
|
<core-loading [hideUntil]="loaded">
|
||||||
<ng-container *ngFor="let section of sectionsToRender">
|
<ion-list *ngIf="loaded" id="core-course-section-selector" role="listbox" aria-labelledby="core-course-section-selector-label">
|
||||||
<ion-item *ngIf="allSectionId == section.id" class="divider core-course-index-all"
|
<ng-container *ngFor="let section of sectionsToRender">
|
||||||
(click)="selectSectionOrModule($event, section.id)" button [class.item-current]="selectedId === section.id" detail="false">
|
<ion-item *ngIf="allSectionId == section.id" class="divider core-course-index-all"
|
||||||
<ion-label>
|
(click)="selectSectionOrModule($event, section.id)" button [class.item-current]="selectedId === section.id"
|
||||||
<h2>
|
detail="false">
|
||||||
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id">
|
|
||||||
</core-format-text>
|
|
||||||
</h2>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
<ng-container *ngIf="allSectionId != section.id">
|
|
||||||
<ion-item class="divider section" (click)="selectSectionOrModule($event, section.id)" button
|
|
||||||
[class.item-current]="selectedId === section.id" [class.item-dimmed]="!section.visible"
|
|
||||||
[class.item-hightlighted]="section.highlighted" detail="false" sticky="true">
|
|
||||||
<ion-icon *ngIf="section.hasVisibleModules" name="fas-chevron-right" flip-rtl slot="start"
|
|
||||||
class="expandable-status-icon" (click)="toggleExpand($event, section)"
|
|
||||||
[attr.aria-label]="(section.expanded ? 'core.collapse' : 'core.expand') | translate"
|
|
||||||
[attr.aria-expanded]="section.expanded" [attr.aria-controls]="'core-course-index-section-' + section.id"
|
|
||||||
[class.expandable-status-icon-expanded]="section.expanded">
|
|
||||||
</ion-icon>
|
|
||||||
<ion-icon *ngIf="!section.hasVisibleModules" name="" slot="start" aria-hidden="true" class="expandable-status-icon">
|
|
||||||
</ion-icon>
|
|
||||||
<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">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</h2>
|
</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-badge *ngIf="section.highlighted && highlighted" slot="end">{{highlighted}}</ion-badge>
|
|
||||||
<ion-icon name="fas-lock" *ngIf="section.availabilityinfo" slot="end" class="restricted"
|
|
||||||
[attr.aria-label]="'core.restricted' | translate"></ion-icon>
|
|
||||||
<ion-icon name="fas-eye-slash" *ngIf="!section.visible && !section.uservisible" slot="end" class="restricted"
|
|
||||||
[attr.aria-label]="'core.notavailable' | translate"></ion-icon>
|
|
||||||
<ion-icon name="fas-eye-slash" *ngIf="!section.visible && section.uservisible" slot="end" class="restricted"
|
|
||||||
[attr.aria-label]="'core.course.hiddenfromstudents' | translate"></ion-icon>
|
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<div id="core-course-index-section-{{section.id}}">
|
<ng-container *ngIf="allSectionId != section.id">
|
||||||
<ng-container *ngIf="section.expanded">
|
<ion-item class="divider section" (click)="selectSectionOrModule($event, section.id)" button
|
||||||
<ng-container *ngFor="let module of section.modules">
|
[class.item-current]="selectedId === section.id" [class.item-dimmed]="!section.visible"
|
||||||
<ion-item class="module" [class.item-dimmed]="!module.visible" [class.item-hightlighted]="section.highlighted"
|
[class.item-hightlighted]="section.highlighted" detail="false" sticky="true">
|
||||||
(click)="selectSectionOrModule($event, section.id, module.id)" button>
|
<ion-icon *ngIf="section.hasVisibleModules" name="fas-chevron-right" flip-rtl slot="start"
|
||||||
<ion-icon class="completioninfo completion_none" name="" *ngIf="module.completionStatus === undefined"
|
class="expandable-status-icon" (click)="toggleExpand($event, section)"
|
||||||
slot="start" aria-hidden="true"></ion-icon>
|
[attr.aria-label]="(section.expanded ? 'core.collapse' : 'core.expand') | translate"
|
||||||
<ion-icon class="completioninfo completion_incomplete" name="far-circle"
|
[attr.aria-expanded]="section.expanded" [attr.aria-controls]="'core-course-index-section-' + section.id"
|
||||||
*ngIf="module.completionStatus === 0" slot="start" [attr.aria-label]="'core.course.todo' | translate">
|
[class.expandable-status-icon-expanded]="section.expanded">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
<ion-icon class="completioninfo completion_complete" name="fas-circle"
|
<ion-icon *ngIf="!section.hasVisibleModules" name="" slot="start" aria-hidden="true" class="expandable-status-icon">
|
||||||
*ngIf="module.completionStatus === 1 || module.completionStatus === 2" color="success" slot="start"
|
</ion-icon>
|
||||||
[attr.aria-label]="'core.course.done' | translate">
|
<ion-label>
|
||||||
</ion-icon>
|
<h2>
|
||||||
<ion-icon class="completioninfo completion_fail" name="fas-circle" *ngIf="module.completionStatus === 3"
|
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id">
|
||||||
color="danger" slot="start" [attr.aria-label]="'core.course.failed' | translate">
|
</core-format-text>
|
||||||
</ion-icon>
|
</h2>
|
||||||
<ion-label>
|
</ion-label>
|
||||||
<p class="item-heading">
|
<ion-badge *ngIf="section.highlighted && highlighted" slot="end">{{highlighted}}</ion-badge>
|
||||||
<core-format-text [text]="module.name" contextLevel="module" [contextInstanceId]="module.id"
|
<ion-icon name="fas-lock" *ngIf="section.availabilityinfo" slot="end" class="restricted"
|
||||||
[courseId]="module.course">
|
[attr.aria-label]="'core.restricted' | translate"></ion-icon>
|
||||||
</core-format-text>
|
<ion-icon name="fas-eye-slash" *ngIf="!section.visible && !section.uservisible" slot="end" class="restricted"
|
||||||
</p>
|
[attr.aria-label]="'core.notavailable' | translate"></ion-icon>
|
||||||
</ion-label>
|
<ion-icon name="fas-eye-slash" *ngIf="!section.visible && section.uservisible" slot="end" class="restricted"
|
||||||
<ion-icon name="fas-lock" *ngIf="!module.uservisible" slot="end" class="restricted"
|
[attr.aria-label]="'core.course.hiddenfromstudents' | translate"></ion-icon>
|
||||||
[attr.aria-label]="'core.restricted' | translate"></ion-icon>
|
</ion-item>
|
||||||
</ion-item>
|
<div id="core-course-index-section-{{section.id}}">
|
||||||
|
<ng-container *ngIf="section.expanded">
|
||||||
|
<ng-container *ngFor="let module of section.modules">
|
||||||
|
<ion-item class="module" [class.item-dimmed]="!module.visible"
|
||||||
|
[class.item-hightlighted]="section.highlighted"
|
||||||
|
(click)="selectSectionOrModule($event, section.id, module.id)" button>
|
||||||
|
<ion-icon class="completioninfo completion_none" name="" *ngIf="module.completionStatus === undefined"
|
||||||
|
slot="start" aria-hidden="true"></ion-icon>
|
||||||
|
<ion-icon class="completioninfo completion_incomplete" name="far-circle"
|
||||||
|
*ngIf="module.completionStatus === 0" slot="start"
|
||||||
|
[attr.aria-label]="'core.course.todo' | translate">
|
||||||
|
</ion-icon>
|
||||||
|
<ion-icon class="completioninfo completion_complete" name="fas-circle"
|
||||||
|
*ngIf="module.completionStatus === 1 || module.completionStatus === 2" color="success" slot="start"
|
||||||
|
[attr.aria-label]="'core.course.done' | translate">
|
||||||
|
</ion-icon>
|
||||||
|
<ion-icon class="completioninfo completion_fail" name="fas-circle" *ngIf="module.completionStatus === 3"
|
||||||
|
color="danger" slot="start" [attr.aria-label]="'core.course.failed' | translate">
|
||||||
|
</ion-icon>
|
||||||
|
<ion-label>
|
||||||
|
<p class="item-heading">
|
||||||
|
<core-format-text [text]="module.name" contextLevel="module" [contextInstanceId]="module.id"
|
||||||
|
[courseId]="module.course">
|
||||||
|
</core-format-text>
|
||||||
|
</p>
|
||||||
|
</ion-label>
|
||||||
|
<ion-icon name="fas-lock" *ngIf="!module.uservisible" slot="end" class="restricted"
|
||||||
|
[attr.aria-label]="'core.restricted' | translate"></ion-icon>
|
||||||
|
</ion-item>
|
||||||
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</div>
|
||||||
</div>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ion-list>
|
||||||
</ion-list>
|
</core-loading>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
import { CoreCourseHelper, CoreCourseSection } from '@features/course/services/course-helper';
|
import { CoreCourseHelper, CoreCourseSection } from '@features/course/services/course-helper';
|
||||||
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
||||||
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
||||||
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { ModalController } from '@singletons';
|
import { ModalController } from '@singletons';
|
||||||
import { CoreDom } from '@singletons/dom';
|
import { CoreDom } from '@singletons/dom';
|
||||||
|
|
||||||
|
@ -41,6 +42,7 @@ export class CoreCourseCourseIndexComponent implements OnInit {
|
||||||
allSectionId = CoreCourseProvider.ALL_SECTIONS_ID;
|
allSectionId = CoreCourseProvider.ALL_SECTIONS_ID;
|
||||||
highlighted?: string;
|
highlighted?: string;
|
||||||
sectionsToRender: CourseIndexSection[] = [];
|
sectionsToRender: CourseIndexSection[] = [];
|
||||||
|
loaded = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected elementRef: ElementRef,
|
protected elementRef: ElementRef,
|
||||||
|
@ -109,6 +111,13 @@ export class CoreCourseCourseIndexComponent implements OnInit {
|
||||||
|
|
||||||
this.highlighted = CoreCourseFormatDelegate.getSectionHightlightedName(this.course);
|
this.highlighted = CoreCourseFormatDelegate.getSectionHightlightedName(this.course);
|
||||||
|
|
||||||
|
// Wait a bit to render the data, otherwise the modal takes a while to appear in big courses or slow devices.
|
||||||
|
await CoreUtils.wait(400);
|
||||||
|
|
||||||
|
this.loaded = true;
|
||||||
|
|
||||||
|
await CoreUtils.nextTick();
|
||||||
|
|
||||||
CoreDom.scrollToElement(
|
CoreDom.scrollToElement(
|
||||||
this.elementRef.nativeElement,
|
this.elementRef.nativeElement,
|
||||||
'.item.item-current',
|
'.item.item-current',
|
||||||
|
|
Loading…
Reference in New Issue