MOBILE-3915 course: Implement new course index

main
Pau Ferrer Ocaña 2021-11-17 11:46:37 +01:00
parent 1dd5eba1de
commit 86365d260d
10 changed files with 95 additions and 149 deletions

View File

@ -20,7 +20,7 @@ import { CoreCourseFormatComponent } from './format/format';
import { CoreCourseModuleComponent } from './module/module';
import { CoreCourseModuleCompletionComponent } from './module-completion/module-completion';
import { CoreCourseModuleDescriptionComponent } from './module-description/module-description';
import { CoreCourseSectionSelectorComponent } from './section-selector/section-selector';
import { CoreCourseCourseIndexComponent } from './course-index/course-index';
import { CoreCourseTagAreaComponent } from './tag-area/tag-area';
import { CoreCourseUnsupportedModuleComponent } from './unsupported-module/unsupported-module';
import { CoreCourseModuleCompletionLegacyComponent } from './module-completion-legacy/module-completion-legacy';
@ -37,7 +37,7 @@ import { CoreCourseModuleNavigationComponent } from './module-navigation/module-
CoreCourseModuleDescriptionComponent,
CoreCourseModuleInfoComponent,
CoreCourseModuleManualCompletionComponent,
CoreCourseSectionSelectorComponent,
CoreCourseCourseIndexComponent,
CoreCourseTagAreaComponent,
CoreCourseUnsupportedModuleComponent,
CoreCourseModuleNavigationComponent,
@ -54,7 +54,7 @@ import { CoreCourseModuleNavigationComponent } from './module-navigation/module-
CoreCourseModuleDescriptionComponent,
CoreCourseModuleInfoComponent,
CoreCourseModuleManualCompletionComponent,
CoreCourseSectionSelectorComponent,
CoreCourseCourseIndexComponent,
CoreCourseTagAreaComponent,
CoreCourseUnsupportedModuleComponent,
CoreCourseModuleNavigationComponent,

View File

