diff --git a/src/core/features/contentlinks/classes/module-list-handler.ts b/src/core/features/contentlinks/classes/module-list-handler.ts index f1c5c376a..0a05df9e1 100644 --- a/src/core/features/contentlinks/classes/module-list-handler.ts +++ b/src/core/features/contentlinks/classes/module-list-handler.ts @@ -16,6 +16,7 @@ import { CoreContentLinksHandlerBase } from './base-handler'; import { Translate } from '@singletons'; import { Params } from '@angular/router'; import { CoreContentLinksAction } from '../services/contentlinks-delegate'; +import { CoreNavigator } from '@services/navigator'; /** * Handler to handle URLs pointing to a list of a certain type of modules. @@ -55,16 +56,15 @@ export class CoreContentLinksModuleListHandler extends CoreContentLinksHandlerBa getActions(siteIds: string[], url: string, params: Params): CoreContentLinksAction[] | Promise { return [{ - // eslint-disable-next-line @typescript-eslint/no-unused-vars action: (siteId): void => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const stateParams = { - courseId: params.id, - modName: this.modName, - title: this.title || Translate.instance.instant('addon.mod_' + this.modName + '.modulenameplural'), - }; - - // @todo CoreNavigator.instance.goInSite('CoreCourseListModTypePage', stateParams, siteId); + CoreNavigator.instance.navigateToSitePath('course/list-mod-type', { + params: { + courseId: params.id, + modName: this.modName, + title: this.title || Translate.instance.instant('addon.mod_' + this.modName + '.modulenameplural'), + }, + siteId, + }); }, }]; } diff --git a/src/core/features/course/course-lazy.module.ts b/src/core/features/course/course-lazy.module.ts index b78a3f30c..fa42b82c0 100644 --- a/src/core/features/course/course-lazy.module.ts +++ b/src/core/features/course/course-lazy.module.ts @@ -30,6 +30,10 @@ const routes: Routes = [ loadChildren: () => import('./pages/unsupported-module/unsupported-module.module') .then( m => m.CoreCourseUnsupportedModulePageModule), }, + { + path: 'list-mod-type', + loadChildren: () => import('./pages/list-mod-type/list-mod-type').then( m => m.CoreCourseListModTypePage), + }, ]; @NgModule({ diff --git a/src/core/features/course/pages/list-mod-type/list-mod-type.html b/src/core/features/course/pages/list-mod-type/list-mod-type.html new file mode 100644 index 000000000..7c2ebffed --- /dev/null +++ b/src/core/features/course/pages/list-mod-type/list-mod-type.html @@ -0,0 +1,28 @@ + + + + + + {{ title }} + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/core/features/course/pages/list-mod-type/list-mod-type.module.ts b/src/core/features/course/pages/list-mod-type/list-mod-type.module.ts new file mode 100644 index 000000000..8efce4a18 --- /dev/null +++ b/src/core/features/course/pages/list-mod-type/list-mod-type.module.ts @@ -0,0 +1,46 @@ +// (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 { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule, Routes } from '@angular/router'; +import { IonicModule } from '@ionic/angular'; +import { TranslateModule } from '@ngx-translate/core'; + +import { CoreSharedModule } from '@/core/shared.module'; +import { CoreCourseListModTypePage } from './list-mod-type'; +import { CoreCourseComponentsModule } from '@features/course/components/components.module'; + +const routes: Routes = [ + { + path: '', + component: CoreCourseListModTypePage, + }, +]; + +@NgModule({ + declarations: [ + CoreCourseListModTypePage, + ], + imports: [ + RouterModule.forChild(routes), + CommonModule, + IonicModule, + TranslateModule.forChild(), + CoreSharedModule, + CoreCourseComponentsModule, + ], + exports: [RouterModule], +}) +export class CoreCourseListModTypePageModule {} diff --git a/src/core/features/course/pages/list-mod-type/list-mod-type.ts b/src/core/features/course/pages/list-mod-type/list-mod-type.ts new file mode 100644 index 000000000..13661b8a3 --- /dev/null +++ b/src/core/features/course/pages/list-mod-type/list-mod-type.ts @@ -0,0 +1,132 @@ +// (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, OnInit } from '@angular/core'; + +import { CoreSites } from '@services/sites'; +import { CoreDomUtils } from '@services/utils/dom'; +import { CoreCourse } from '@features/course/services/course'; +import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; +import { CoreCourseHelper, CoreCourseSection } from '@features/course/services/course-helper'; +import { CoreNavigator } from '@services/navigator'; +import { CoreConstants } from '@/core/constants'; +import { IonRefresher } from '@ionic/angular'; +import { CoreUtils } from '@services/utils/utils'; + +/** + * Page that displays all modules of a certain type in a course. + */ +@Component({ + selector: 'page-core-course-list-mod-type', + templateUrl: 'list-mod-type.html', +}) +export class CoreCourseListModTypePage implements OnInit { + + sections: CoreCourseSection[] = []; + title = ''; + loaded = false; + downloadEnabled = false; + courseId?: number; + + protected modName?: string; + protected archetypes: Record = {}; // To speed up the check of modules. + + /** + * @inheritdoc + */ + async ngOnInit(): Promise { + this.title = CoreNavigator.instance.getRouteParam('title') || ''; + this.courseId = CoreNavigator.instance.getRouteParam('courseId'); + this.modName = CoreNavigator.instance.getRouteParam('modName'); + this.downloadEnabled = !CoreSites.instance.getCurrentSite()?.isOfflineDisabled(); + + try { + await this.fetchData(); + } finally { + this.loaded = true; + } + } + + /** + * Fetches the data. + * + * @return Resolved when done. + */ + protected async fetchData(): Promise { + if (!this.courseId) { + return; + } + + try { + // Get all the modules in the course. + let sections = await CoreCourse.instance.getSections(this.courseId, false, true); + + sections = sections.filter((section) => { + if (!section.modules) { + return false; + } + + section.modules = section.modules.filter((mod) => { + if (mod.uservisible === false || !CoreCourse.instance.moduleHasView(mod)) { + // Ignore this module. + return false; + } + + if (this.modName === 'resources') { + // Check that the module is a resource. + if (typeof this.archetypes[mod.modname] == 'undefined') { + this.archetypes[mod.modname] = CoreCourseModuleDelegate.instance.supportsFeature( + mod.modname, + CoreConstants.FEATURE_MOD_ARCHETYPE, + CoreConstants.MOD_ARCHETYPE_OTHER, + ); + } + + if (this.archetypes[mod.modname] == CoreConstants.MOD_ARCHETYPE_RESOURCE) { + return true; + } + + } else if (mod.modname == this.modName) { + return true; + } + }); + + return section.modules.length > 0; + }); + + const result = CoreCourseHelper.instance.addHandlerDataForModules(sections, this.courseId); + + this.sections = result.sections; + } catch (error) { + CoreDomUtils.instance.showErrorModalDefault(error, 'Error getting data'); + } + } + + /** + * Refresh the data. + * + * @param refresher Refresher. + * @return Promise resolved when done. + */ + async refreshData(refresher: CustomEvent): Promise { + await CoreUtils.instance.ignoreErrors(CoreCourse.instance.invalidateSections(this.courseId || 0)); + + try { + await this.fetchData(); + } finally { + refresher.detail.complete(); + } + } + +}