From 101faf20aaec071953ac2ae7b186bdaf703276cd Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Fri, 21 Jan 2022 12:58:11 +0100 Subject: [PATCH] MOBILE-3966 user: Use context+contextId in user delegate --- src/addons/badges/services/handlers/user.ts | 28 +-- src/addons/blog/services/handlers/user.ts | 4 +- .../competency/services/handlers/user.ts | 43 ++-- .../services/handlers/user.ts | 21 +- .../services/handlers/user-send-message.ts | 11 +- src/addons/notes/services/handlers/user.ts | 17 +- .../privatefiles/services/handlers/user.ts | 13 +- .../features/grades/services/handlers/user.ts | 19 +- .../components/user-menu/user-menu.ts | 34 +-- .../classes/handlers/user-handler.ts | 18 +- .../user/pages/profile/profile.page.ts | 16 +- .../user/services/handlers/profile-mail.ts | 2 +- .../features/user/services/user-delegate.ts | 232 ++++++++++++------ upgrade.txt | 4 + 14 files changed, 284 insertions(+), 178 deletions(-) diff --git a/src/addons/badges/services/handlers/user.ts b/src/addons/badges/services/handlers/user.ts index 5e3a5bc44..a15acfed3 100644 --- a/src/addons/badges/services/handlers/user.ts +++ b/src/addons/badges/services/handlers/user.ts @@ -14,7 +14,12 @@ import { Injectable } from '@angular/core'; import { CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses'; -import { CoreUserDelegateService, CoreUserProfileHandler, CoreUserProfileHandlerData } from '@features/user/services/user-delegate'; +import { + CoreUserDelegateContext, + CoreUserDelegateService, + CoreUserProfileHandler, + CoreUserProfileHandlerData, +} from '@features/user/services/user-delegate'; import { CoreNavigator } from '@services/navigator'; import { makeSingleton } from '@singletons'; import { AddonBadges } from '../badges'; @@ -30,22 +35,17 @@ export class AddonBadgesUserHandlerService implements CoreUserProfileHandler { type = CoreUserDelegateService.TYPE_NEW_PAGE; /** - * Check if handler is enabled. - * - * @return Always enabled. + * @inheritdoc */ isEnabled(): Promise { return AddonBadges.isPluginEnabled(); } /** - * Check if handler is enabled for this user in this context. - * - * @param courseId Course ID. - * @param navOptions Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions. - * @return True if enabled, false otherwise. + * @inheritdoc */ - async isEnabledForCourse( + async isEnabledForContext( + context: CoreUserDelegateContext, courseId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed, ): Promise { @@ -58,19 +58,17 @@ export class AddonBadgesUserHandlerService implements CoreUserProfileHandler { } /** - * Returns the data needed to render the handler. - * - * @return Data needed to render the handler. + * @inheritdoc */ getDisplayData(): CoreUserProfileHandlerData { return { icon: 'fas-trophy', title: 'addon.badges.badges', - action: (event, user, courseId): void => { + action: (event, user, context, contextId): void => { event.preventDefault(); event.stopPropagation(); CoreNavigator.navigateToSitePath('/badges', { - params: { courseId, userId: user.id }, + params: { courseId: contextId, userId: user.id }, }); }, }; diff --git a/src/addons/blog/services/handlers/user.ts b/src/addons/blog/services/handlers/user.ts index 5c6d08726..566b361bf 100644 --- a/src/addons/blog/services/handlers/user.ts +++ b/src/addons/blog/services/handlers/user.ts @@ -43,11 +43,11 @@ export class AddonBlogUserHandlerService implements CoreUserProfileHandler { icon: 'far-newspaper', title: 'addon.blog.blogentries', class: 'addon-blog-handler', - action: (event, user, courseId): void => { + action: (event, user, context, contextId): void => { event.preventDefault(); event.stopPropagation(); CoreNavigator.navigateToSitePath('/blog', { - params: { courseId, userId: user.id }, + params: { courseId: contextId, userId: user.id }, }); }, }; diff --git a/src/addons/competency/services/handlers/user.ts b/src/addons/competency/services/handlers/user.ts index 2bd346028..9f8b28379 100644 --- a/src/addons/competency/services/handlers/user.ts +++ b/src/addons/competency/services/handlers/user.ts @@ -16,7 +16,12 @@ import { ADDON_COMPETENCY_COMPETENCIES_PAGE, ADDON_COMPETENCY_LEARNING_PLANS_PAG import { Injectable } from '@angular/core'; import { COURSE_PAGE_NAME } from '@features/course/course.module'; import { CoreUserProfile } from '@features/user/services/user'; -import { CoreUserProfileHandler, CoreUserDelegateService, CoreUserProfileHandlerData } from '@features/user/services/user-delegate'; +import { + CoreUserProfileHandler, + CoreUserDelegateService, + CoreUserProfileHandlerData, + CoreUserDelegateContext, +} from '@features/user/services/user-delegate'; import { PARTICIPANTS_PAGE_NAME } from '@features/user/user.module'; import { CoreNavigator } from '@services/navigator'; import { makeSingleton } from '@singletons'; @@ -43,10 +48,10 @@ export class AddonCompetencyUserHandlerService implements CoreUserProfileHandler /** * @inheritdoc */ - async isEnabledForUser(user: CoreUserProfile, courseId?: number): Promise { + async isEnabledForUser(user: CoreUserProfile, context: CoreUserDelegateContext, contextId: number): Promise { try { - if (courseId) { - return AddonCompetency.canViewUserCompetenciesInCourse(courseId, user.id); + if (context === CoreUserDelegateContext.COURSE) { + return await AddonCompetency.canViewUserCompetenciesInCourse(contextId, user.id); } else { const plans = await AddonCompetency.getLearningPlans(user.id); @@ -61,21 +66,8 @@ export class AddonCompetencyUserHandlerService implements CoreUserProfileHandler /** * @inheritdoc */ - getDisplayData(user: CoreUserProfile, courseId: number): CoreUserProfileHandlerData { - if (courseId) { - return { - icon: 'fas-award', - title: 'addon.competency.competencies', - class: 'addon-competency-handler', - action: (event, user, courseId): void => { - event.preventDefault(); - event.stopPropagation(); - CoreNavigator.navigateToSitePath( - [COURSE_PAGE_NAME, courseId, PARTICIPANTS_PAGE_NAME, user.id, ADDON_COMPETENCY_COMPETENCIES_PAGE].join('/'), - ); - }, - }; - } else { + getDisplayData(user: CoreUserProfile, context: CoreUserDelegateContext): CoreUserProfileHandlerData { + if (context !== CoreUserDelegateContext.COURSE) { return { icon: 'fas-route', title: 'addon.competency.learningplans', @@ -89,6 +81,19 @@ export class AddonCompetencyUserHandlerService implements CoreUserProfileHandler }, }; } + + return { + icon: 'fas-award', + title: 'addon.competency.competencies', + class: 'addon-competency-handler', + action: (event, user, context, contextId): void => { + event.preventDefault(); + event.stopPropagation(); + CoreNavigator.navigateToSitePath( + [COURSE_PAGE_NAME, contextId, PARTICIPANTS_PAGE_NAME, user.id, ADDON_COMPETENCY_COMPETENCIES_PAGE].join('/'), + ); + }, + }; } } diff --git a/src/addons/coursecompletion/services/handlers/user.ts b/src/addons/coursecompletion/services/handlers/user.ts index 172073c60..69f47f71f 100644 --- a/src/addons/coursecompletion/services/handlers/user.ts +++ b/src/addons/coursecompletion/services/handlers/user.ts @@ -14,7 +14,12 @@ import { Injectable } from '@angular/core'; import { CoreUserProfile } from '@features/user/services/user'; -import { CoreUserProfileHandler, CoreUserDelegateService, CoreUserProfileHandlerData } from '@features/user/services/user-delegate'; +import { + CoreUserProfileHandler, + CoreUserDelegateService, + CoreUserProfileHandlerData, + CoreUserDelegateContext, +} from '@features/user/services/user-delegate'; import { CoreNavigator } from '@services/navigator'; import { makeSingleton } from '@singletons'; import { AddonCourseCompletion } from '../coursecompletion'; @@ -40,15 +45,19 @@ export class AddonCourseCompletionUserHandlerService implements CoreUserProfileH /** * @inheritdoc */ - async isEnabledForCourse(courseId?: number): Promise { + async isEnabledForContext(context: CoreUserDelegateContext, courseId: number): Promise { + if (context !== CoreUserDelegateContext.COURSE) { + return false; + } + return AddonCourseCompletion.isPluginViewEnabledForCourse(courseId); } /** * @inheritdoc */ - async isEnabledForUser(user: CoreUserProfile, courseId?: number): Promise { - return await AddonCourseCompletion.isPluginViewEnabledForUser(courseId!, user.id); + async isEnabledForUser(user: CoreUserProfile, context: CoreUserDelegateContext, contextId: number): Promise { + return await AddonCourseCompletion.isPluginViewEnabledForUser(contextId, user.id); } /** @@ -59,11 +68,11 @@ export class AddonCourseCompletionUserHandlerService implements CoreUserProfileH icon: 'fas-tasks', title: 'addon.coursecompletion.coursecompletion', class: 'addon-coursecompletion-handler', - action: (event, user, courseId): void => { + action: (event, user, context, contextId): void => { event.preventDefault(); event.stopPropagation(); CoreNavigator.navigateToSitePath('/coursecompletion', { - params: { courseId, userId: user.id }, + params: { courseId: contextId, userId: user.id }, }); }, }; diff --git a/src/addons/messages/services/handlers/user-send-message.ts b/src/addons/messages/services/handlers/user-send-message.ts index 6afaa6080..0e9d12f8d 100644 --- a/src/addons/messages/services/handlers/user-send-message.ts +++ b/src/addons/messages/services/handlers/user-send-message.ts @@ -32,9 +32,7 @@ export class AddonMessagesSendMessageUserHandlerService implements CoreUserProfi type = CoreUserDelegateService.TYPE_COMMUNICATION; /** - * Check if handler is enabled. - * - * @return Promise resolved with true if enabled, rejected or resolved with false otherwise. + * @inheritdoc */ isEnabled(): Promise { return AddonMessages.isPluginEnabled(); @@ -43,15 +41,12 @@ export class AddonMessagesSendMessageUserHandlerService implements CoreUserProfi /** * @inheritdoc */ - async isEnabledForCourse(): Promise { + async isEnabledForContext(): Promise { return !!CoreSites.getCurrentSite(); } /** - * Check if handler is enabled for this user in this context. - * - * @param user User to check. - * @return Promise resolved with true if enabled, resolved with false otherwise. + * @inheritdoc */ async isEnabledForUser(user: CoreUserProfile): Promise { const currentSite = CoreSites.getRequiredCurrentSite(); diff --git a/src/addons/notes/services/handlers/user.ts b/src/addons/notes/services/handlers/user.ts index f0dc13001..4bad2ad6e 100644 --- a/src/addons/notes/services/handlers/user.ts +++ b/src/addons/notes/services/handlers/user.ts @@ -14,7 +14,12 @@ import { Injectable } from '@angular/core'; import { CoreUserProfile } from '@features/user/services/user'; -import { CoreUserProfileHandler, CoreUserDelegateService, CoreUserProfileHandlerData } from '@features/user/services/user-delegate'; +import { + CoreUserProfileHandler, + CoreUserDelegateService, + CoreUserProfileHandlerData, + CoreUserDelegateContext, +} from '@features/user/services/user-delegate'; import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; import { makeSingleton } from '@singletons'; @@ -41,14 +46,14 @@ export class AddonNotesUserHandlerService implements CoreUserProfileHandler { /** * @inheritdoc */ - async isEnabledForUser(user: CoreUserProfile, courseId?: number): Promise { + async isEnabledForUser(user: CoreUserProfile, context: CoreUserDelegateContext, contextId: number): Promise { // Active course required. - if (!courseId || user.id == CoreSites.getCurrentSiteUserId()) { + if (context !== CoreUserDelegateContext.COURSE || !contextId || user.id == CoreSites.getCurrentSiteUserId()) { return false; } // We are not using isEnabledForCourse because we need to cache the call. - return AddonNotes.isPluginViewNotesEnabledForCourse(courseId); + return AddonNotes.isPluginViewNotesEnabledForCourse(contextId); } /** @@ -59,11 +64,11 @@ export class AddonNotesUserHandlerService implements CoreUserProfileHandler { icon: 'fas-receipt', title: 'addon.notes.notes', class: 'addon-notes-handler', - action: (event, user, courseId): void => { + action: (event, user, context, contextId): void => { event.preventDefault(); event.stopPropagation(); CoreNavigator.navigateToSitePath('/notes', { - params: { courseId, userId: user.id }, + params: { courseId: contextId, userId: user.id }, }); }, }; diff --git a/src/addons/privatefiles/services/handlers/user.ts b/src/addons/privatefiles/services/handlers/user.ts index 4672385b3..f35aba520 100644 --- a/src/addons/privatefiles/services/handlers/user.ts +++ b/src/addons/privatefiles/services/handlers/user.ts @@ -16,7 +16,12 @@ import { Injectable } from '@angular/core'; import { AddonPrivateFiles } from '@/addons/privatefiles/services/privatefiles'; import { makeSingleton } from '@singletons'; -import { CoreUserDelegateService, CoreUserProfileHandler, CoreUserProfileHandlerData } from '@features/user/services/user-delegate'; +import { + CoreUserDelegateContext, + CoreUserDelegateService, + CoreUserProfileHandler, + CoreUserProfileHandlerData, +} from '@features/user/services/user-delegate'; import { CoreUserProfile } from '@features/user/services/user'; import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; @@ -44,9 +49,9 @@ export class AddonPrivateFilesUserHandlerService implements CoreUserProfileHandl /** * @inheritdoc */ - async isEnabledForUser(user: CoreUserProfile): Promise { - // Private files only available for the current user. - return user.id == CoreSites.getCurrentSiteUserId(); + async isEnabledForUser(user: CoreUserProfile, context: CoreUserDelegateContext): Promise { + // Private files only available for the current user in user menu. + return user.id == CoreSites.getCurrentSiteUserId() && context === CoreUserDelegateContext.USER_MENU; } /** diff --git a/src/core/features/grades/services/handlers/user.ts b/src/core/features/grades/services/handlers/user.ts index 6c4a655a0..61009832a 100644 --- a/src/core/features/grades/services/handlers/user.ts +++ b/src/core/features/grades/services/handlers/user.ts @@ -19,6 +19,7 @@ import { GRADES_PAGE_NAME } from '@features/grades/grades.module'; import { CoreGrades } from '@features/grades/services/grades'; import { CoreUserProfile } from '@features/user/services/user'; import { + CoreUserDelegateContext, CoreUserDelegateService , CoreUserProfileHandler, CoreUserProfileHandlerData, @@ -50,8 +51,8 @@ export class CoreGradesUserHandlerService implements CoreUserProfileHandler { /** * @inheritdoc */ - async isEnabledForCourse(courseId?: number): Promise { - if (courseId) { + async isEnabledForContext(context: CoreUserDelegateContext, courseId: number): Promise { + if (context === CoreUserDelegateContext.COURSE) { return CoreUtils.ignoreErrors(CoreGrades.isPluginEnabledForCourse(courseId), false); } else { return CoreGrades.isCourseGradesEnabled(); @@ -61,9 +62,9 @@ export class CoreGradesUserHandlerService implements CoreUserProfileHandler { /** * @inheritdoc */ - async isEnabledForUser(user: CoreUserProfile, courseId?: number): Promise { - if (courseId) { - return CoreUtils.promiseWorks(CoreGrades.getCourseGradesTable(courseId, user.id)); + async isEnabledForUser(user: CoreUserProfile, context: CoreUserDelegateContext, contextId: number): Promise { + if (context === CoreUserDelegateContext.COURSE) { + return CoreUtils.promiseWorks(CoreGrades.getCourseGradesTable(contextId, user.id)); } // All course grades only available for the current user. @@ -73,17 +74,17 @@ export class CoreGradesUserHandlerService implements CoreUserProfileHandler { /** * @inheritdoc */ - getDisplayData(user: CoreUserProfile, courseId?: number): CoreUserProfileHandlerData { - if (courseId) { + getDisplayData(user: CoreUserProfile, context: CoreUserDelegateContext): CoreUserProfileHandlerData { + if (context === CoreUserDelegateContext.COURSE) { return { icon: 'fas-chart-bar', title: 'core.grades.grades', class: 'core-grades-user-handler', - action: (event, user, courseId): void => { + action: (event, user, context, contextId): void => { event.preventDefault(); event.stopPropagation(); CoreNavigator.navigateToSitePath( - [COURSE_PAGE_NAME, courseId, PARTICIPANTS_PAGE_NAME, user.id, GRADES_PAGE_NAME].join('/'), + [COURSE_PAGE_NAME, contextId, PARTICIPANTS_PAGE_NAME, user.id, GRADES_PAGE_NAME].join('/'), ); }, }; diff --git a/src/core/features/mainmenu/components/user-menu/user-menu.ts b/src/core/features/mainmenu/components/user-menu/user-menu.ts index 2ac460e3e..dce64d9ea 100644 --- a/src/core/features/mainmenu/components/user-menu/user-menu.ts +++ b/src/core/features/mainmenu/components/user-menu/user-menu.ts @@ -18,7 +18,12 @@ import { CoreSite, CoreSiteInfo } from '@classes/site'; import { CoreLoginSitesComponent } from '@features/login/components/sites/sites'; import { CoreLoginHelper } from '@features/login/services/login-helper'; import { CoreUser, CoreUserProfile } from '@features/user/services/user'; -import { CoreUserProfileHandlerData, CoreUserDelegate, CoreUserDelegateService } from '@features/user/services/user-delegate'; +import { + CoreUserProfileHandlerData, + CoreUserDelegate, + CoreUserDelegateService, + CoreUserDelegateContext, +} from '@features/user/services/user-delegate'; import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; @@ -64,20 +69,21 @@ export class CoreMainMenuUserMenuComponent implements OnInit, OnDestroy { if (this.siteInfo) { this.user = await CoreUser.getProfile(this.siteInfo.userid); - this.subscription = CoreUserDelegate.getProfileHandlersFor(this.user).subscribe((handlers) => { - if (!handlers || !this.user) { - return; - } - - this.handlers = []; - handlers.forEach((handler) => { - if (handler.type == CoreUserDelegateService.TYPE_NEW_PAGE) { - this.handlers.push(handler.data); + this.subscription = CoreUserDelegate.getProfileHandlersFor(this.user, CoreUserDelegateContext.USER_MENU) + .subscribe((handlers) => { + if (!handlers || !this.user) { + return; } - }); - this.handlersLoaded = CoreUserDelegate.areHandlersLoaded(this.user.id); - }); + this.handlers = []; + handlers.forEach((handler) => { + if (handler.type == CoreUserDelegateService.TYPE_NEW_PAGE) { + this.handlers.push(handler.data); + } + }); + + this.handlersLoaded = CoreUserDelegate.areHandlersLoaded(this.user.id, CoreUserDelegateContext.USER_MENU); + }); } } @@ -150,7 +156,7 @@ export class CoreMainMenuUserMenuComponent implements OnInit, OnDestroy { await this.close(event); - handler.action(event, this.user); + handler.action(event, this.user, CoreUserDelegateContext.USER_MENU); } /** diff --git a/src/core/features/siteplugins/classes/handlers/user-handler.ts b/src/core/features/siteplugins/classes/handlers/user-handler.ts index 12e48e214..036cc8152 100644 --- a/src/core/features/siteplugins/classes/handlers/user-handler.ts +++ b/src/core/features/siteplugins/classes/handlers/user-handler.ts @@ -19,9 +19,13 @@ import { CoreSitePluginsUserHandlerData, } from '@features/siteplugins/services/siteplugins'; import { CoreUserProfile } from '@features/user/services/user'; -import { CoreUserDelegateService, CoreUserProfileHandler, CoreUserProfileHandlerData } from '@features/user/services/user-delegate'; +import { + CoreUserDelegateContext, + CoreUserDelegateService, + CoreUserProfileHandler, + CoreUserProfileHandlerData, +} from '@features/user/services/user-delegate'; import { CoreNavigator } from '@services/navigator'; -import { CoreSites } from '@services/sites'; import { CoreUtils, PromiseDefer } from '@services/utils/utils'; import { Md5 } from 'ts-md5'; import { CoreSitePluginsBaseHandler } from './base-handler'; @@ -55,11 +59,7 @@ export class CoreSitePluginsUserProfileHandler extends CoreSitePluginsBaseHandle /** * @inheritdoc */ - async isEnabledForCourse( - courseId?: number, - ): Promise { - courseId = courseId || CoreSites.getCurrentSiteHomeId(); - + async isEnabledForContext(context: CoreUserDelegateContext, courseId: number): Promise { // Check if it's enabled for the course. return CoreSitePlugins.isHandlerEnabledForCourse( courseId, @@ -89,12 +89,12 @@ export class CoreSitePluginsUserProfileHandler extends CoreSitePluginsBaseHandle title: this.title, icon: this.handlerSchema.displaydata?.icon, class: this.handlerSchema.displaydata?.class, - action: (event: Event, user: CoreUserProfile, courseId?: number): void => { + action: (event, user, context, contextId): void => { event.preventDefault(); event.stopPropagation(); const args = { - courseid: courseId, + courseid: contextId, userid: user.id, }; const hash = Md5.hashAsciiStr(JSON.stringify(args)); diff --git a/src/core/features/user/pages/profile/profile.page.ts b/src/core/features/user/pages/profile/profile.page.ts index 88604bde6..e23ff8f3c 100644 --- a/src/core/features/user/pages/profile/profile.page.ts +++ b/src/core/features/user/pages/profile/profile.page.ts @@ -23,7 +23,12 @@ import { CoreDomUtils } from '@services/utils/dom'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreUser, CoreUserProfile, CoreUserProvider } from '@features/user/services/user'; import { CoreUserHelper } from '@features/user/services/user-helper'; -import { CoreUserDelegate, CoreUserDelegateService, CoreUserProfileHandlerData } from '@features/user/services/user-delegate'; +import { + CoreUserDelegate, + CoreUserDelegateContext, + CoreUserDelegateService, + CoreUserProfileHandlerData, +} from '@features/user/services/user-delegate'; import { CoreUtils } from '@services/utils/utils'; import { CoreNavigator } from '@services/navigator'; import { CoreCourses } from '@features/courses/services/courses'; @@ -131,7 +136,9 @@ export class CoreUserProfilePage implements OnInit, OnDestroy { // If there's already a subscription, unsubscribe because we'll get a new one. this.subscription?.unsubscribe(); - this.subscription = CoreUserDelegate.getProfileHandlersFor(user, this.courseId).subscribe((handlers) => { + const context = this.courseId ? CoreUserDelegateContext.COURSE : CoreUserDelegateContext.SITE; + + this.subscription = CoreUserDelegate.getProfileHandlersFor(user, context, this.courseId).subscribe((handlers) => { this.actionHandlers = []; this.newPageHandlers = []; this.communicationHandlers = []; @@ -150,7 +157,7 @@ export class CoreUserProfilePage implements OnInit, OnDestroy { } }); - this.isLoadingHandlers = !CoreUserDelegate.areHandlersLoaded(user.id); + this.isLoadingHandlers = !CoreUserDelegate.areHandlersLoaded(user.id, context, this.courseId); }); } catch (error) { @@ -208,7 +215,8 @@ export class CoreUserProfilePage implements OnInit, OnDestroy { return; } - handler.action(event, this.user, this.courseId); + const context = this.courseId ? CoreUserDelegateContext.COURSE : CoreUserDelegateContext.SITE; + handler.action(event, this.user, context, this.courseId); } /** diff --git a/src/core/features/user/services/handlers/profile-mail.ts b/src/core/features/user/services/handlers/profile-mail.ts index 0ba0d60e9..d848f6307 100644 --- a/src/core/features/user/services/handlers/profile-mail.ts +++ b/src/core/features/user/services/handlers/profile-mail.ts @@ -52,7 +52,7 @@ export class CoreUserProfileMailHandlerService implements CoreUserProfileHandler icon: 'mail', title: 'core.user.sendemail', class: 'core-user-profile-mail', - action: (event: Event, user: CoreUserProfile): void => { + action: (event, user): void => { event.preventDefault(); event.stopPropagation(); diff --git a/src/core/features/user/services/user-delegate.ts b/src/core/features/user/services/user-delegate.ts index 6adebcf06..a4c2bf16c 100644 --- a/src/core/features/user/services/user-delegate.ts +++ b/src/core/features/user/services/user-delegate.ts @@ -47,15 +47,17 @@ export interface CoreUserProfileHandler extends CoreDelegateHandler { cacheEnabled?: boolean; /** - * Whether or not the handler is enabled for a course. + * Whether or not the handler is enabled for a context. * - * @param courseId Course ID where to show. + * @param context Context. + * @param contextId Context ID. * @param navOptions Navigation options for the course. * @param admOptions Admin options for the course. * @return Whether or not the handler is enabled for a user. */ - isEnabledForCourse?( - courseId?: number, + isEnabledForContext?( + context: CoreUserDelegateContext, + contextId: number, navOptions?: CoreCourseUserAdminOrNavOptionIndexed, admOptions?: CoreCourseUserAdminOrNavOptionIndexed, ): Promise; @@ -64,22 +66,21 @@ export interface CoreUserProfileHandler extends CoreDelegateHandler { * Whether or not the handler is enabled for a user. * * @param user User object. - * @param courseId Course ID where to show. + * @param context Context. + * @param contextId Context ID. * @return Whether or not the handler is enabled for a user. */ - isEnabledForUser?( - user: CoreUserProfile, - courseId?: number, - ): Promise; + isEnabledForUser?(user: CoreUserProfile, context: CoreUserDelegateContext, contextId: number): Promise; /** * Returns the data needed to render the handler. * * @param user User object. - * @param courseId Course ID where to show. + * @param context Context. + * @param contextId Context ID. * @return Data to be shown. */ - getDisplayData(user: CoreUserProfile, courseId?: number): CoreUserProfileHandlerData; + getDisplayData(user: CoreUserProfile, context: CoreUserDelegateContext, contextId: number): CoreUserProfileHandlerData; } /** @@ -136,9 +137,10 @@ export interface CoreUserProfileHandlerData { * * @param event Click event. * @param user User object. - * @param courseId Course ID being viewed. If not defined, site context. + * @param context Context. + * @param contextId Context ID. */ - action(event: Event, user: CoreUserProfile, courseId?: number): void; + action(event: Event, user: CoreUserProfile, context: CoreUserDelegateContext, contextId?: number): void; } /** @@ -199,24 +201,16 @@ export class CoreUserDelegateService extends CoreDelegate; // Observale to notify the handlers. - }; - } = {}; + protected userHandlers: Record> = {}; constructor() { super('CoreUserDelegate', true); CoreEvents.on(CoreUserDelegateService.UPDATE_HANDLER_EVENT, (data) => { - if (!data || !data.handler || !this.userHandlers[data.userId]) { - return; - } + const handlersData = this.getHandlersData(data.userId, data.context, data.contextId); // Search the handler. - const handler = this.userHandlers[data.userId].handlers.find((userHandler) => userHandler.name == data.handler); + const handler = handlersData.handlers.find((userHandler) => userHandler.name == data.handler); if (!handler) { return; @@ -224,7 +218,7 @@ export class CoreUserDelegateService extends CoreDelegate { @@ -232,31 +226,41 @@ export class CoreUserDelegateService extends CoreDelegate { - this.clearHandlerCache(data.courseId, data.userId); + const context = data.courseId ? CoreUserDelegateContext.COURSE : CoreUserDelegateContext.SITE; + this.clearHandlerCache(data.userId, context, data.courseId); }); } /** - * Check if handlers are loaded. + * Check if handlers are loaded for a certain user and context. * + * @param userId User ID. + * @param context Context. + * @param contextId Context ID. * @return True if handlers are loaded, false otherwise. */ - areHandlersLoaded(userId: number): boolean { - return this.userHandlers[userId]?.loaded; + areHandlersLoaded(userId: number, context: CoreUserDelegateContext, contextId?: number): boolean { + return this.getHandlersData(userId, context, contextId).loaded; } /** * Clear current user handlers. * - * @param userId The user to clear. + * @param userId The user to clear. Undefined for all users. + * @param context Context. + * @param contextId Context ID. */ - clearUserHandlers(userId: number): void { - const userData = this.userHandlers[userId]; + clearUserHandlers(userId?: number, context?: CoreUserDelegateContext, contextId?: number): void { + if (!userId) { + this.userHandlers = {}; + } else if (!context) { + delete this.userHandlers[userId]; + } else { + const handlersData = this.getHandlersData(userId, context, contextId); - if (userData) { - userData.handlers = []; - userData.observable.next([]); - userData.loaded = false; + handlersData.handlers = []; + handlersData.observable.next([]); + handlersData.loaded = false; } } @@ -264,58 +268,65 @@ export class CoreUserDelegateService extends CoreDelegate { - // Initialize the user handlers if it isn't initialized already. - if (!this.userHandlers[user.id]) { - this.userHandlers[user.id] = { - loaded: false, - handlers: [], - observable: new BehaviorSubject([]), - }; - } + getProfileHandlersFor( + user: CoreUserProfile, + context: CoreUserDelegateContext, + contextId?: number, + ): Subject { + this.calculateUserHandlers(user, context, contextId); - this.calculateUserHandlers(user, courseId); - - return this.userHandlers[user.id].observable; + return this.getHandlersData(user.id, context, contextId).observable; } /** * Get the profile handlers for a user. * * @param user The user object. - * @param courseId The course ID. + * @param context Context. + * @param contextId Context ID. * @return Promise resolved when done. */ - protected async calculateUserHandlers(user: CoreUserProfile, courseId?: number): Promise { + protected async calculateUserHandlers( + user: CoreUserProfile, + context: CoreUserDelegateContext, + contextId?: number, + ): Promise { // Get course options. const courses = await CoreCourses.getUserCourses(true); const courseIds = courses.map((course) => course.id); const options = await CoreCourses.getCoursesAdminAndNavOptions(courseIds); - // For backwards compatibility we don't modify the courseId. - const courseIdForOptions = courseId || CoreSites.getCurrentSiteHomeId(); + const courseId = context === CoreUserDelegateContext.COURSE && contextId ? contextId : CoreSites.getCurrentSiteHomeId(); - const navOptions = options.navOptions[courseIdForOptions]; - const admOptions = options.admOptions[courseIdForOptions]; + const navOptions = options.navOptions[courseId]; + const admOptions = options.admOptions[courseId]; - const userData = this.userHandlers[user.id]; - userData.handlers = []; + const handlersData = this.getHandlersData(user.id, context, contextId); + handlersData.handlers = []; await CoreUtils.allPromises(Object.keys(this.enabledHandlers).map(async (name) => { // Checks if the handler is enabled for the user. const handler = this.handlers[name]; try { - const enabled = await this.getAndCacheEnabledForUserFromHandler(handler, user, courseId, navOptions, admOptions); + const enabled = await this.getAndCacheEnabledForUserFromHandler( + handler, + user, + context, + courseId, + navOptions, + admOptions, + ); if (enabled) { - userData.handlers.push({ + handlersData.handlers.push({ name: name, - data: handler.getDisplayData(user, courseId), + data: handler.getDisplayData(user, context, courseId), priority: handler.priority || 0, type: handler.type || CoreUserDelegateService.TYPE_NEW_PAGE, }); @@ -326,9 +337,9 @@ export class CoreUserDelegateService extends CoreDelegate b.priority! - a.priority!); - userData.loaded = true; - userData.observable.next(userData.handlers); + handlersData.handlers.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0)); + handlersData.loaded = true; + handlersData.observable.next(handlersData.handlers); } /** @@ -336,7 +347,8 @@ export class CoreUserDelegateService extends CoreDelegate { - if (handler.isEnabledForCourse) { - const enabledOnCourse = await handler.isEnabledForCourse(courseId, navOptions, admOptions); + if (handler.isEnabledForContext) { + const enabledOnCourse = await handler.isEnabledForContext(context, contextId, navOptions, admOptions); if (!enabledOnCourse) { // If is not enabled in the course, is not enabled for the user. @@ -364,14 +377,14 @@ export class CoreUserDelegateService extends CoreDelegate { const cache = this.enabledForUserCache[name]; @@ -412,25 +426,81 @@ export class CoreUserDelegateService extends CoreDelegate([]), + }; + } + + return this.userHandlers[userId][contextKey]; } } export const CoreUserDelegate = makeSingleton(CoreUserDelegateService); +/** + * Handlers data for a user and context. + */ +type CoreUserDelegateHandlersData = { + loaded: boolean; // Whether the handlers are loaded. + handlers: CoreUserProfileHandlerToDisplay[]; // List of handlers. + observable: Subject; // Observable to notify the handlers. +}; + +/** + * Context levels enumeration. + */ +export enum CoreUserDelegateContext { + SITE = 'site', + COURSE = 'course', + USER_MENU = 'user_menu', +} + /** * Data passed to UPDATE_HANDLER_EVENT event. */ export type CoreUserUpdateHandlerData = { handler: string; // Name of the handler. userId: number; // User affected. + context: CoreUserDelegateContext; // Context affected. + contextId?: number; // ID related to the context. data: Record; // Data to set to the handler. }; diff --git a/upgrade.txt b/upgrade.txt index 11db21eef..79ccced1d 100644 --- a/upgrade.txt +++ b/upgrade.txt @@ -11,6 +11,10 @@ information provided here is intended especially for developers. - CoreCourse.getModuleBasicInfoByInstance and CoreCourse.getModuleBasicInfo have been modified to accept an "options" parameter instead of only siteId. - The function CoreFilepool.isFileDownloadingByUrl now returns Promise instead of relying on resolve/reject. - downloadEnabled input has been removed from CoreBlockSideBlocksComponent, CoreCourseFormatComponent, CoreCourseFormatSingleActivityComponent and CoreCourseModuleComponent. +- There were several breaking changes done in CoreUserDelegate and its handlers: + The function CoreUserDelegate.getProfileHandlersFor must now receive a context + contextId instead of a courseId. + The user handler function isEnabledForCourse is now called isEnabledForContext and receives a context + contextId instead of a courseId. + Some user handler's functions have also changed to accept context + contextId instead of a courseId: isEnabledForUser, getDisplayData, action. === 3.9.5 ===