From bb7e1217a9e67b1067e32983b2528512ade7fc3f Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 20 Mar 2019 11:32:19 +0100 Subject: [PATCH] MOBILE-2921 competency: Support push clicks and link clicks --- src/addon/competency/competency.module.ts | 25 ++++- .../providers/competency-link-handler.ts | 74 +++++++++++++ src/addon/competency/providers/competency.ts | 14 +++ .../competency/providers/plan-link-handler.ts | 68 ++++++++++++ .../providers/plans-link-handler.ts | 69 ++++++++++++ .../providers/push-click-handler.ts | 100 ++++++++++++++++++ .../providers/user-competency-link-handler.ts | 68 ++++++++++++ 7 files changed, 416 insertions(+), 2 deletions(-) create mode 100644 src/addon/competency/providers/competency-link-handler.ts create mode 100644 src/addon/competency/providers/plan-link-handler.ts create mode 100644 src/addon/competency/providers/plans-link-handler.ts create mode 100644 src/addon/competency/providers/push-click-handler.ts create mode 100644 src/addon/competency/providers/user-competency-link-handler.ts diff --git a/src/addon/competency/competency.module.ts b/src/addon/competency/competency.module.ts index c321e8a20..b7aecb757 100644 --- a/src/addon/competency/competency.module.ts +++ b/src/addon/competency/competency.module.ts @@ -18,10 +18,17 @@ import { AddonCompetencyHelperProvider } from './providers/helper'; import { AddonCompetencyCourseOptionHandler } from './providers/course-option-handler'; import { AddonCompetencyMainMenuHandler } from './providers/mainmenu-handler'; import { AddonCompetencyUserHandler } from './providers/user-handler'; +import { AddonCompetencyCompetencyLinkHandler } from './providers/competency-link-handler'; +import { AddonCompetencyPlanLinkHandler } from './providers/plan-link-handler'; +import { AddonCompetencyPlansLinkHandler } from './providers/plans-link-handler'; +import { AddonCompetencyUserCompetencyLinkHandler } from './providers/user-competency-link-handler'; +import { AddonCompetencyPushClickHandler } from './providers/push-click-handler'; import { AddonCompetencyComponentsModule } from './components/components.module'; import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate'; import { CoreMainMenuDelegate } from '@core/mainmenu/providers/delegate'; import { CoreUserDelegate } from '@core/user/providers/user-delegate'; +import { CoreContentLinksDelegate } from '@core/contentlinks/providers/delegate'; +import { CorePushNotificationsDelegate } from '@core/pushnotifications/providers/delegate'; // List of providers (without handlers). export const ADDON_COMPETENCY_PROVIDERS: any[] = [ @@ -40,16 +47,30 @@ export const ADDON_COMPETENCY_PROVIDERS: any[] = [ AddonCompetencyHelperProvider, AddonCompetencyCourseOptionHandler, AddonCompetencyMainMenuHandler, - AddonCompetencyUserHandler + AddonCompetencyUserHandler, + AddonCompetencyCompetencyLinkHandler, + AddonCompetencyPlanLinkHandler, + AddonCompetencyPlansLinkHandler, + AddonCompetencyUserCompetencyLinkHandler, + AddonCompetencyPushClickHandler ] }) export class AddonCompetencyModule { constructor(mainMenuDelegate: CoreMainMenuDelegate, mainMenuHandler: AddonCompetencyMainMenuHandler, courseOptionsDelegate: CoreCourseOptionsDelegate, courseOptionHandler: AddonCompetencyCourseOptionHandler, - userDelegate: CoreUserDelegate, userHandler: AddonCompetencyUserHandler) { + userDelegate: CoreUserDelegate, userHandler: AddonCompetencyUserHandler, + contentLinksDelegate: CoreContentLinksDelegate, competencyLinkHandler: AddonCompetencyCompetencyLinkHandler, + planLinkHandler: AddonCompetencyPlanLinkHandler, plansLinkHandler: AddonCompetencyPlansLinkHandler, + userComptencyLinkHandler: AddonCompetencyUserCompetencyLinkHandler, + pushNotificationsDelegate: CorePushNotificationsDelegate, pushClickHandler: AddonCompetencyPushClickHandler) { mainMenuDelegate.registerHandler(mainMenuHandler); courseOptionsDelegate.registerHandler(courseOptionHandler); userDelegate.registerHandler(userHandler); + contentLinksDelegate.registerHandler(competencyLinkHandler); + contentLinksDelegate.registerHandler(planLinkHandler); + contentLinksDelegate.registerHandler(plansLinkHandler); + contentLinksDelegate.registerHandler(userComptencyLinkHandler); + pushNotificationsDelegate.registerClickHandler(pushClickHandler); } } diff --git a/src/addon/competency/providers/competency-link-handler.ts b/src/addon/competency/providers/competency-link-handler.ts new file mode 100644 index 000000000..a85c8d1bb --- /dev/null +++ b/src/addon/competency/providers/competency-link-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 } from '@angular/core'; +import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler'; +import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate'; +import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper'; +import { AddonCompetencyProvider } from './competency'; + +/** + * Handler to treat links to a competency in a plan or in a course. + */ +@Injectable() +export class AddonCompetencyCompetencyLinkHandler extends CoreContentLinksHandlerBase { + name = 'AddonCompetencyCompetencyLinkHandler'; + pattern = /\/admin\/tool\/lp\/(user_competency_in_course|user_competency_in_plan)\.php/; + + constructor(private linkHelper: CoreContentLinksHelperProvider, private competencyProvider: AddonCompetencyProvider) { + super(); + } + + /** + * Get the list of actions for a link (url). + * + * @param {string[]} siteIds List of sites the URL belongs to. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {CoreContentLinksAction[]|Promise} List of (or promise resolved with list of) actions. + */ + getActions(siteIds: string[], url: string, params: any, courseId?: number): + CoreContentLinksAction[] | Promise { + courseId = courseId || params.courseid || params.cid; + + return [{ + action: (siteId, navCtrl?): void => { + this.linkHelper.goInSite(navCtrl, 'AddonCompetencyCompetencyPage', { + planId: params.planid, + competencyId: params.competencyid, + courseId: courseId, + userId: params.userid + }, siteId); + } + }]; + } + + /** + * Check if the handler is enabled for a certain site (site + user) and a URL. + * If not defined, defaults to true. + * + * @param {string} siteId The site ID. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {boolean|Promise} Whether the handler is enabled for the URL and site. + */ + isEnabled(siteId: string, url: string, params: any, courseId?: number): boolean | Promise { + // Handler is disabled if all competency features are disabled. + return this.competencyProvider.allCompetenciesDisabled(siteId).then((disabled) => { + return !disabled; + }); + } +} diff --git a/src/addon/competency/providers/competency.ts b/src/addon/competency/providers/competency.ts index 28fae6304..455c2fd93 100644 --- a/src/addon/competency/providers/competency.ts +++ b/src/addon/competency/providers/competency.ts @@ -42,6 +42,20 @@ export class AddonCompetencyProvider { this.logger = loggerProvider.getInstance('AddonCompetencyProvider'); } + /** + * Check if all competencies features are disabled. + * + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved with boolean: whether all competency features are disabled. + */ + allCompetenciesDisabled(siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + return site.isFeatureDisabled('CoreMainMenuDelegate_AddonCompetency') && + site.isFeatureDisabled('CoreCourseOptionsDelegate_AddonCompetency') && + site.isFeatureDisabled('CoreUserDelegate_AddonCompetency'); + }); + } + /** * Get cache key for user learning plans data WS calls. * diff --git a/src/addon/competency/providers/plan-link-handler.ts b/src/addon/competency/providers/plan-link-handler.ts new file mode 100644 index 000000000..1e20c5fe7 --- /dev/null +++ b/src/addon/competency/providers/plan-link-handler.ts @@ -0,0 +1,68 @@ +// (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 } from '@angular/core'; +import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler'; +import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate'; +import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper'; +import { AddonCompetencyProvider } from './competency'; + +/** + * Handler to treat links to a plan. + */ +@Injectable() +export class AddonCompetencyPlanLinkHandler extends CoreContentLinksHandlerBase { + name = 'AddonCompetencyPlanLinkHandler'; + pattern = /\/admin\/tool\/lp\/plan\.php.*([\?\&]id=\d+)/; + + constructor(private linkHelper: CoreContentLinksHelperProvider, private competencyProvider: AddonCompetencyProvider) { + super(); + } + + /** + * Get the list of actions for a link (url). + * + * @param {string[]} siteIds List of sites the URL belongs to. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {CoreContentLinksAction[]|Promise} List of (or promise resolved with list of) actions. + */ + getActions(siteIds: string[], url: string, params: any, courseId?: number): + CoreContentLinksAction[] | Promise { + + return [{ + action: (siteId, navCtrl?): void => { + this.linkHelper.goInSite(navCtrl, 'AddonCompetencyPlanPage', { planId: params.id }, siteId); + } + }]; + } + + /** + * Check if the handler is enabled for a certain site (site + user) and a URL. + * If not defined, defaults to true. + * + * @param {string} siteId The site ID. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {boolean|Promise} Whether the handler is enabled for the URL and site. + */ + isEnabled(siteId: string, url: string, params: any, courseId?: number): boolean | Promise { + // Handler is disabled if all competency features are disabled. + return this.competencyProvider.allCompetenciesDisabled(siteId).then((disabled) => { + return !disabled; + }); + } +} diff --git a/src/addon/competency/providers/plans-link-handler.ts b/src/addon/competency/providers/plans-link-handler.ts new file mode 100644 index 000000000..a99280f3a --- /dev/null +++ b/src/addon/competency/providers/plans-link-handler.ts @@ -0,0 +1,69 @@ +// (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 } from '@angular/core'; +import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler'; +import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate'; +import { CoreLoginHelperProvider } from '@core/login/providers/helper'; +import { AddonCompetencyProvider } from './competency'; + +/** + * Handler to treat links to user plans. + */ +@Injectable() +export class AddonCompetencyPlansLinkHandler extends CoreContentLinksHandlerBase { + name = 'AddonCompetencyPlansLinkHandler'; + pattern = /\/admin\/tool\/lp\/plans\.php/; + + constructor(private loginHelper: CoreLoginHelperProvider, private competencyProvider: AddonCompetencyProvider) { + super(); + } + + /** + * Get the list of actions for a link (url). + * + * @param {string[]} siteIds List of sites the URL belongs to. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {CoreContentLinksAction[]|Promise} List of (or promise resolved with list of) actions. + */ + getActions(siteIds: string[], url: string, params: any, courseId?: number): + CoreContentLinksAction[] | Promise { + + return [{ + action: (siteId, navCtrl?): void => { + // Always use redirect to make it the new history root (to avoid "loops" in history). + this.loginHelper.redirect('AddonCompetencyPlanListPage', { userId: params.userid }, siteId); + } + }]; + } + + /** + * Check if the handler is enabled for a certain site (site + user) and a URL. + * If not defined, defaults to true. + * + * @param {string} siteId The site ID. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {boolean|Promise} Whether the handler is enabled for the URL and site. + */ + isEnabled(siteId: string, url: string, params: any, courseId?: number): boolean | Promise { + // Handler is disabled if all competency features are disabled. + return this.competencyProvider.allCompetenciesDisabled(siteId).then((disabled) => { + return !disabled; + }); + } +} diff --git a/src/addon/competency/providers/push-click-handler.ts b/src/addon/competency/providers/push-click-handler.ts new file mode 100644 index 000000000..eca567205 --- /dev/null +++ b/src/addon/competency/providers/push-click-handler.ts @@ -0,0 +1,100 @@ +// (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 } from '@angular/core'; +import { CoreUrlUtilsProvider } from '@providers/utils/url'; +import { CoreUtilsProvider } from '@providers/utils/utils'; +import { CorePushNotificationsClickHandler } from '@core/pushnotifications/providers/delegate'; +import { CoreLoginHelperProvider } from '@core/login/providers/helper'; +import { AddonCompetencyProvider } from './competency'; + +/** + * Handler for competencies push notifications clicks. + */ +@Injectable() +export class AddonCompetencyPushClickHandler implements CorePushNotificationsClickHandler { + name = 'AddonCompetencyPushClickHandler'; + priority = 200; + + constructor(private utils: CoreUtilsProvider, private urlUtils: CoreUrlUtilsProvider, + private competencyProvider: AddonCompetencyProvider, private loginHelper: CoreLoginHelperProvider) {} + + /** + * Check if a notification click is handled by this handler. + * + * @param {any} notification The notification to check. + * @return {boolean} Whether the notification click is handled by this handler + */ + handles(notification: any): boolean | Promise { + if (this.utils.isTrueOrOne(notification.notif) && notification.moodlecomponent == 'moodle' && + (notification.name == 'competencyplancomment' || notification.name == 'competencyusercompcomment')) { + // If all competency features are disabled, don't handle the click. + return this.competencyProvider.allCompetenciesDisabled(notification.site).then((disabled) => { + return !disabled; + }); + } + + return false; + } + + /** + * Handle the notification click. + * + * @param {any} notification The notification to check. + * @return {Promise} Promise resolved when done. + */ + handleClick(notification: any): Promise { + const contextUrlParams = this.urlUtils.extractUrlParams(notification.contexturl); + + if (notification.name == 'competencyplancomment') { + // Open the learning plan. + const planId = Number(contextUrlParams.id); + + return this.competencyProvider.invalidateLearningPlan(planId, notification.site).catch(() => { + // Ignore errors. + }).then(() => { + return this.loginHelper.redirect('AddonCompetencyPlanPage', { planId: planId }, notification.site); + }); + } else { + + if (notification.contexturl && notification.contexturl.indexOf('user_competency_in_plan.php') != -1) { + // Open the competency. + const courseId = Number(notification.course), + competencyId = Number(contextUrlParams.competencyid), + planId = Number(contextUrlParams.planid), + userId = Number(contextUrlParams.userid); + + return this.competencyProvider.invalidateCompetencyInPlan(planId, competencyId, notification.site).catch(() => { + // Ignore errors. + }).then(() => { + return this.loginHelper.redirect('AddonCompetencyCompetencyPage', { + planId: planId, + competencyId: competencyId, + courseId: courseId, + userId: userId + }, notification.site); + }); + } else { + // Open the list of plans. + const userId = Number(contextUrlParams.userid); + + return this.competencyProvider.invalidateLearningPlans(userId, notification.site).catch(() => { + // Ignore errors. + }).then(() => { + return this.loginHelper.redirect('AddonCompetencyPlanListPage', { userId: userId }, notification.site); + }); + } + } + } +} diff --git a/src/addon/competency/providers/user-competency-link-handler.ts b/src/addon/competency/providers/user-competency-link-handler.ts new file mode 100644 index 000000000..06cee4f90 --- /dev/null +++ b/src/addon/competency/providers/user-competency-link-handler.ts @@ -0,0 +1,68 @@ +// (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 } from '@angular/core'; +import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler'; +import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate'; +import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper'; +import { AddonCompetencyProvider } from './competency'; + +/** + * Handler to treat links to a usr competency. + */ +@Injectable() +export class AddonCompetencyUserCompetencyLinkHandler extends CoreContentLinksHandlerBase { + name = 'AddonCompetencyUserCompetencyLinkHandler'; + pattern = /\/admin\/tool\/lp\/user_competency\.php.*([\?\&]id=\d+)/; + + constructor(private linkHelper: CoreContentLinksHelperProvider, private competencyProvider: AddonCompetencyProvider) { + super(); + } + + /** + * Get the list of actions for a link (url). + * + * @param {string[]} siteIds List of sites the URL belongs to. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {CoreContentLinksAction[]|Promise} List of (or promise resolved with list of) actions. + */ + getActions(siteIds: string[], url: string, params: any, courseId?: number): + CoreContentLinksAction[] | Promise { + + return [{ + action: (siteId, navCtrl?): void => { + this.linkHelper.goInSite(navCtrl, 'AddonCompetencyCompetencySummaryPage', { competencyId: params.id }, siteId); + } + }]; + } + + /** + * Check if the handler is enabled for a certain site (site + user) and a URL. + * If not defined, defaults to true. + * + * @param {string} siteId The site ID. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {boolean|Promise} Whether the handler is enabled for the URL and site. + */ + isEnabled(siteId: string, url: string, params: any, courseId?: number): boolean | Promise { + // Handler is disabled if all competency features are disabled. + return this.competencyProvider.allCompetenciesDisabled(siteId).then((disabled) => { + return !disabled; + }); + } +}