From eed78c8b6f56a85750149ec1186470c1e3153de2 Mon Sep 17 00:00:00 2001 From: Albert Gasset Date: Mon, 8 Jul 2019 12:02:33 +0200 Subject: [PATCH] MOBILE-2201 course: Tag area handler for courses --- scripts/langindex.json | 1 + src/assets/lang/en.json | 1 + .../course/components/components.module.ts | 6 +- .../tag-area/core-course-tag-area.html | 5 ++ .../course/components/tag-area/tag-area.ts | 43 +++++++++++ src/core/course/course.module.ts | 9 ++- .../providers/course-tag-area-handler.ts | 74 +++++++++++++++++++ src/core/tag/lang/en.json | 1 + 8 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 src/core/course/components/tag-area/core-course-tag-area.html create mode 100644 src/core/course/components/tag-area/tag-area.ts create mode 100644 src/core/course/providers/course-tag-area-handler.ts diff --git a/scripts/langindex.json b/scripts/langindex.json index d9741522c..b9db7a280 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1795,6 +1795,7 @@ "core.submit": "moodle", "core.success": "moodle", "core.tablet": "local_moodlemobileapp", + "core.tag.tagarea_course": "moodle", "core.tag.tags": "moodle", "core.teachers": "moodle", "core.thereisdatatosync": "local_moodlemobileapp", diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index b75231f80..1174b5e6a 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1795,6 +1795,7 @@ "core.submit": "Submit", "core.success": "Success", "core.tablet": "Tablet", + "core.tag.tagarea_course": "Courses", "core.tag.tags": "Tags", "core.teachers": "Teachers", "core.thereisdatatosync": "There are offline {{$a}} to be synchronised.", diff --git a/src/core/course/components/components.module.ts b/src/core/course/components/components.module.ts index a56f920d8..4b55708e2 100644 --- a/src/core/course/components/components.module.ts +++ b/src/core/course/components/components.module.ts @@ -22,6 +22,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 { CoreCourseTagAreaComponent } from './tag-area/tag-area'; import { CoreCourseUnsupportedModuleComponent } from './unsupported-module/unsupported-module'; @NgModule({ @@ -30,6 +31,7 @@ import { CoreCourseUnsupportedModuleComponent } from './unsupported-module/unsup CoreCourseModuleComponent, CoreCourseModuleCompletionComponent, CoreCourseModuleDescriptionComponent, + CoreCourseTagAreaComponent, CoreCourseUnsupportedModuleComponent ], imports: [ @@ -46,10 +48,12 @@ import { CoreCourseUnsupportedModuleComponent } from './unsupported-module/unsup CoreCourseModuleComponent, CoreCourseModuleCompletionComponent, CoreCourseModuleDescriptionComponent, + CoreCourseTagAreaComponent, CoreCourseUnsupportedModuleComponent ], entryComponents: [ - CoreCourseUnsupportedModuleComponent + CoreCourseUnsupportedModuleComponent, + CoreCourseTagAreaComponent ] }) export class CoreCourseComponentsModule {} diff --git a/src/core/course/components/tag-area/core-course-tag-area.html b/src/core/course/components/tag-area/core-course-tag-area.html new file mode 100644 index 000000000..b372fdf09 --- /dev/null +++ b/src/core/course/components/tag-area/core-course-tag-area.html @@ -0,0 +1,5 @@ + + +

{{ item.courseName }}

+

{{ 'core.category' | translate }}: {{ item.categoryName }}

