diff --git a/src/core/features/course/components/components.module.ts b/src/core/features/course/components/components.module.ts
index 24637f512..02d524304 100644
--- a/src/core/features/course/components/components.module.ts
+++ b/src/core/features/course/components/components.module.ts
@@ -23,6 +23,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 { CoreCourseUnsupportedModuleComponent } from './unsupported-module/unsupported-module';
@NgModule({
@@ -31,6 +32,7 @@ import { CoreCourseUnsupportedModuleComponent } from './unsupported-module/unsup
CoreCourseModuleComponent,
CoreCourseModuleCompletionComponent,
CoreCourseModuleDescriptionComponent,
+ CoreCourseSectionSelectorComponent,
CoreCourseUnsupportedModuleComponent,
],
imports: [
@@ -45,6 +47,7 @@ import { CoreCourseUnsupportedModuleComponent } from './unsupported-module/unsup
CoreCourseModuleComponent,
CoreCourseModuleCompletionComponent,
CoreCourseModuleDescriptionComponent,
+ CoreCourseSectionSelectorComponent,
CoreCourseUnsupportedModuleComponent,
],
})
diff --git a/src/core/features/course/components/format/core-course-format.html b/src/core/features/course/components/format/core-course-format.html
index a4016d942..8f7fcbe87 100644
--- a/src/core/features/course/components/format/core-course-format.html
+++ b/src/core/features/course/components/format/core-course-format.html
@@ -2,7 +2,7 @@
+ [content]="'core.course.sections' | translate" (action)="showSectionSelector()" iconAction="menu">
@@ -19,7 +19,7 @@
-
diff --git a/src/core/features/course/components/format/format.ts b/src/core/features/course/components/format/format.ts
index 3bbad7a01..90b06f01f 100644
--- a/src/core/features/course/components/format/format.ts
+++ b/src/core/features/course/components/format/format.ts
@@ -46,6 +46,8 @@ import { CoreUtils } from '@services/utils/utils';
import { CoreBlockCourseBlocksComponent } from '@features/block/components/course-blocks/course-blocks';
import { CoreCourseSectionFormatted } from '@features/course/services/course-helper';
import { CoreCourseModuleStatusChangedData } from '../module/module';
+import { ModalController } from '@singletons';
+import { CoreCourseSectionSelectorComponent } from '../section-selector/section-selector';
/**
* Component to display course contents using a certain format. If the format isn't found, use default one.
@@ -330,29 +332,30 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
/**
* Display the section selector modal.
- *
- * @param event Event.
*/
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- showSectionSelector(event?: MouseEvent): void {
+ async showSectionSelector(): Promise {
if (this.sectionSelectorExpanded) {
return;
}
- // @todo this.sectionSelectorExpanded = true;
- // const modal = this.modalCtrl.create('CoreCourseSectionSelectorPage',
- // {course: this.course, sections: this.sections, selected: this.selectedSection});
- // modal.onDidDismiss((newSection) => {
- // if (newSection) {
- // this.sectionChanged(newSection);
- // }
+ this.sectionSelectorExpanded = true;
- // this.sectionSelectorExpanded = false;
- // });
+ const modal = await ModalController.instance.create({
+ component: CoreCourseSectionSelectorComponent,
+ componentProps: {
+ course: this.course,
+ sections: this.sections,
+ selected: this.selectedSection,
+ },
+ });
+ await modal.present();
- // modal.present({
- // ev: event
- // });
+ const result = await modal.onWillDismiss();
+
+ this.sectionSelectorExpanded = false;
+ if (result?.data) {
+ this.sectionChanged(result?.data);
+ }
}
/**
diff --git a/src/core/features/course/components/section-selector/section-selector.html b/src/core/features/course/components/section-selector/section-selector.html
new file mode 100644
index 000000000..92b0ba8fa
--- /dev/null
+++ b/src/core/features/course/components/section-selector/section-selector.html
@@ -0,0 +1,39 @@
+
+
+ {{ 'core.course.sections' | translate }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = 0" [progress]="section.progress">
+
+
+ {{ 'core.course.hiddenfromstudents' | translate }}
+
+
+ {{ 'core.notavailable' | translate }}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/core/features/course/components/section-selector/section-selector.scss b/src/core/features/course/components/section-selector/section-selector.scss
new file mode 100644
index 000000000..429076451
--- /dev/null
+++ b/src/core/features/course/components/section-selector/section-selector.scss
@@ -0,0 +1,17 @@
+:host {
+ core-progress-bar {
+ .core-progress-text {
+ line-height: 24px;
+ position: absolute;
+ top: -8px;
+ right: 10px;
+ }
+ progress {
+ margin: 8px 0 4px 0;
+ }
+ }
+
+ ion-badge {
+ text-align: start;
+ }
+}
\ No newline at end of file
diff --git a/src/core/features/course/components/section-selector/section-selector.ts b/src/core/features/course/components/section-selector/section-selector.ts
new file mode 100644
index 000000000..0edc88144
--- /dev/null
+++ b/src/core/features/course/components/section-selector/section-selector.ts
@@ -0,0 +1,98 @@
+// (C) Copyright 2015 Moodle Pty Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { Component, Input, OnInit } from '@angular/core';
+
+import { CoreCourseSectionFormatted } from '@features/course/services/course-helper';
+import { CoreCourseProvider } from '@features/course/services/course';
+import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
+import { CoreUtils } from '@services/utils/utils';
+import { ModalController } from '@singletons';
+
+/**
+ * Component to display course section selector in a modal.
+ */
+@Component({
+ selector: 'core-course-section-selector',
+ templateUrl: 'section-selector.html',
+})
+export class CoreCourseSectionSelectorComponent implements OnInit {
+
+ @Input() sections?: SectionWithProgress[];
+ @Input() selected?: CoreCourseSectionFormatted;
+ @Input() course?: CoreCourseAnyCourseData;
+
+ stealthModulesSectionId = CoreCourseProvider.STEALTH_MODULES_SECTION_ID;
+
+ /**
+ * Component being initialized.
+ */
+ ngOnInit(): void {
+
+ if (!this.course || !this.sections || !this.course.enablecompletion || !('courseformatoptions' in this.course) ||
+ !this.course.courseformatoptions) {
+ return;
+ }
+
+ const formatOptions = CoreUtils.instance.objectToKeyValueMap(this.course.courseformatoptions, 'name', 'value');
+
+ if (!formatOptions || formatOptions.coursedisplay != 1 || formatOptions.completionusertracked === false) {
+ return;
+ }
+
+ this.sections.forEach((section) => {
+ let complete = 0;
+ let total = 0;
+ section.modules.forEach((module) => {
+ if (!module.uservisible || module.completiondata === undefined || module.completiondata.tracking === undefined ||
+ module.completiondata.tracking <= CoreCourseProvider.COMPLETION_TRACKING_NONE) {
+ return;
+ }
+
+ total++;
+ if (module.completiondata.state == CoreCourseProvider.COMPLETION_COMPLETE ||
+ module.completiondata.state == CoreCourseProvider.COMPLETION_COMPLETE_PASS) {
+ complete++;
+ }
+ });
+
+ if (total > 0) {
+ section.progress = complete / total * 100;
+ }
+ });
+ }
+
+ /**
+ * Close the modal.
+ */
+ closeModal(): void {
+ ModalController.instance.dismiss();
+ }
+
+ /**
+ * Select a section.
+ *
+ * @param section Selected section object.
+ */
+ selectSection(section: SectionWithProgress): void {
+ if (section.uservisible !== false) {
+ ModalController.instance.dismiss(section);
+ }
+ }
+
+}
+
+type SectionWithProgress = CoreCourseSectionFormatted & {
+ progress?: number;
+};
diff --git a/src/theme/app.scss b/src/theme/app.scss
index 3bb2d68c2..1e88bf9ee 100644
--- a/src/theme/app.scss
+++ b/src/theme/app.scss
@@ -169,6 +169,9 @@ ion-toolbar {
.item.core-danger-item {
--border-color: var(--ion-color-danger);
}
+.item-dimmed {
+ opacity: 0.71;
+}
// Extra text colors.
.text-gray {