@ -1,7 +1,7 @@
<ion-header>
<ion-toolbar>
<ion-title>
<h2 id="core-course-section-selector-label">{{ 'core.course.sections' | translate }}</h2>
<h2 id="core-course-section-selector-label">{{ 'core.course.courseindex' | translate }}</h2>
</ion-title>
<ion-buttons slot="end">
<ion-button fill="clear" (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
@ -13,10 +13,10 @@
<ion-content>
<ion-list id="core-course-section-selector" role="listbox" aria-labelledby="core-course-section-selector-label">
<ng-container *ngFor="let section of sections">
<ion-item *ngIf="!section.hiddenbynumsections && section.id != stealthModulesSectionId" class="ion-text-wrap"
<ion-item-divider *ngIf="!section.hiddenbynumsections && section.id != stealthModulesSectionId" class="ion-text-wrap"
(click)="selectSection(section)" [attr.aria-current]="selected?.id == section.id ? 'page' : 'false'"
[class.item-dimmed]="section.visible === 0 || section.uservisible === false" detail="false"
[attr.aria-hidden]="section.uservisible === false" button>
[attr.aria-hidden]="section.uservisible === false" button sticky="true">
<ion-icon name="fas-folder" slot="start" aria-hidden="true"></ion-icon>
<ion-label>
@ -39,7 +39,24 @@
</core-format-text>
</ion-badge>
</ion-label>
</ion-item>
</ion-item-divider>
<ng-container *ngFor="let module of section.modules">
<ion-item *ngIf="module.visibleoncoursepage !== 0" class="ion-text-wrap">
<!-- TODO Add Aria, styles when disabled, etc. -->
<ion-icon name="" *ngIf="module.completionStatus === undefined" slot="start"></ion-icon>
<ion-icon name="far-circle" *ngIf="module.completionStatus === 0" slot="start"></ion-icon>
<ion-icon name="fas-circle" *ngIf="module.completionStatus === 1" color="success" slot="start"></ion-icon>
<ion-icon name="fas-circle" *ngIf="module.completionStatus === 2" color="success" slot="start"></ion-icon>
<ion-icon name="fas-circle" *ngIf="module.completionStatus === 3" color="danger" slot="start"></ion-icon>
<ion-label>
<p class="item-heading">
<core-format-text [text]="module.name" contextLevel="module" [contextInstanceId]="module.id"
[courseId]="module.courseid">
</core-format-text>
</p>
</ion-label>
</ion-item>
</ng-container>
</ng-container>
</ion-list>
</ion-content>

View File

@ -14,7 +14,7 @@
import { Component, Input, OnInit } from '@angular/core';
import { CoreCourseSection } from '@features/course/services/course-helper';
import { CoreCourseModuleData, CoreCourseSection, CoreCourseSectionWithStatus } from '@features/course/services/course-helper';
import {
CoreCourseModuleCompletionStatus,
CoreCourseModuleCompletionTracking,
@ -25,14 +25,14 @@ import { CoreUtils } from '@services/utils/utils';
import { ModalController } from '@singletons';
/**
* Component to display course section selector in a modal.
* Component to display course index modal.
*/
@Component({
selector: 'core-course-section-selector',
templateUrl: 'section-selector.html',
styleUrls: ['section-selector.scss'],
selector: 'core-course-course-index',
templateUrl: 'course-index.html',
styleUrls: ['course-index.scss'],
})
export class CoreCourseSectionSelectorComponent implements OnInit {
export class CoreCourseCourseIndexComponent implements OnInit {
@Input() sections?: SectionWithProgress[];
@Input() selected?: CoreCourseSection;
@ -41,7 +41,7 @@ export class CoreCourseSectionSelectorComponent implements OnInit {
stealthModulesSectionId = CoreCourseProvider.STEALTH_MODULES_SECTION_ID;
/**
* Component being initialized.
* @inheritdoc
*/
ngOnInit(): void {
@ -52,7 +52,7 @@ export class CoreCourseSectionSelectorComponent implements OnInit {
const formatOptions = CoreUtils.objectToKeyValueMap(this.course.courseformatoptions, 'name', 'value');
if (!formatOptions || formatOptions.coursedisplay != 1 || formatOptions.completionusertracked === false) {
if (!formatOptions || formatOptions.completionusertracked === false) {
return;
}
@ -60,11 +60,16 @@ export class CoreCourseSectionSelectorComponent implements OnInit {
let complete = 0;
let total = 0;
section.modules.forEach((module) => {
console.error(module);
if (!module.uservisible || module.completiondata === undefined ||
module.completiondata.tracking == CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_NONE) {
module.completionStatus = undefined;
return;
}
module.completionStatus = module.completiondata.state;
total++;
if (module.completiondata.state == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE ||
module.completiondata.state == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_PASS) {
@ -98,6 +103,9 @@ export class CoreCourseSectionSelectorComponent implements OnInit {
}
type SectionWithProgress = CoreCourseSection & {
type SectionWithProgress = Omit<CoreCourseSectionWithStatus, 'modules'> & {
progress?: number;
modules: (CoreCourseModuleData & {
completionStatus?: CoreCourseModuleCompletionStatus;
})[];
};

View File

@ -1,8 +1,8 @@
<!-- Buttons to add to the header. *ngIf is needed, otherwise the component is executed too soon and doesn't find the header. -->
<core-navbar-buttons slot="end" *ngIf="loaded">
<core-context-menu>
<core-context-menu-item [hidden]="!displaySectionSelector || !sections || !sections.length" [priority]="500"
[content]="'core.course.sections' | translate" (action)="showSectionSelector()" iconAction="menu">
<core-context-menu-item [hidden]="!displayCourseIndex || !sections || !sections.length" [priority]="500"
[content]="'core.course.courseindex' | translate" (action)="openCourseIndex()" iconAction="menu">
</core-context-menu-item>
</core-context-menu>
</core-navbar-buttons>
@ -32,46 +32,6 @@
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button>
</ion-item>
<ion-item *ngIf="selectedSection && selectedSection.id != allSectionsId" class="ion-text-wrap">
<ion-icon name="fas-folder" aria-label="hidden" slot="start"></ion-icon>
<ion-label>
<p class="item-heading">
<core-format-text *ngIf="selectedSection" [text]="selectedSection.name" contextLevel="course"
[contextInstanceId]="course.id" [clean]="true" [singleLine]="true">
</core-format-text>
</p>
<ion-badge color="info" class="ion-text-wrap"
*ngIf="selectedSection.visible === 0 && selectedSection.uservisible !== false">
{{ 'core.course.hiddenfromstudents' | translate }}
</ion-badge>
<ion-badge color="info" class="ion-text-wrap"
*ngIf="selectedSection.visible === 0 && selectedSection.uservisible === false">
{{ 'core.notavailable' | translate }}
</ion-badge>
<ion-badge color="info" class="ion-text-wrap" *ngIf="selectedSection.availabilityinfo">
<core-format-text [text]="selectedSection.availabilityinfo" contextLevel="course" [contextInstanceId]="course.id">
</core-format-text>
</ion-badge>
</ion-label>
</ion-item>
</core-dynamic-component>
<!-- Section selector. -->
<core-dynamic-component [component]="sectionSelectorComponent" [data]="data">
<div *ngIf="displaySectionSelector && sections && hasSeveralSections"
class="ion-text-wrap ion-justify-content-between ion-align-items-center core-button-selector-row">
<core-combobox [modalOptions]="sectionSelectorModalOptions" interface="modal" listboxId="core-course-section-button"
icon="fas-folder" [label]="'core.course.section' | translate"
[selection]="selectedSection ? selectedSection.name : 'core.course.sections' | translate"
(onChange)="sectionChanged($event)">
<span slot="text">
<core-format-text *ngIf="selectedSection" [text]="selectedSection.name" contextLevel="course"
[contextInstanceId]="course.id" [clean]="true" [singleLine]="true">
</core-format-text>
<ng-container *ngIf="!selectedSection">{{ 'core.course.sections' | translate }}</ng-container>
</span>
</core-combobox>
</div>
</core-dynamic-component>
<!-- Single section. -->
@ -98,7 +58,7 @@
</div>
<ion-buttons class="ion-padding core-course-section-nav-buttons safe-area-padding-horizontal"
*ngIf="displaySectionSelector && sections?.length">
*ngIf="displayCourseIndex && sections?.length">
<ion-button *ngIf="previousSection" (click)="sectionChanged(previousSection)" fill="outline" color="primary"
[attr.aria-label]="('core.previous' | translate) + ': ' + previousSection.name">
<ion-icon name="fas-chevron-left" slot="icon-only" aria-hidden="true"></ion-icon>
@ -115,17 +75,25 @@
<core-block-side-blocks-button *ngIf="course && displayBlocks && hasBlocks" [courseId]="course.id">
</core-block-side-blocks-button>
</core-loading>
</core-dynamic-component>
<!-- Course Index button. -->
<ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="displayCourseIndex">
<ion-fab-button (click)="openCourseIndex()" [attr.aria-label]="'core.course.courseindex' | translate">
<ion-icon name="fas-list-ul" aria-hidden="true"></ion-icon>
<span class="sr-only">{{'core.course.courseindex' | translate }}</span>
</ion-fab-button>
</ion-fab>
<!-- Template to render a section. -->
<ng-template #sectionTemplate let-section="section">
<section *ngIf="!section.hiddenbynumsections && section.id != allSectionsId && section.id != stealthModulesSectionId">
<!-- Title is only displayed when viewing all sections. -->
<ion-item-divider *ngIf="selectedSection?.id == allSectionsId && section.name" class="ion-text-wrap" color="light"
[class.item-dimmed]="section.visible === 0 || section.uservisible === false">
<ion-item-divider class="ion-text-wrap" color="light" [class.item-dimmed]="section.visible === 0 || section.uservisible === false">
<ion-icon name="fas-folder" aria-label="hidden" slot="start"></ion-icon>
<ion-label>
<h2>
<h2 *ngIf="section.name">
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course.id">
</core-format-text>
</h2>

View File

@ -26,7 +26,6 @@ import {
Type,
ElementRef,
} from '@angular/core';
import { ModalOptions } from '@ionic/core';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-component';
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
@ -45,7 +44,7 @@ import { CoreCourseFormatDelegate } from '@features/course/services/format-deleg
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { IonContent, IonRefresher } from '@ionic/angular';
import { CoreUtils } from '@services/utils/utils';
import { CoreCourseSectionSelectorComponent } from '../section-selector/section-selector';
import { CoreCourseCourseIndexComponent } from '../course-index/course-index';
import { CoreBlockHelper } from '@features/block/services/block-helper';
import { CoreNavigator } from '@services/navigator';
@ -80,7 +79,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
// All the possible component classes.
courseFormatComponent?: Type<unknown>;
courseSummaryComponent?: Type<unknown>;
sectionSelectorComponent?: Type<unknown>;
singleSectionComponent?: Type<unknown>;
allSectionsComponent?: Type<unknown>;
@ -88,7 +86,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
showSectionId = 0;
data: Record<string, unknown> = {}; // Data to pass to the components.
displaySectionSelector = false;
displayCourseIndex = false;
displayBlocks = false;
hasBlocks = false;
selectedSection?: CoreCourseSection;
@ -97,17 +95,11 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
allSectionsId: number = CoreCourseProvider.ALL_SECTIONS_ID;
stealthModulesSectionId: number = CoreCourseProvider.STEALTH_MODULES_SECTION_ID;
loaded = false;
hasSeveralSections?: boolean;
imageThumb?: string;
progress?: number;
sectionSelectorModalOptions: ModalOptions = {
component: CoreCourseSectionSelectorComponent,
componentProps: {},
};
protected selectTabObserver?: CoreEventObserver;
protected lastCourseFormat?: string;
protected sectionSelectorExpanded = false;
constructor(
protected content: IonContent,
@ -154,14 +146,12 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
*/
async ngOnChanges(changes: { [name: string]: SimpleChange }): Promise<void> {
this.setInputData();
this.sectionSelectorModalOptions.componentProps!.course = this.course;
this.sectionSelectorModalOptions.componentProps!.sections = this.sections;
if (changes.course && this.course) {
// Course has changed, try to get the components.
this.getComponents();
this.displaySectionSelector = CoreCourseFormatDelegate.displaySectionSelector(this.course);
this.displayCourseIndex = CoreCourseFormatDelegate.displaySectionSelector(this.course);
this.displayBlocks = CoreCourseFormatDelegate.displayBlocks(this.course);
this.hasBlocks = await CoreBlockHelper.hasCourseBlocks(this.course.id);
@ -174,7 +164,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
}
if (changes.sections && this.sections) {
this.sectionSelectorModalOptions.componentProps!.sections = this.sections;
this.treatSections(this.sections);
}
}
@ -205,7 +194,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
await Promise.all([
this.loadCourseFormatComponent(),
this.loadCourseSummaryComponent(),
this.loadSectionSelectorComponent(),
this.loadSingleSectionComponent(),
this.loadAllSectionsComponent(),
]);
@ -229,15 +217,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
this.courseSummaryComponent = await CoreCourseFormatDelegate.getCourseSummaryComponent(this.course);
}
/**
* Load section selector component.
*
* @return Promise resolved when done.
*/
protected async loadSectionSelectorComponent(): Promise<void> {
this.sectionSelectorComponent = await CoreCourseFormatDelegate.getSectionSelectorComponent(this.course);
}
/**
* Load single section component.
*
@ -264,7 +243,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
*/
protected async treatSections(sections: CoreCourseSection[]): Promise<void> {
const hasAllSections = sections[0].id == CoreCourseProvider.ALL_SECTIONS_ID;
this.hasSeveralSections = sections.length > 2 || (sections.length == 2 && !hasAllSections);
const hasSeveralSections = sections.length > 2 || (sections.length == 2 && !hasAllSections);
if (this.selectedSection) {
// We have a selected section, but the list has changed. Search the section in the list.
@ -281,7 +260,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
}
// There is no selected section yet, calculate which one to load.
if (!this.hasSeveralSections) {
if (!hasSeveralSections) {
// Always load "All sections" to display the section title. If it isn't there just load the section.
this.loaded = true;
this.sectionChanged(sections[0]);
@ -309,18 +288,18 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
}
/**
* Display the section selector modal.
* Display the course index modal.
*/
async showSectionSelector(): Promise<void> {
if (this.sectionSelectorExpanded) {
return;
}
async openCourseIndex(): Promise<void> {
const data = await CoreDomUtils.openModal<CoreCourseSection>({
component: CoreCourseCourseIndexComponent,
componentProps: {
course: this.course,
sections: this.sections,
selected: this.selectedSection,
},
});
this.sectionSelectorExpanded = true;
const data = await CoreDomUtils.openModal<CoreCourseSection>(this.sectionSelectorModalOptions);
this.sectionSelectorExpanded = false;
if (data) {
this.sectionChanged(data);
}
@ -334,7 +313,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
sectionChanged(newSection: CoreCourseSection): void {
const previousValue = this.selectedSection;
this.selectedSection = newSection;
this.sectionSelectorModalOptions.componentProps!.selected = this.selectedSection;
this.data.section = this.selectedSection;
if (newSection.id != this.allSectionsId) {

View File

@ -52,30 +52,28 @@ export class CoreCourseModuleCompletionLegacyComponent extends CoreCourseModuleC
let langKey: string | undefined;
let image: string | undefined;
if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL &&
this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE) {
image = 'completion-manual-n';
langKey = 'core.completion-alt-manual-n';
} else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL &&
this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE) {
image = 'completion-manual-y';
langKey = 'core.completion-alt-manual-y';
} else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC &&
this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE) {
image = 'completion-auto-n';
langKey = 'core.completion-alt-auto-n';
} else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC &&
this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE) {
image = 'completion-auto-y';
langKey = 'core.completion-alt-auto-y';
} else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC &&
this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_PASS) {
image = 'completion-auto-pass';
langKey = 'core.completion-alt-auto-pass';
} else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC &&
this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_FAIL) {
image = 'completion-auto-fail';
langKey = 'core.completion-alt-auto-fail';
if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL) {
if (this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE) {
image = 'completion-manual-n';
langKey = 'core.completion-alt-manual-n';
} else if (this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE) {
image = 'completion-manual-y';
langKey = 'core.completion-alt-manual-y';
}
} else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC) {
if (this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE) {
image = 'completion-auto-n';
langKey = 'core.completion-alt-auto-n';
} else if (this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE) {
image = 'completion-auto-y';
langKey = 'core.completion-alt-auto-y';
} else if (this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_PASS) {
image = 'completion-auto-pass';
langKey = 'core.completion-alt-auto-pass';
} else if (this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_FAIL) {
image = 'completion-auto-fail';
langKey = 'core.completion-alt-auto-fail';
}
}
if (image) {

View File

@ -26,6 +26,7 @@
"confirmdownloadzerosize": "You are about to start downloading.{{availableSpace}} Are you sure you want to continue?",
"confirmpartialdownloadsize": "You are about to download <strong>at least</strong> {{size}}.{{availableSpace}} Are you sure you want to continue?",
"confirmlimiteddownload": "You are not currently connected to Wi-Fi. ",
"courseindex": "Course index",
"gotonextactivity": "Continue to next activity",
"gotonextactivitynotfound": "Next activity not found. It's possible that it has been hidden or deleted.",
"gotopreviousactivity": "Continue to previous activity",
@ -49,7 +50,6 @@
"overriddennotice": "Your final grade from this activity was manually adjusted.",
"refreshcourse": "Refresh course",
"section": "Section",
"sections": "Sections",
"useactivityonbrowser": "You can still use it using your device's web browser.",
"warningmanualcompletionmodified": "The manual completion of an activity was modified on the site.",
"warningofflinemanualcompletiondeleted": "Some offline manual completion of course '{{name}}' has been deleted. {{error}}"

View File

@ -62,7 +62,7 @@ declare module '@singletons/events' {
}
/**
* Completion status valid values.
* Course Module completion status enumeration.
*/
export enum CoreCourseModuleCompletionStatus {
COMPLETION_INCOMPLETE = 0,

View File

@ -125,15 +125,6 @@ export interface CoreCourseFormatHandler extends CoreDelegateHandler {
*/
getCourseSummaryComponent?(course: CoreCourseAnyCourseData): Promise<Type<unknown> | undefined>;
/**
* Return the Component to use to display the section selector inside the default course format.
* It's recommended to return the class of the component, but you can also return an instance of the component.
*
* @param course The course to render.
* @return Promise resolved with component to use, undefined if not found.
*/
getSectionSelectorComponent?(course: CoreCourseAnyCourseData): Promise<Type<unknown> | undefined>;
/**
* Return the Component to use to display a single section. This component will only be used if the user is viewing a
* single section. If all the sections are displayed at once then it won't be used.
@ -302,20 +293,6 @@ export class CoreCourseFormatDelegateService extends CoreDelegate<CoreCourseForm
}
}
/**
* Get the component to use to display the section selector inside the default course format.
*
* @param course The course to render.
* @return Promise resolved with component to use, undefined if not found.
*/
async getSectionSelectorComponent(course: CoreCourseAnyCourseData): Promise<Type<unknown> | undefined> {
try {
return await this.executeFunctionOnEnabled<Type<unknown>>(course.format || '', 'getSectionSelectorComponent', [course]);
} catch (error) {
this.logger.error('Error getting section selector component', error);
}
}
/**
* Get the component to use to display a single section. This component will only be used if the user is viewing
* a single section. If all the sections are displayed at once then it won't be used.