diff --git a/src/addons/competency/competency-lazy.module.ts b/src/addons/competency/competency-lazy.module.ts index 0c27d43b1..09dce93a7 100644 --- a/src/addons/competency/competency-lazy.module.ts +++ b/src/addons/competency/competency-lazy.module.ts @@ -18,11 +18,11 @@ import { RouterModule, Routes } from '@angular/router'; import { conditionalRoutes } from '@/app/app-routing.module'; import { CoreScreen } from '@services/screen'; import { CoreSharedModule } from '@/core/shared.module'; -import { AddonCompetencyPlanPage } from './pages/plan/plan.page'; -import { AddonCompetencyPlanListPage } from './pages/planlist/planlist.page'; -import { AddonCompetencyCompetenciesPage } from './pages/competencies/competencies.page'; -import { AddonCompetencyCompetencyPage } from './pages/competency/competency.page'; -import { AddonCompetencyCompetencySummaryPage } from './pages/competencysummary/competencysummary.page'; +import { AddonCompetencyPlanPage } from './pages/plan/plan'; +import { AddonCompetencyPlanListPage } from './pages/planlist/planlist'; +import { AddonCompetencyCompetenciesPage } from './pages/competencies/competencies'; +import { AddonCompetencyCompetencyPage } from './pages/competency/competency'; +import { AddonCompetencyCompetencySummaryPage } from './pages/competencysummary/competencysummary'; import { AddonCompetencyCourseCompetenciesPage } from './pages/coursecompetencies/coursecompetencies.page'; import { AddonCompetencyCourseCompetenciesPageModule } from './pages/coursecompetencies/coursecompetencies.module'; @@ -33,7 +33,7 @@ const mobileRoutes: Routes = [ component: AddonCompetencyPlanListPage, }, { - path: 'competencies/', + path: 'competencies', component: AddonCompetencyCompetenciesPage, }, { diff --git a/src/addons/competency/pages/competencies/competencies.page.ts b/src/addons/competency/pages/competencies/competencies.ts similarity index 97% rename from src/addons/competency/pages/competencies/competencies.page.ts rename to src/addons/competency/pages/competencies/competencies.ts index 2d817fd4a..399c5371c 100644 --- a/src/addons/competency/pages/competencies/competencies.page.ts +++ b/src/addons/competency/pages/competencies/competencies.ts @@ -91,8 +91,8 @@ export class AddonCompetencyCompetenciesPage implements AfterViewInit, OnDestroy } else { throw null; } - } catch (message) { - CoreDomUtils.showErrorModalDefault(message, 'Error getting competencies data.'); + } catch (error) { + CoreDomUtils.showErrorModalDefault(error, 'Error getting competencies data.'); } } diff --git a/src/addons/competency/pages/competency/competency.html b/src/addons/competency/pages/competency/competency.html index 48e84c110..c565defd1 100644 --- a/src/addons/competency/pages/competency/competency.html +++ b/src/addons/competency/pages/competency/competency.html @@ -4,7 +4,7 @@ - {{ competency!.competency.competency.shortname }} {{ competency.competency.competency.idnumber }} + {{ competency.competency.competency.shortname }} {{ competency.competency.competency.idnumber }} @@ -16,14 +16,14 @@ -

{{ user!.fullname }}

+

{{ user.fullname }}

- + - @@ -31,23 +31,23 @@ {{ 'addon.competency.path' | translate }} - - {{ competency!.competency.comppath.framework.name }} + + {{ competency.competency.comppath.framework.name }} - - {{ competency!.competency.comppath.framework.name }} + + {{ competency.competency.comppath.framework.name }}  /  - - + {{ ancestor.name }} - {{ ancestor.name }} + {{ ancestor.name }}  /  @@ -55,11 +55,11 @@ {{ 'addon.competency.crossreferencedcompetencies' | translate }}: -
+
{{ 'addon.competency.nocrossreferencedcompetencies' | translate }}
-
-

+

+

{{ relatedcomp.shortname }} - {{ relatedcomp.idnumber }} @@ -70,7 +70,7 @@ {{ 'addon.competency.activities' | translate }} -

+

{{ 'addon.competency.noactivities' | translate }}

- + {{ 'addon.competency.reviewstatus' | translate }} - {{ competency!.usercompetency!.statusname }} + {{ competency.usercompetency!.statusname }} {{ 'addon.competency.proficient' | translate }} - + {{ 'core.yes' | translate }} - + {{ 'core.no' | translate }} @@ -107,22 +107,22 @@ {{ 'addon.competency.rating' | translate }} - {{ userCompetency!.gradename }} + {{ userCompetency.gradename }}