+
diff --git a/src/core/course/components/tag-area/tag-area.ts b/src/core/course/components/tag-area/tag-area.ts new file mode 100644 index 000000000..07d34c21c --- /dev/null +++ b/src/core/course/components/tag-area/tag-area.ts @@ -0,0 +1,43 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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, Optional } from '@angular/core'; +import { NavController } from 'ionic-angular'; +import { CoreSplitViewComponent } from '@components/split-view/split-view'; +import { CoreCourseHelperProvider } from '@core/course/providers/helper'; + +/** + * Component that renders the course tag area. + */ +@Component({ + selector: 'core-course-tag-area', + templateUrl: 'core-course-tag-area.html' +}) +export class CoreCourseTagAreaComponent { + @Input() items: any[]; // Area items to render. + + constructor(private navCtrl: NavController, @Optional() private splitviewCtrl: CoreSplitViewComponent, + private courseHelper: CoreCourseHelperProvider) {} + + /** + * Open a course. + * + * @param {number} courseId The course to open. + */ + openCourse(courseId: number): void { + // If this component is inside a split view, use the master nav to open it. + const navCtrl = this.splitviewCtrl ? this.splitviewCtrl.getMasterNav() : this.navCtrl; + this.courseHelper.getAndOpenCourse(navCtrl, courseId); + } +} diff --git a/src/core/course/course.module.ts b/src/core/course/course.module.ts index 5293eda63..4e8206abf 100644 --- a/src/core/course/course.module.ts +++ b/src/core/course/course.module.ts @@ -33,6 +33,8 @@ import { CoreCourseFormatWeeksModule } from './formats/weeks/weeks.module'; import { CoreCourseSyncProvider } from './providers/sync'; import { CoreCourseSyncCronHandler } from './providers/sync-cron-handler'; import { CoreCourseLogCronHandler } from './providers/log-cron-handler'; +import { CoreTagAreaDelegate } from '@core/tag/providers/area-delegate'; +import { CoreCourseTagAreaHandler } from './providers/course-tag-area-handler'; // List of providers (without handlers). export const CORE_COURSE_PROVIDERS: any[] = [ @@ -68,15 +70,18 @@ export const CORE_COURSE_PROVIDERS: any[] = [ CoreCourseFormatDefaultHandler, CoreCourseModuleDefaultHandler, CoreCourseSyncCronHandler, - CoreCourseLogCronHandler + CoreCourseLogCronHandler, + CoreCourseTagAreaHandler ], exports: [] }) export class CoreCourseModule { constructor(cronDelegate: CoreCronDelegate, syncHandler: CoreCourseSyncCronHandler, logHandler: CoreCourseLogCronHandler, - platform: Platform, eventsProvider: CoreEventsProvider) { + platform: Platform, eventsProvider: CoreEventsProvider, tagAreaDelegate: CoreTagAreaDelegate, + courseTagAreaHandler: CoreCourseTagAreaHandler) { cronDelegate.register(syncHandler); cronDelegate.register(logHandler); + tagAreaDelegate.registerHandler(courseTagAreaHandler); platform.resume.subscribe(() => { // Log the app is open to keep user in online status. diff --git a/src/core/course/providers/course-tag-area-handler.ts b/src/core/course/providers/course-tag-area-handler.ts new file mode 100644 index 000000000..066754de6 --- /dev/null +++ b/src/core/course/providers/course-tag-area-handler.ts @@ -0,0 +1,74 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { Injectable, Injector } from '@angular/core'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; +import { CoreTagAreaHandler } from '@core/tag/providers/area-delegate'; +import { CoreCourseTagAreaComponent } from '../components/tag-area/tag-area'; + +/** + * Handler to support tags. + */ +@Injectable() +export class CoreCourseTagAreaHandler implements CoreTagAreaHandler { + name = 'CoreCourseTagAreaHandler'; + type = 'core/course'; + + constructor(private domUtils: CoreDomUtilsProvider) {} + + /** + * Whether or not the handler is enabled on a site level. + * @return {boolean|Promise} Whether or not the handler is enabled on a site level. + */ + isEnabled(): boolean | Promise { + return true; + } + + /** + * Parses the rendered content of a tag index and returns the items. + * + * @param {string} content Rendered content. + * @return {any[]|Promise} Area items (or promise resolved with the items). + */ + parseContent(content: string): any[] | Promise { + const items = []; + const element = this.domUtils.convertToElement(content); + + Array.from(element.querySelectorAll('div.coursebox')).forEach((coursebox) => { + const courseId = parseInt(coursebox.getAttribute('data-courseid'), 10); + const courseLink = coursebox.querySelector('.coursename > a'); + const categoryLink = coursebox.querySelector('.coursecat > a'); + + if (courseId > 0 && courseLink) { + items.push({ + courseId, + courseName: courseLink.innerHTML, + categoryName: categoryLink ? categoryLink.innerHTML : null + }); + } + }); + + return items; + } + + /** + * Get the component to use to display items. + * + * @param {Injector} injector Injector. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getComponent(injector: Injector): any | Promise { + return CoreCourseTagAreaComponent; + } +} diff --git a/src/core/tag/lang/en.json b/src/core/tag/lang/en.json index fec56bb36..c8303131c 100644 --- a/src/core/tag/lang/en.json +++ b/src/core/tag/lang/en.json @@ -1,3 +1,4 @@ { + "tagarea_course": "Courses", "tags": "Tags" }