diff --git a/scripts/langindex.json b/scripts/langindex.json index 4f962d300..473b3ddbd 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -2578,6 +2578,7 @@ "core.tag.searchtags": "tag", "core.tag.showingfirsttags": "tag", "core.tag.tag": "moodle", + "core.tag.tagarea_badge": "badges", "core.tag.tagarea_course": "tag", "core.tag.tagarea_course_modules": "tag", "core.tag.tagarea_post": "tag", diff --git a/src/addons/badges/badges.module.ts b/src/addons/badges/badges.module.ts index d96f6d730..e65429de8 100644 --- a/src/addons/badges/badges.module.ts +++ b/src/addons/badges/badges.module.ts @@ -23,6 +23,8 @@ import { AddonBadgesUserHandler } from './services/handlers/user'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; import { AddonBadgesPushClickHandler } from './services/handlers/push-click'; +import { CoreTagAreaDelegate } from '@features/tag/services/tag-area-delegate'; +import { AddonBadgesTagAreaHandler } from './services/handlers/tag-area'; /** * Get badges services. @@ -57,6 +59,7 @@ const mainMenuRoutes: Routes = [ CoreContentLinksDelegate.registerHandler(AddonBadgesBadgeLinkHandler.instance); CoreUserDelegate.registerHandler(AddonBadgesUserHandler.instance); CorePushNotificationsDelegate.registerClickHandler(AddonBadgesPushClickHandler.instance); + CoreTagAreaDelegate.registerHandler(AddonBadgesTagAreaHandler.instance); }, }, ], diff --git a/src/addons/badges/services/handlers/tag-area.ts b/src/addons/badges/services/handlers/tag-area.ts new file mode 100644 index 000000000..e04b3a08a --- /dev/null +++ b/src/addons/badges/services/handlers/tag-area.ts @@ -0,0 +1,53 @@ +// (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 { Injectable, Type } from '@angular/core'; +import { CoreTagFeedComponent } from '@features/tag/components/feed/feed'; +import { CoreTagAreaHandler } from '@features/tag/services/tag-area-delegate'; +import { CoreTagFeedElement, CoreTagHelper } from '@features/tag/services/tag-helper'; +import { makeSingleton } from '@singletons'; +import { AddonBadges } from '../badges'; + +/** + * Handler to support tags. + */ +@Injectable({ providedIn: 'root' }) +export class AddonBadgesTagAreaHandlerService implements CoreTagAreaHandler { + + name = 'AddonBadgesTagAreaHandler'; + type = 'core_badges/badge'; + + /** + * @inheritdoc + */ + isEnabled(): Promise { + return AddonBadges.isPluginEnabled(); + } + + /** + * @inheritdoc + */ + async parseContent(content: string): Promise { + return CoreTagHelper.parseFeedContent(content); + } + + /** + * @inheritdoc + */ + getComponent(): Type | Promise> { + return CoreTagFeedComponent; + } + +} +export const AddonBadgesTagAreaHandler = makeSingleton(AddonBadgesTagAreaHandlerService); diff --git a/src/core/features/tag/components/feed/core-tag-feed.html b/src/core/features/tag/components/feed/core-tag-feed.html index a9715910f..832faa27f 100644 --- a/src/core/features/tag/components/feed/core-tag-feed.html +++ b/src/core/features/tag/components/feed/core-tag-feed.html @@ -1,6 +1,7 @@ - + diff --git a/src/core/features/tag/lang.json b/src/core/features/tag/lang.json index e5b47fd49..5629d469d 100644 --- a/src/core/features/tag/lang.json +++ b/src/core/features/tag/lang.json @@ -8,8 +8,9 @@ "searchtags": "Search tags", "showingfirsttags": "Showing {{$a}} most popular tags", "tag": "Tag", - "tagarea_course": "Courses", + "tagarea_badge": "Badges", "tagarea_course_modules": "Activities and resources", + "tagarea_course": "Courses", "tagarea_post": "Blog posts", "tagarea_user": "User interests", "tagareabadgedescription": "There are {{count}} items.", diff --git a/src/core/features/tag/services/tag-area-delegate.ts b/src/core/features/tag/services/tag-area-delegate.ts index e8e697963..a8714bd68 100644 --- a/src/core/features/tag/services/tag-area-delegate.ts +++ b/src/core/features/tag/services/tag-area-delegate.ts @@ -69,7 +69,7 @@ export class CoreTagAreaDelegateService extends CoreDelegate * @returns String key. */ getDisplayNameKey(component: string, itemType: string): string { - return (component == 'core' ? 'core.tag' : 'addon.' + component) + '.tagarea_' + itemType; + return (component === 'core' || component.startsWith('core_') ? 'core.tag' : 'addon.' + component) + '.tagarea_' + itemType; } /** diff --git a/src/core/features/tag/services/tag-helper.ts b/src/core/features/tag/services/tag-helper.ts index d618fe490..becd52a95 100644 --- a/src/core/features/tag/services/tag-helper.ts +++ b/src/core/features/tag/services/tag-helper.ts @@ -32,11 +32,11 @@ export class CoreTagHelperProvider { const items: CoreTagFeedElement[] = []; const element = CoreDomUtils.convertToElement(content); - Array.from(element.querySelectorAll('ul.tag_feed > li.media')).forEach((itemElement) => { + Array.from(element.querySelectorAll('ul.tag_feed > li')).forEach((itemElement) => { const item: CoreTagFeedElement = { details: [] }; - Array.from(itemElement.querySelectorAll('div.media-body > div')).forEach((div: HTMLElement) => { - if (div.classList.contains('media-heading')) { + Array.from(itemElement.querySelectorAll('div.media-body > div, div.flex-grow-1 > div')).forEach((div: HTMLElement) => { + if (div.classList.contains('media-heading') || div.classList.contains('item-heading')) { item.heading = div.innerText.trim(); const link = div.querySelector('a'); if (link) { @@ -46,11 +46,11 @@ export class CoreTagHelperProvider { // Separate details by lines. const lines = ['']; Array.from(div.childNodes).forEach((childNode: Node) => { - if (childNode.nodeType == Node.TEXT_NODE) { + if (childNode.nodeType === Node.TEXT_NODE) { lines[lines.length - 1] += childNode.textContent; - } else if (childNode.nodeType == Node.ELEMENT_NODE) { + } else if (childNode.nodeType === Node.ELEMENT_NODE) { const childElement = childNode as HTMLElement; - if (childElement.tagName == 'BR') { + if (childElement.tagName === 'BR') { lines.push(''); } else { lines[lines.length - 1] += childElement.innerText; @@ -61,13 +61,20 @@ export class CoreTagHelperProvider { } }); - const image = itemElement.querySelector('div.itemimage img'); + const image = itemElement.querySelector('div.itemimage img, div.flex-shrink-0 img'); if (image) { if (image.classList.contains('userpicture')) { item.avatarUrl = image.getAttribute('src'); + item.fullname = image.getAttribute('title'); } else { item.iconUrl = image.getAttribute('src'); } + } else { + const initials = itemElement.querySelector('div.itemimage .userinitials, div.flex-shrink-0 .userinitials'); + if (initials) { + item.avatarUrl = 'error'; // Use 'error' to show the default avatar. + item.fullname = initials.getAttribute('title'); + } } if (item.heading && item.url) { @@ -91,4 +98,5 @@ export type CoreTagFeedElement = { iconUrl?: string | null; avatarUrl?: string | null; url?: string | null; + fullname?: string | null; };