{{ 'addon.competency.evidence' | translate }}

-

+

{{ 'addon.competency.noevidence' | translate }}

- - + -

{{ evidence.actionuser!.fullname }}

+

{{ evidence.actionuser.fullname }}

{{ evidence.timemodified * 1000 | coreFormatDate }}

diff --git a/src/addons/competency/pages/competency/competency.page.ts b/src/addons/competency/pages/competency/competency.ts similarity index 99% rename from src/addons/competency/pages/competency/competency.page.ts rename to src/addons/competency/pages/competency/competency.ts index 919281cc4..e4ebe432e 100644 --- a/src/addons/competency/pages/competency/competency.page.ts +++ b/src/addons/competency/pages/competency/competency.ts @@ -35,7 +35,7 @@ import { CoreUtils } from '@services/utils/utils'; import { AddonCompetencyMainMenuHandlerService } from '@addons/competency/services/handlers/mainmenu'; /** - * Page that displays a learning plan. + * Page that displays the competency information. */ @Component({ selector: 'page-addon-competency-competency', diff --git a/src/addons/competency/pages/competencysummary/competencysummary.html b/src/addons/competency/pages/competencysummary/competencysummary.html index 82bd824a2..df05f5428 100644 --- a/src/addons/competency/pages/competencysummary/competencysummary.html +++ b/src/addons/competency/pages/competencysummary/competencysummary.html @@ -4,7 +4,7 @@ - {{ competency!.competency.shortname }} {{ competency!.competency.idnumber }} + {{ competency.competency.shortname }} {{ competency.competency.idnumber }} @@ -14,9 +14,9 @@ - + - @@ -24,8 +24,8 @@ {{ 'addon.competency.path' | translate }} - {{ competency!.comppath.framework.name }} - + {{ competency.comppath.framework.name }} +  / {{ ancestor.name }} diff --git a/src/addons/competency/pages/competencysummary/competencysummary.page.ts b/src/addons/competency/pages/competencysummary/competencysummary.ts similarity index 98% rename from src/addons/competency/pages/competencysummary/competencysummary.page.ts rename to src/addons/competency/pages/competencysummary/competencysummary.ts index 4a75f8b3a..451d85553 100644 --- a/src/addons/competency/pages/competencysummary/competencysummary.page.ts +++ b/src/addons/competency/pages/competencysummary/competencysummary.ts @@ -22,7 +22,7 @@ import { CoreUtils } from '@services/utils/utils'; import { AddonCompetencyMainMenuHandlerService } from '@addons/competency/services/handlers/mainmenu'; /** - * Page that displays a learning plan. + * Page that displays the competency summary. */ @Component({ selector: 'page-addon-competency-competency-summary', diff --git a/src/addons/competency/pages/coursecompetencies/coursecompetencies.html b/src/addons/competency/pages/coursecompetencies/coursecompetencies.html index ce4a887a6..244afad0f 100644 --- a/src/addons/competency/pages/coursecompetencies/coursecompetencies.html +++ b/src/addons/competency/pages/coursecompetencies/coursecompetencies.html @@ -11,27 +11,27 @@ - - - + + + {{ 'addon.competency.coursecompetencyratingsarepushedtouserplans' | translate }} - + {{ 'addon.competency.coursecompetencyratingsarenotpushedtouserplans' | translate }} - + {{ 'addon.competency.xcompetenciesproficientoutofyincourse' | translate: {$a: - {x: competencies!.statistics.proficientcompetencycount, y: competencies!.statistics.competencycount} } }} - + {x: competencies.statistics.proficientcompetencycount, y: competencies.statistics.competencycount} } }} + + *ngIf="competencies.statistics.canmanagecoursecompetencies && competencies.statistics.leastproficientcount > 0"> {{ 'addon.competency.competenciesmostoftennotproficientincourse' | translate }}: -

+

{{ comp.shortname }} - {{ comp.idnumber }} @@ -40,29 +40,29 @@ -

+

{{ 'addon.competency.coursecompetencies' | translate }}

-

{{ user!.fullname }}

+

{{ user.fullname }}

-
- +

{{competency.competency.shortname}} {{competency.competency.idnumber}}

- - {{ competency.usercompetencycourse!.gradename }} + + {{ competency.usercompetencycourse.gradename }}
@@ -92,7 +92,7 @@  / 
-
+
{{ 'addon.competency.uponcoursecompletion' | translate }} {{ ruleoutcome.text }} diff --git a/src/addons/competency/pages/plan/plan.html b/src/addons/competency/pages/plan/plan.html index 41d1f3ba7..9b207a7f6 100644 --- a/src/addons/competency/pages/plan/plan.html +++ b/src/addons/competency/pages/plan/plan.html @@ -3,7 +3,7 @@ - {{plan!.plan.name}} + {{plan.plan.name}} @@ -15,27 +15,27 @@ -

{{ user!.fullname }}

+

{{ user.fullname }}

- + - +

- {{ 'addon.competency.status' | translate }}: {{ plan!.plan.statusname }} + {{ 'addon.competency.status' | translate }}: {{ plan.plan.statusname }}

- +

{{ 'addon.competency.duedate' | translate }}: @@ -43,10 +43,10 @@

- +

- {{ 'addon.competency.template' | translate }}: {{ plan!.plan.template!.shortname }} + {{ 'addon.competency.template' | translate }}: {{ plan.plan.template.shortname }}

diff --git a/src/addons/competency/pages/plan/plan.page.ts b/src/addons/competency/pages/plan/plan.ts similarity index 100% rename from src/addons/competency/pages/plan/plan.page.ts rename to src/addons/competency/pages/plan/plan.ts diff --git a/src/addons/competency/pages/planlist/planlist.page.ts b/src/addons/competency/pages/planlist/planlist.ts similarity index 100% rename from src/addons/competency/pages/planlist/planlist.page.ts rename to src/addons/competency/pages/planlist/planlist.ts diff --git a/src/addons/competency/services/competency.ts b/src/addons/competency/services/competency.ts index 666be85a2..802c7f925 100644 --- a/src/addons/competency/services/competency.ts +++ b/src/addons/competency/services/competency.ts @@ -56,6 +56,41 @@ export class AddonCompetencyProvider { site.isFeatureDisabled('CoreUserDelegate_AddonCompetency'); } + /** + * Returns whether current user can see another user competencies in a course. + * + * @param courseId Course ID. + * @param userId User ID. + * @param siteId Site ID. If not defined, current site. + * @return Promise resolved with boolean: whether the user can view the competencies. + */ + async canViewUserCompetenciesInCourse(courseId: number, userId?: number, siteId?: string): Promise { + if (!CoreSites.isLoggedIn()) { + return false; + } + + try { + const response = await this.getCourseCompetenciesPage(courseId, siteId); + + if (!response.competencies.length) { + // No competencies. + return false; + } + + if (!userId || userId == CoreSites.getCurrentSiteUserId()) { + // Current user. + return true; + } + + // Check if current user can view any competency of the user. + await this.getCompetencyInCourse(courseId, response.competencies[0].competency.id, userId, siteId); + + return true; + } catch { + return false; + } + } + /** * Get cache key for user learning plans data WS calls. * @@ -290,7 +325,7 @@ export class AddonCompetencyProvider { } /** - * Get all competencies in a course. + * Get all competencies in a course for a certain user. * * @param courseId ID of the course. * @param userId ID of the user. @@ -304,6 +339,38 @@ export class AddonCompetencyProvider { siteId?: string, ignoreCache = false, ): Promise { + + const courseCompetencies = await this.getCourseCompetenciesPage(courseId, siteId, ignoreCache); + + if (!userId || userId == CoreSites.getCurrentSiteUserId()) { + return courseCompetencies; + } + + const userCompetenciesSumaries: AddonCompetencyDataForUserCompetencySummaryInCourseWSResponse[] = + await Promise.all(courseCompetencies.competencies.map((competency) => + this.getCompetencyInCourse(courseId, competency.competency.id, userId, siteId))); + + userCompetenciesSumaries.forEach((userCompetenciesSumary, index) => { + courseCompetencies.competencies[index].usercompetencycourse = + userCompetenciesSumary.usercompetencysummary.usercompetencycourse; + }); + + return courseCompetencies; + } + + /** + * Get all competencies in a course. + * + * @param courseId ID of the course. + * @param siteId Site ID. If not defined, current site. + * @param ignoreCache True if it should ignore cached data (it will always fail in offline or server down). + * @return Promise to be resolved when the course competencies are retrieved. + */ + async getCourseCompetenciesPage( + courseId: number, + siteId?: string, + ignoreCache = false, + ): Promise { const site = await CoreSites.getSite(siteId); const params: AddonCompetencyDataForCourseCompetenciesPageWSParams = { @@ -320,26 +387,11 @@ export class AddonCompetencyProvider { preSets.emergencyCache = false; } - const courseCompetencies = await site.read( + return site.read( 'tool_lp_data_for_course_competencies_page', params, preSets, ); - - if (!userId || userId == CoreSites.getCurrentSiteUserId()) { - return courseCompetencies; - } - - const userCompetenciesSumaries: AddonCompetencyDataForUserCompetencySummaryInCourseWSResponse[] = - await Promise.all(courseCompetencies.competencies.map((competency) => - this.getCompetencyInCourse(courseId, competency.competency.id, userId, siteId))); - - userCompetenciesSumaries.forEach((userCompetenciesSumary, index) => { - courseCompetencies.competencies[index].usercompetencycourse = - userCompetenciesSumary.usercompetencysummary.usercompetencycourse; - }); - - return courseCompetencies; } /** diff --git a/src/addons/competency/services/handlers/course-option.ts b/src/addons/competency/services/handlers/course-option.ts index e70fe28a4..e5f1e5364 100644 --- a/src/addons/competency/services/handlers/course-option.ts +++ b/src/addons/competency/services/handlers/course-option.ts @@ -98,39 +98,41 @@ export class AddonCompetencyCourseOptionHandlerService implements CoreCourseOpti // Get the competencies in the course. const competencies = await AddonCompetency.getCourseCompetencies(course.id, undefined, undefined, true); + if (!competencies || !competencies.competencies) { + return; + } + const promises: Promise[] = []; // Prefetch all the competencies. - if (competencies && competencies.competencies) { - competencies.competencies.forEach((competency) => { - promises.push(AddonCompetency.getCompetencyInCourse( - course.id, - competency.competency.id, - undefined, - undefined, - true, - )); + competencies.competencies.forEach((competency) => { + promises.push(AddonCompetency.getCompetencyInCourse( + course.id, + competency.competency.id, + undefined, + undefined, + true, + )); - promises.push(AddonCompetency.getCompetencySummary( - competency.competency.id, - undefined, - undefined, - true, - )); + promises.push(AddonCompetency.getCompetencySummary( + competency.competency.id, + undefined, + undefined, + true, + )); - if (competency.coursemodules) { - competency.coursemodules.forEach((module) => { - promises.push(CoreFilterHelper.getFilters(ContextLevel.MODULE, module.id, { courseId: course.id })); - }); - } + if (competency.coursemodules) { + competency.coursemodules.forEach((module) => { + promises.push(CoreFilterHelper.getFilters(ContextLevel.MODULE, module.id, { courseId: course.id })); + }); + } - if (competency.plans) { - competency.plans.forEach((plan) => { - promises.push(CoreFilterHelper.getFilters(ContextLevel.USER, plan.userid)); - }); - } - }); - } + if (competency.plans) { + competency.plans.forEach((plan) => { + promises.push(CoreFilterHelper.getFilters(ContextLevel.USER, plan.userid)); + }); + } + }); await Promise.all(promises); } diff --git a/src/addons/competency/services/handlers/push-click.ts b/src/addons/competency/services/handlers/push-click.ts index 0adf67f70..7966bbf66 100644 --- a/src/addons/competency/services/handlers/push-click.ts +++ b/src/addons/competency/services/handlers/push-click.ts @@ -54,7 +54,7 @@ export class AddonCompetencyPushClickHandlerService implements CorePushNotificat // Open the learning plan. const planId = Number(contextUrlParams.id); - await CoreUtils.ignoreErrors(AddonCompetency.invalidateLearningPlan(planId, notification.site)); + await CoreUtils.ignoreErrors(AddonCompetency.invalidateLearningPlan(planId, notification.site)); await CoreNavigator.navigateToSitePath('/' + AddonCompetencyMainMenuHandlerService.PAGE_NAME + '/' + planId, { siteId: notification.site, diff --git a/src/addons/competency/services/handlers/user.ts b/src/addons/competency/services/handlers/user.ts index 54805ff82..1500085ee 100644 --- a/src/addons/competency/services/handlers/user.ts +++ b/src/addons/competency/services/handlers/user.ts @@ -44,9 +44,7 @@ export class AddonCompetencyUserHandlerService implements CoreUserProfileHandler async isEnabledForUser(user: CoreUserProfile, courseId?: number): Promise { try { if (courseId) { - const response = await AddonCompetency.getCourseCompetencies(courseId, user.id); - - return response.competencies.length > 0; + return AddonCompetency.canViewUserCompetenciesInCourse(courseId, user.id); } else { const plans = await AddonCompetency.getLearningPlans(user.id);