forked from EVOgeek/Vmeda.Online
		
	MOBILE-3934 competency: Add swipe navigation
This commit is contained in:
		
							parent
							
								
									c549e733fb
								
							
						
					
					
						commit
						d2b716da8d
					
				@ -0,0 +1,97 @@
 | 
			
		||||
// (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 { CoreRoutedItemsManagerSource } from '@classes/items-management/routed-items-manager-source';
 | 
			
		||||
import { CoreUserProfile } from '@features/user/services/user';
 | 
			
		||||
import { CoreUtils } from '@services/utils/utils';
 | 
			
		||||
import {
 | 
			
		||||
    AddonCompetency,
 | 
			
		||||
    AddonCompetencyDataForCourseCompetenciesPageCompetency,
 | 
			
		||||
    AddonCompetencyDataForCourseCompetenciesPageWSResponse,
 | 
			
		||||
} from '../services/competency';
 | 
			
		||||
import { AddonCompetencyHelper } from '../services/competency-helper';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides a collection of course competencies.
 | 
			
		||||
 */
 | 
			
		||||
export class AddonCompetencyCourseCompetenciesSource
 | 
			
		||||
    extends CoreRoutedItemsManagerSource<AddonCompetencyDataForCourseCompetenciesPageCompetency> {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    static getSourceId(courseId: number, userId?: number): string {
 | 
			
		||||
        return `${courseId}-${userId || 'current-user'}`;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    readonly COURSE_ID: number;
 | 
			
		||||
    readonly USER_ID?: number;
 | 
			
		||||
 | 
			
		||||
    courseCompetencies?: AddonCompetencyDataForCourseCompetenciesPageWSResponse;
 | 
			
		||||
    user?: CoreUserProfile;
 | 
			
		||||
 | 
			
		||||
    constructor(courseId: number, userId?: number) {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this.COURSE_ID = courseId;
 | 
			
		||||
        this.USER_ID = userId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    getItemPath(competency: AddonCompetencyDataForCourseCompetenciesPageCompetency): string {
 | 
			
		||||
        return String(competency.competency.id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async load(): Promise<void> {
 | 
			
		||||
        if (this.dirty || !this.courseCompetencies) {
 | 
			
		||||
            await this.loadCourseCompetencies();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await super.load();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Invalidate course cache.
 | 
			
		||||
     */
 | 
			
		||||
    async invalidateCache(): Promise<void> {
 | 
			
		||||
        await CoreUtils.ignoreErrors(AddonCompetency.invalidateCourseCompetencies(this.COURSE_ID, this.USER_ID));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    protected async loadPageItems(): Promise<{ items: AddonCompetencyDataForCourseCompetenciesPageCompetency[] }> {
 | 
			
		||||
        if (!this.courseCompetencies) {
 | 
			
		||||
            throw new Error('Can\'t load competencies without course data');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return { items: this.courseCompetencies.competencies };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Load competencies.
 | 
			
		||||
     */
 | 
			
		||||
    private async loadCourseCompetencies(): Promise<void> {
 | 
			
		||||
        [this.courseCompetencies, this.user] = await Promise.all([
 | 
			
		||||
            AddonCompetency.getCourseCompetencies(this.COURSE_ID, this.USER_ID),
 | 
			
		||||
            AddonCompetencyHelper.getProfile(this.USER_ID),
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,88 @@
 | 
			
		||||
// (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 { CoreRoutedItemsManagerSource } from '@classes/items-management/routed-items-manager-source';
 | 
			
		||||
import { CoreUserProfile } from '@features/user/services/user';
 | 
			
		||||
import { CoreUtils } from '@services/utils/utils';
 | 
			
		||||
import {
 | 
			
		||||
    AddonCompetency,
 | 
			
		||||
    AddonCompetencyDataForPlanPageCompetency,
 | 
			
		||||
    AddonCompetencyDataForPlanPageWSResponse,
 | 
			
		||||
} from '../services/competency';
 | 
			
		||||
import { AddonCompetencyHelper } from '../services/competency-helper';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides a collection of plan competencies.
 | 
			
		||||
 */
 | 
			
		||||
export class AddonCompetencyPlanCompetenciesSource extends CoreRoutedItemsManagerSource<AddonCompetencyDataForPlanPageCompetency> {
 | 
			
		||||
 | 
			
		||||
    readonly PLAN_ID: number;
 | 
			
		||||
 | 
			
		||||
    plan?: AddonCompetencyDataForPlanPageWSResponse;
 | 
			
		||||
    user?: CoreUserProfile;
 | 
			
		||||
 | 
			
		||||
    constructor(planId: number) {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this.PLAN_ID = planId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    getItemPath(competency: AddonCompetencyDataForPlanPageCompetency): string {
 | 
			
		||||
        return String(competency.competency.id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async load(): Promise<void> {
 | 
			
		||||
        if (this.dirty || !this.plan) {
 | 
			
		||||
            await this.loadLearningPlan();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await super.load();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Invalidate plan cache.
 | 
			
		||||
     */
 | 
			
		||||
    async invalidateCache(): Promise<void> {
 | 
			
		||||
        await CoreUtils.ignoreErrors(AddonCompetency.invalidateLearningPlan(this.PLAN_ID));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    protected async loadPageItems(): Promise<{ items: AddonCompetencyDataForPlanPageCompetency[] }> {
 | 
			
		||||
        if (!this.plan) {
 | 
			
		||||
            throw new Error('Can\'t load competencies without plan!');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return { items: this.plan.competencies };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Load learning plan.
 | 
			
		||||
     */
 | 
			
		||||
    private async loadLearningPlan(): Promise<void> {
 | 
			
		||||
        this.plan = await AddonCompetency.getLearningPlan(this.PLAN_ID);
 | 
			
		||||
        this.plan.plan.statusname = AddonCompetencyHelper.getPlanStatusName(this.plan.plan.status);
 | 
			
		||||
 | 
			
		||||
        // Get the user profile image.
 | 
			
		||||
        this.user = await AddonCompetencyHelper.getProfile(this.plan.plan.userid);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										97
									
								
								src/addons/competency/classes/competency-plans-source.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/addons/competency/classes/competency-plans-source.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,97 @@
 | 
			
		||||
// (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 { Params } from '@angular/router';
 | 
			
		||||
import { CoreRoutedItemsManagerSource } from '@classes/items-management/routed-items-manager-source';
 | 
			
		||||
import { ADDON_COMPETENCY_COMPETENCIES_PAGE } from '../competency.module';
 | 
			
		||||
import { AddonCompetency, AddonCompetencyPlan, AddonCompetencyProvider } from '../services/competency';
 | 
			
		||||
import { AddonCompetencyHelper } from '../services/competency-helper';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Provides a collection of learning plans.
 | 
			
		||||
 */
 | 
			
		||||
export class AddonCompetencyPlansSource extends CoreRoutedItemsManagerSource<AddonCompetencyPlanFormatted> {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    static getSourceId(userId?: number): string {
 | 
			
		||||
        return userId ? String(userId) : 'current-user';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    readonly USER_ID?: number;
 | 
			
		||||
 | 
			
		||||
    constructor(userId?: number) {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        this.USER_ID = userId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    getItemPath(plan: AddonCompetencyPlanFormatted): string {
 | 
			
		||||
        return `${plan.id}/${ADDON_COMPETENCY_COMPETENCIES_PAGE}`;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    getItemQueryParams(): Params {
 | 
			
		||||
        if (this.USER_ID) {
 | 
			
		||||
            return { userId: this.USER_ID };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Invalidate learning plans cache.
 | 
			
		||||
     */
 | 
			
		||||
    async invalidateCache(): Promise<void> {
 | 
			
		||||
        await AddonCompetency.invalidateLearningPlans(this.USER_ID);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    protected async loadPageItems(): Promise<{ items: AddonCompetencyPlanFormatted[] }> {
 | 
			
		||||
        const plans = await AddonCompetency.getLearningPlans(this.USER_ID);
 | 
			
		||||
 | 
			
		||||
        plans.forEach((plan: AddonCompetencyPlanFormatted) => {
 | 
			
		||||
            plan.statusname = AddonCompetencyHelper.getPlanStatusName(plan.status);
 | 
			
		||||
            switch (plan.status) {
 | 
			
		||||
                case AddonCompetencyProvider.STATUS_ACTIVE:
 | 
			
		||||
                    plan.statuscolor = 'success';
 | 
			
		||||
                    break;
 | 
			
		||||
                case AddonCompetencyProvider.STATUS_COMPLETE:
 | 
			
		||||
                    plan.statuscolor = 'danger';
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    plan.statuscolor = 'warning';
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return { items: plans };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Competency plan with some calculated data.
 | 
			
		||||
 */
 | 
			
		||||
export type AddonCompetencyPlanFormatted = AddonCompetencyPlan & {
 | 
			
		||||
    statuscolor?: string; // Calculated in the app. Color of the plan's status.
 | 
			
		||||
};
 | 
			
		||||
@ -10,7 +10,7 @@
 | 
			
		||||
        </ion-title>
 | 
			
		||||
    </ion-toolbar>
 | 
			
		||||
</ion-header>
 | 
			
		||||
<ion-content>
 | 
			
		||||
<ion-content [core-swipe-navigation]="competencies">
 | 
			
		||||
    <ion-refresher slot="fixed" [disabled]="!competencyLoaded" (ionRefresh)="refreshCompetency($event.target)">
 | 
			
		||||
        <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
			
		||||
    </ion-refresher>
 | 
			
		||||
@ -36,9 +36,7 @@
 | 
			
		||||
                <ion-label>
 | 
			
		||||
                    <p class="item-heading">{{ 'addon.competency.path' | translate }}</p>
 | 
			
		||||
                    <p>
 | 
			
		||||
                        <a *ngIf="competency.competency.comppath.showlinks" [href]="competency.competency.comppath.pluginbaseurl + '/competencies.php?competencyframeworkid=' +
 | 
			
		||||
                            competency.competency.comppath.framework.id + '&pagecontextid=' +
 | 
			
		||||
                            competency.competency.comppath.pagecontextid" core-link>
 | 
			
		||||
                        <a *ngIf="competency.competency.comppath.showlinks" [href]="competencyFrameworkUrl" core-link>
 | 
			
		||||
                            {{ competency.competency.comppath.framework.name }}
 | 
			
		||||
                        </a>
 | 
			
		||||
                        <ng-container *ngIf="!competency.competency.comppath.showlinks">
 | 
			
		||||
@ -79,7 +77,8 @@
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <ion-item class="ion-text-wrap" *ngFor="let activity of coursemodules" [href]="activity.url"
 | 
			
		||||
                        [attr.aria-label]="activity.name" core-link capture="true">
 | 
			
		||||
                        <core-mod-icon slot="start" [modicon]="activity.iconurl" [showAlt]="false" *ngIf="activity.iconurl"></core-mod-icon>
 | 
			
		||||
                        <core-mod-icon slot="start" [modicon]="activity.iconurl" [showAlt]="false" *ngIf="activity.iconurl">
 | 
			
		||||
                        </core-mod-icon>
 | 
			
		||||
                        <ion-label>
 | 
			
		||||
                            <core-format-text [text]="activity.name" contextLevel="module" [contextInstanceId]="activity.id"
 | 
			
		||||
                                [courseId]="courseId">
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,7 @@
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { AddonCompetencyHelper } from '@addons/competency/services/competency-helper';
 | 
			
		||||
import { Component, OnInit } from '@angular/core';
 | 
			
		||||
import { Component, OnDestroy, OnInit } from '@angular/core';
 | 
			
		||||
import { CoreCourseModuleSummary } from '@features/course/services/course';
 | 
			
		||||
import { CoreUserSummary } from '@features/user/services/user';
 | 
			
		||||
import { CoreSites } from '@services/sites';
 | 
			
		||||
@ -25,14 +25,19 @@ import {
 | 
			
		||||
    AddonCompetencyUserCompetency,
 | 
			
		||||
    AddonCompetencyUserCompetencyCourse,
 | 
			
		||||
    AddonCompetency,
 | 
			
		||||
    AddonCompetencyDataForUserCompetencySummaryInPlanWSResponse,
 | 
			
		||||
    AddonCompetencyDataForUserCompetencySummaryInCourseWSResponse,
 | 
			
		||||
    AddonCompetencyDataForPlanPageCompetency,
 | 
			
		||||
    AddonCompetencyDataForCourseCompetenciesPageCompetency,
 | 
			
		||||
} from '@addons/competency/services/competency';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { IonRefresher } from '@ionic/angular';
 | 
			
		||||
import { ContextLevel } from '@/core/constants';
 | 
			
		||||
import { CoreUtils } from '@services/utils/utils';
 | 
			
		||||
import { ADDON_COMPETENCY_SUMMARY_PAGE } from '@addons/competency/competency.module';
 | 
			
		||||
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
 | 
			
		||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
 | 
			
		||||
import { AddonCompetencyPlanCompetenciesSource } from '@addons/competency/classes/competency-plan-competencies-source';
 | 
			
		||||
import { ActivatedRouteSnapshot } from '@angular/router';
 | 
			
		||||
import { AddonCompetencyCourseCompetenciesSource } from '@addons/competency/classes/competency-course-competencies-source';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page that displays the competency information.
 | 
			
		||||
@ -41,13 +46,10 @@ import { ADDON_COMPETENCY_SUMMARY_PAGE } from '@addons/competency/competency.mod
 | 
			
		||||
    selector: 'page-addon-competency-competency',
 | 
			
		||||
    templateUrl: 'competency.html',
 | 
			
		||||
})
 | 
			
		||||
export class AddonCompetencyCompetencyPage implements OnInit {
 | 
			
		||||
export class AddonCompetencyCompetencyPage implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
    competencyLoaded = false;
 | 
			
		||||
    competencyId!: number;
 | 
			
		||||
    planId?: number;
 | 
			
		||||
    courseId?: number;
 | 
			
		||||
    userId?: number;
 | 
			
		||||
    competencies!: AddonCompetencyCompetenciesSwipeManager;
 | 
			
		||||
    planStatus?: number;
 | 
			
		||||
    coursemodules?: CoreCourseModuleSummary[];
 | 
			
		||||
    user?: CoreUserSummary;
 | 
			
		||||
@ -56,17 +58,26 @@ export class AddonCompetencyCompetencyPage implements OnInit {
 | 
			
		||||
    contextLevel?: string;
 | 
			
		||||
    contextInstanceId?: number;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async ngOnInit(): Promise<void> {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        try {
 | 
			
		||||
            this.competencyId = CoreNavigator.getRequiredRouteNumberParam('competencyId');
 | 
			
		||||
            this.planId = CoreNavigator.getRouteNumberParam('planId');
 | 
			
		||||
            if (!this.planId) {
 | 
			
		||||
                this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
 | 
			
		||||
                this.userId = CoreNavigator.getRouteNumberParam('userId');
 | 
			
		||||
            const planId = CoreNavigator.getRouteNumberParam('planId');
 | 
			
		||||
 | 
			
		||||
            if (!planId) {
 | 
			
		||||
                const courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
 | 
			
		||||
                const userId = CoreNavigator.getRouteNumberParam('userId');
 | 
			
		||||
                const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
 | 
			
		||||
                    AddonCompetencyCourseCompetenciesSource,
 | 
			
		||||
                    [courseId, userId],
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                this.competencies = new AddonCompetencyCompetenciesSwipeManager(source);
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(AddonCompetencyPlanCompetenciesSource, [planId]);
 | 
			
		||||
 | 
			
		||||
            this.competencies = new AddonCompetencyCompetenciesSwipeManager(source);
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            CoreDomUtils.showErrorModal(error);
 | 
			
		||||
 | 
			
		||||
@ -74,24 +85,63 @@ export class AddonCompetencyCompetencyPage implements OnInit {
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get competencyFrameworkUrl(): string | undefined {
 | 
			
		||||
        if (!this.competency) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const { pluginbaseurl, framework, pagecontextid } = this.competency.competency.comppath;
 | 
			
		||||
 | 
			
		||||
        return `${pluginbaseurl}/competencies.php?competencyframeworkid=${framework.id}&pagecontextid=${pagecontextid}`;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get courseId(): number | undefined {
 | 
			
		||||
        const source = this.competencies.getSource();
 | 
			
		||||
 | 
			
		||||
        if (!(source instanceof AddonCompetencyCourseCompetenciesSource)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return source.COURSE_ID;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async ngOnInit(): Promise<void> {
 | 
			
		||||
        try {
 | 
			
		||||
            const source = this.competencies.getSource();
 | 
			
		||||
 | 
			
		||||
            await source.reload();
 | 
			
		||||
            await this.competencies.start();
 | 
			
		||||
            await this.fetchCompetency();
 | 
			
		||||
 | 
			
		||||
            const name = this.competency && this.competency.competency && this.competency.competency.competency &&
 | 
			
		||||
                    this.competency.competency.competency.shortname;
 | 
			
		||||
            if (!this.competency) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.planId) {
 | 
			
		||||
                CoreUtils.ignoreErrors(AddonCompetency.logCompetencyInPlanView(
 | 
			
		||||
                    this.planId,
 | 
			
		||||
                    this.competencyId,
 | 
			
		||||
                    this.planStatus!,
 | 
			
		||||
            const name = this.competency.competency.competency.shortname;
 | 
			
		||||
 | 
			
		||||
            if (source instanceof AddonCompetencyPlanCompetenciesSource) {
 | 
			
		||||
                this.planStatus && await CoreUtils.ignoreErrors(
 | 
			
		||||
                    AddonCompetency.logCompetencyInPlanView(
 | 
			
		||||
                        source.PLAN_ID,
 | 
			
		||||
                        this.requireCompetencyId(),
 | 
			
		||||
                        this.planStatus,
 | 
			
		||||
                        name,
 | 
			
		||||
                    this.userId,
 | 
			
		||||
                ));
 | 
			
		||||
                        source.user?.id,
 | 
			
		||||
                    ),
 | 
			
		||||
                );
 | 
			
		||||
            } else {
 | 
			
		||||
                CoreUtils.ignoreErrors(
 | 
			
		||||
                    AddonCompetency.logCompetencyInCourseView(this.courseId!, this.competencyId, name, this.userId),
 | 
			
		||||
                await CoreUtils.ignoreErrors(
 | 
			
		||||
                    AddonCompetency.logCompetencyInCourseView(
 | 
			
		||||
                        source.COURSE_ID,
 | 
			
		||||
                        this.requireCompetencyId(),
 | 
			
		||||
                        name,
 | 
			
		||||
                        source.USER_ID,
 | 
			
		||||
                    ),
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        } finally {
 | 
			
		||||
@ -99,47 +149,25 @@ export class AddonCompetencyCompetencyPage implements OnInit {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    ngOnDestroy(): void {
 | 
			
		||||
        this.competencies.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Fetches the competency and updates the view.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Promise resolved when done.
 | 
			
		||||
     */
 | 
			
		||||
    protected async fetchCompetency(): Promise<void> {
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            let competency: AddonCompetencyDataForUserCompetencySummaryInPlanWSResponse |
 | 
			
		||||
            AddonCompetencyDataForUserCompetencySummaryInCourseWSResponse;
 | 
			
		||||
            const source = this.competencies.getSource();
 | 
			
		||||
 | 
			
		||||
            if (this.planId) {
 | 
			
		||||
                this.planStatus = undefined;
 | 
			
		||||
 | 
			
		||||
                competency = await AddonCompetency.getCompetencyInPlan(this.planId, this.competencyId);
 | 
			
		||||
            } else if (this.courseId) {
 | 
			
		||||
                competency = await AddonCompetency.getCompetencyInCourse(this.courseId, this.competencyId, this.userId);
 | 
			
		||||
            } else {
 | 
			
		||||
                throw null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Calculate the context.
 | 
			
		||||
            if (this.courseId) {
 | 
			
		||||
                this.contextLevel = ContextLevel.COURSE;
 | 
			
		||||
                this.contextInstanceId = this.courseId;
 | 
			
		||||
            } else {
 | 
			
		||||
                this.contextLevel = ContextLevel.USER;
 | 
			
		||||
                this.contextInstanceId = this.userId || competency.usercompetencysummary.user.id;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.competency = competency.usercompetencysummary;
 | 
			
		||||
            this.userCompetency = this.competency.usercompetencyplan || this.competency.usercompetency;
 | 
			
		||||
 | 
			
		||||
            if ('plan' in competency) {
 | 
			
		||||
                this.planStatus = competency.plan.status;
 | 
			
		||||
                this.competency.usercompetency!.statusname =
 | 
			
		||||
                    AddonCompetencyHelper.getCompetencyStatusName(this.competency.usercompetency!.status);
 | 
			
		||||
            } else {
 | 
			
		||||
                this.userCompetency = this.competency.usercompetencycourse;
 | 
			
		||||
                this.coursemodules = competency.coursemodules;
 | 
			
		||||
            }
 | 
			
		||||
            this.competency = source instanceof AddonCompetencyPlanCompetenciesSource
 | 
			
		||||
                ? await this.fetchCompetencySummaryFromPlan(source)
 | 
			
		||||
                : await this.fetchCompetencySummaryFromCourse(source);
 | 
			
		||||
 | 
			
		||||
            if (this.competency.user.id != CoreSites.getCurrentSiteUserId()) {
 | 
			
		||||
                // Get the user profile from the returned object.
 | 
			
		||||
@ -163,19 +191,18 @@ export class AddonCompetencyCompetencyPage implements OnInit {
 | 
			
		||||
     * @param refresher Refresher.
 | 
			
		||||
     */
 | 
			
		||||
    async refreshCompetency(refresher: IonRefresher): Promise<void> {
 | 
			
		||||
        try {
 | 
			
		||||
            if (this.planId) {
 | 
			
		||||
                await AddonCompetency.invalidateCompetencyInPlan(this.planId, this.competencyId);
 | 
			
		||||
            } else {
 | 
			
		||||
                await AddonCompetency.invalidateCompetencyInCourse(this.courseId!, this.competencyId);
 | 
			
		||||
            }
 | 
			
		||||
        const source = this.competencies.getSource();
 | 
			
		||||
 | 
			
		||||
        await CoreUtils.ignoreErrors(
 | 
			
		||||
            source instanceof AddonCompetencyPlanCompetenciesSource
 | 
			
		||||
                ? AddonCompetency.invalidateCompetencyInPlan(source.PLAN_ID, this.requireCompetencyId())
 | 
			
		||||
                : AddonCompetency.invalidateCompetencyInCourse(source.COURSE_ID, this.requireCompetencyId(), source.USER_ID),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        } finally {
 | 
			
		||||
        this.fetchCompetency().finally(() => {
 | 
			
		||||
            refresher?.complete();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Opens the summary of a competency.
 | 
			
		||||
@ -191,4 +218,91 @@ export class AddonCompetencyCompetencyPage implements OnInit {
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get competency id or fail.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns Competency id.
 | 
			
		||||
     */
 | 
			
		||||
    private requireCompetencyId(): number {
 | 
			
		||||
        const selectedItem = this.competencies.getSelectedItem();
 | 
			
		||||
 | 
			
		||||
        if (!selectedItem) {
 | 
			
		||||
            throw new Error('Failed to get competency id from selected item');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return selectedItem.competency.id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Fetch competency summary from a plan source.
 | 
			
		||||
     *
 | 
			
		||||
     * @param source Plan competencies source.
 | 
			
		||||
     * @returns Competency summary.
 | 
			
		||||
     */
 | 
			
		||||
    private async fetchCompetencySummaryFromPlan(
 | 
			
		||||
        source: AddonCompetencyPlanCompetenciesSource,
 | 
			
		||||
    ): Promise<AddonCompetencyDataForUserCompetencySummaryWSResponse> {
 | 
			
		||||
        const competency = await AddonCompetency.getCompetencyInPlan(
 | 
			
		||||
            source.PLAN_ID,
 | 
			
		||||
            this.requireCompetencyId(),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        this.planStatus = competency.plan.status;
 | 
			
		||||
 | 
			
		||||
        if (competency.usercompetencysummary.usercompetency) {
 | 
			
		||||
            competency.usercompetencysummary.usercompetency.statusname =
 | 
			
		||||
                AddonCompetencyHelper.getCompetencyStatusName(competency.usercompetencysummary.usercompetency.status);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.contextLevel = ContextLevel.USER;
 | 
			
		||||
        this.contextInstanceId = source.user?.id || competency.usercompetencysummary.user.id;
 | 
			
		||||
        this.userCompetency = competency.usercompetencysummary.usercompetencyplan
 | 
			
		||||
            || competency.usercompetencysummary.usercompetency;
 | 
			
		||||
 | 
			
		||||
        return competency.usercompetencysummary;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Fetch competency summary from a course source.
 | 
			
		||||
     *
 | 
			
		||||
     * @param source Course competencies source.
 | 
			
		||||
     * @returns Competency summary.
 | 
			
		||||
     */
 | 
			
		||||
    private async fetchCompetencySummaryFromCourse(
 | 
			
		||||
        source: AddonCompetencyCourseCompetenciesSource,
 | 
			
		||||
    ): Promise<AddonCompetencyDataForUserCompetencySummaryWSResponse> {
 | 
			
		||||
        const competency = await AddonCompetency.getCompetencyInCourse(
 | 
			
		||||
            source.COURSE_ID,
 | 
			
		||||
            this.requireCompetencyId(),
 | 
			
		||||
            source.USER_ID,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        this.coursemodules = competency.coursemodules;
 | 
			
		||||
 | 
			
		||||
        this.contextLevel = ContextLevel.COURSE;
 | 
			
		||||
        this.contextInstanceId = source.COURSE_ID;
 | 
			
		||||
        this.userCompetency = competency.usercompetencysummary.usercompetencycourse
 | 
			
		||||
            || competency.usercompetencysummary.usercompetency;
 | 
			
		||||
 | 
			
		||||
        return competency.usercompetencysummary;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helper to manage swiping within a collection of competencies.
 | 
			
		||||
 */
 | 
			
		||||
class AddonCompetencyCompetenciesSwipeManager
 | 
			
		||||
    extends CoreSwipeNavigationItemsManager<
 | 
			
		||||
    AddonCompetencyDataForPlanPageCompetency | AddonCompetencyDataForCourseCompetenciesPageCompetency,
 | 
			
		||||
    AddonCompetencyPlanCompetenciesSource | AddonCompetencyCourseCompetenciesSource
 | 
			
		||||
    > {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    protected getSelectedItemPathFromRoute(route: ActivatedRouteSnapshot): string | null {
 | 
			
		||||
        return route.params.competencyId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -9,35 +9,35 @@
 | 
			
		||||
    </ion-toolbar>
 | 
			
		||||
</ion-header>
 | 
			
		||||
<ion-content>
 | 
			
		||||
    <ion-refresher slot="fixed" [disabled]="!competenciesLoaded" (ionRefresh)="refreshCourseCompetencies($event.target)">
 | 
			
		||||
    <ion-refresher slot="fixed" [disabled]="!competencies.loaded" (ionRefresh)="refreshCourseCompetencies($event.target)">
 | 
			
		||||
        <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
			
		||||
    </ion-refresher>
 | 
			
		||||
    <core-loading [hideUntil]="competenciesLoaded">
 | 
			
		||||
        <ion-card *ngIf="!user && competencies && competencies.statistics.competencycount > 0">
 | 
			
		||||
            <ng-container *ngIf="competencies.cangradecompetencies">
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="competencies.settings.pushratingstouserplans">
 | 
			
		||||
    <core-loading [hideUntil]="competencies.loaded">
 | 
			
		||||
        <ion-card *ngIf="!user && courseCompetencies && courseCompetencies.statistics.competencycount > 0">
 | 
			
		||||
            <ng-container *ngIf="courseCompetencies.cangradecompetencies">
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="courseCompetencies.settings.pushratingstouserplans">
 | 
			
		||||
                    <ion-label>{{ 'addon.competency.coursecompetencyratingsarepushedtouserplans' | translate }}</ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="!competencies.settings.pushratingstouserplans" color="danger">
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="!courseCompetencies.settings.pushratingstouserplans" color="danger">
 | 
			
		||||
                    <ion-label>{{ 'addon.competency.coursecompetencyratingsarenotpushedtouserplans' | translate }}</ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
            </ng-container>
 | 
			
		||||
            <ion-item class="ion-text-wrap" *ngIf="competencies.statistics.canbegradedincourse">
 | 
			
		||||
            <ion-item class="ion-text-wrap" *ngIf="courseCompetencies.statistics.canbegradedincourse">
 | 
			
		||||
                <ion-label>
 | 
			
		||||
                    <span id="addon-competency-course-{{courseId}}-progress">
 | 
			
		||||
                        {{ 'addon.competency.xcompetenciesproficientoutofyincourse' | translate: {$a:
 | 
			
		||||
                        {x: competencies.statistics.proficientcompetencycount, y: competencies.statistics.competencycount} } }}
 | 
			
		||||
                        {x: courseCompetencies.statistics.proficientcompetencycount, y: courseCompetencies.statistics.competencycount} } }}
 | 
			
		||||
                    </span>
 | 
			
		||||
                    <core-progress-bar [progress]="competencies.statistics.proficientcompetencypercentage"
 | 
			
		||||
                    <core-progress-bar [progress]="courseCompetencies.statistics.proficientcompetencypercentage"
 | 
			
		||||
                        ariaDescribedBy="addon-competency-course-{{courseId}}-progress">
 | 
			
		||||
                    </core-progress-bar>
 | 
			
		||||
                </ion-label>
 | 
			
		||||
            </ion-item>
 | 
			
		||||
            <ion-item class="ion-text-wrap"
 | 
			
		||||
                *ngIf="competencies.statistics.canmanagecoursecompetencies && competencies.statistics.leastproficientcount > 0">
 | 
			
		||||
                *ngIf="courseCompetencies.statistics.canmanagecoursecompetencies && courseCompetencies.statistics.leastproficientcount > 0">
 | 
			
		||||
                <ion-label>
 | 
			
		||||
                    <p class="item-heading">{{ 'addon.competency.competenciesmostoftennotproficientincourse' | translate }}</p>
 | 
			
		||||
                    <p *ngFor="let comp of competencies.statistics.leastproficient">
 | 
			
		||||
                    <p *ngFor="let comp of courseCompetencies.statistics.leastproficient">
 | 
			
		||||
                        <button class="as-link" (click)="openCompetencySummary(comp.id)">
 | 
			
		||||
                            {{ comp.shortname }} - {{ comp.idnumber }}
 | 
			
		||||
                        </button>
 | 
			
		||||
@ -46,7 +46,7 @@
 | 
			
		||||
            </ion-item>
 | 
			
		||||
        </ion-card>
 | 
			
		||||
 | 
			
		||||
        <h2 class="ion-margin-horizontal" *ngIf="competencies && competencies.statistics.competencycount > 0">
 | 
			
		||||
        <h2 class="ion-margin-horizontal" *ngIf="courseCompetencies && courseCompetencies.statistics.competencycount > 0">
 | 
			
		||||
            {{ 'addon.competency.coursecompetencies' | translate }}
 | 
			
		||||
        </h2>
 | 
			
		||||
        <ion-card *ngIf="user">
 | 
			
		||||
@ -57,13 +57,13 @@
 | 
			
		||||
                </ion-label>
 | 
			
		||||
            </ion-item>
 | 
			
		||||
        </ion-card>
 | 
			
		||||
        <core-empty-box *ngIf="competencies && competencies.statistics.competencycount == 0" icon="fas-award"
 | 
			
		||||
        <core-empty-box *ngIf="courseCompetencies && courseCompetencies.statistics.competencycount == 0" icon="fas-award"
 | 
			
		||||
            message="{{ 'addon.competency.nocompetenciesincourse' | translate }}">
 | 
			
		||||
        </core-empty-box>
 | 
			
		||||
 | 
			
		||||
        <div *ngIf="competencies">
 | 
			
		||||
            <ion-card *ngFor="let competency of competencies.competencies">
 | 
			
		||||
                <ion-item class="ion-text-wrap" (click)="openCompetency(competency.competency.id)"
 | 
			
		||||
        <div *ngIf="competencies.loaded">
 | 
			
		||||
            <ion-card *ngFor="let competency of competencies.items">
 | 
			
		||||
                <ion-item class="ion-text-wrap" (click)="competencies.select(competency)"
 | 
			
		||||
                    [attr.aria-label]="competency.competency.shortname" detail="true" button>
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <p class="item-heading">
 | 
			
		||||
@ -85,8 +85,7 @@
 | 
			
		||||
                        <div>
 | 
			
		||||
                            <p class="item-heading">{{ 'addon.competency.path' | translate }}</p>
 | 
			
		||||
                            <p>
 | 
			
		||||
                                <a *ngIf="competency.comppath.showlinks" [href]="competency.comppath.pluginbaseurl + '/competencies.php?competencyframeworkid=' +
 | 
			
		||||
                                    competency.comppath.framework.id + '&pagecontextid=' + competency.comppath.pagecontextid" core-link
 | 
			
		||||
                                <a *ngIf="competency.comppath.showlinks" [href]="getCompetencyFrameworkUrl(competency)" core-link
 | 
			
		||||
                                    [title]="competency.comppath.framework.name">
 | 
			
		||||
                                    {{ competency.comppath.framework.name }}
 | 
			
		||||
                                </a>
 | 
			
		||||
@ -104,7 +103,7 @@
 | 
			
		||||
                                </ng-container>
 | 
			
		||||
                            </p>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div *ngIf="competencies.statistics.canmanagecoursecompetencies">
 | 
			
		||||
                        <div *ngIf="courseCompetencies?.statistics.canmanagecoursecompetencies">
 | 
			
		||||
                            <p class="item-heading">{{ 'addon.competency.uponcoursecompletion' | translate }}</p>
 | 
			
		||||
                            <ng-container *ngFor="let ruleoutcome of competency.ruleoutcomeoptions">
 | 
			
		||||
                                <span *ngIf="ruleoutcome.selected">{{ ruleoutcome.text }}</span>
 | 
			
		||||
 | 
			
		||||
@ -12,15 +12,20 @@
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { Component, OnInit } from '@angular/core';
 | 
			
		||||
import { AddonCompetencyDataForCourseCompetenciesPageWSResponse, AddonCompetency } from '@addons/competency/services/competency';
 | 
			
		||||
import { AddonCompetencyHelper } from '@addons/competency/services/competency-helper';
 | 
			
		||||
import { Component, OnDestroy, OnInit } from '@angular/core';
 | 
			
		||||
import {
 | 
			
		||||
    AddonCompetencyDataForCourseCompetenciesPageWSResponse,
 | 
			
		||||
    AddonCompetencyDataForCourseCompetenciesPageCompetency,
 | 
			
		||||
} from '@addons/competency/services/competency';
 | 
			
		||||
import { CoreUserProfile } from '@features/user/services/user';
 | 
			
		||||
import { IonRefresher } from '@ionic/angular';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
import { ContextLevel } from '@/core/constants';
 | 
			
		||||
import { ADDON_COMPETENCY_SUMMARY_PAGE } from '@addons/competency/competency.module';
 | 
			
		||||
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
 | 
			
		||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
 | 
			
		||||
import { AddonCompetencyCourseCompetenciesSource } from '@addons/competency/classes/competency-course-competencies-source';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page that displays the list of competencies of a course.
 | 
			
		||||
@ -29,22 +34,23 @@ import { ADDON_COMPETENCY_SUMMARY_PAGE } from '@addons/competency/competency.mod
 | 
			
		||||
    selector: 'page-addon-competency-coursecompetencies',
 | 
			
		||||
    templateUrl: 'coursecompetencies.html',
 | 
			
		||||
})
 | 
			
		||||
export class AddonCompetencyCourseCompetenciesPage implements OnInit {
 | 
			
		||||
export class AddonCompetencyCourseCompetenciesPage implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
    competenciesLoaded = false;
 | 
			
		||||
    competencies?: AddonCompetencyDataForCourseCompetenciesPageWSResponse;
 | 
			
		||||
    user?: CoreUserProfile;
 | 
			
		||||
    courseId!: number;
 | 
			
		||||
    competencies!: CoreListItemsManager<
 | 
			
		||||
        AddonCompetencyDataForCourseCompetenciesPageCompetency,
 | 
			
		||||
        AddonCompetencyCourseCompetenciesSource
 | 
			
		||||
    >;
 | 
			
		||||
 | 
			
		||||
    protected userId?: number;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * View loaded.
 | 
			
		||||
     */
 | 
			
		||||
    ngOnInit(): void {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        try {
 | 
			
		||||
            this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
 | 
			
		||||
            this.userId = CoreNavigator.getRouteNumberParam('userId');
 | 
			
		||||
            const courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
 | 
			
		||||
            const userId = CoreNavigator.getRouteNumberParam('userId');
 | 
			
		||||
            const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
 | 
			
		||||
                AddonCompetencyCourseCompetenciesSource,
 | 
			
		||||
                [courseId, userId],
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            this.competencies = new CoreListItemsManager(source, AddonCompetencyCourseCompetenciesPage);
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            CoreDomUtils.showErrorModal(error);
 | 
			
		||||
 | 
			
		||||
@ -52,10 +58,50 @@ export class AddonCompetencyCourseCompetenciesPage implements OnInit {
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        this.fetchCourseCompetencies().finally(() => {
 | 
			
		||||
            this.competenciesLoaded = true;
 | 
			
		||||
        });
 | 
			
		||||
    get courseCompetencies(): AddonCompetencyDataForCourseCompetenciesPageWSResponse | undefined {
 | 
			
		||||
        return this.competencies.getSource().courseCompetencies;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get courseId(): number {
 | 
			
		||||
        return this.competencies.getSource().COURSE_ID;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get user(): CoreUserProfile | undefined {
 | 
			
		||||
        return this.competencies.getSource().user;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get showLeastProficientCompetencies(): boolean {
 | 
			
		||||
        return !!this.courseCompetencies?.statistics.canmanagecoursecompetencies
 | 
			
		||||
            && this.courseCompetencies?.statistics.leastproficientcount > 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async ngOnInit(): Promise<void> {
 | 
			
		||||
        await this.fetchCourseCompetencies();
 | 
			
		||||
        await this.competencies.start();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    ngOnDestroy(): void {
 | 
			
		||||
        this.competencies.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get competency framework url.
 | 
			
		||||
     *
 | 
			
		||||
     * @param competency Competency.
 | 
			
		||||
     * @returns Competency framework url.
 | 
			
		||||
     */
 | 
			
		||||
    getCompetencyFrameworkUrl(competency: AddonCompetencyDataForCourseCompetenciesPageCompetency): string {
 | 
			
		||||
        const { pluginbaseurl, framework, pagecontextid } = competency.comppath;
 | 
			
		||||
 | 
			
		||||
        return `${pluginbaseurl}/competencies.php?competencyframeworkid=${framework.id}&pagecontextid=${pagecontextid}`;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -65,24 +111,12 @@ export class AddonCompetencyCourseCompetenciesPage implements OnInit {
 | 
			
		||||
     */
 | 
			
		||||
    protected async fetchCourseCompetencies(): Promise<void> {
 | 
			
		||||
        try {
 | 
			
		||||
            this.competencies = await AddonCompetency.getCourseCompetencies(this.courseId, this.userId);
 | 
			
		||||
 | 
			
		||||
            // Get the user profile image.
 | 
			
		||||
            this.user = await AddonCompetencyHelper.getProfile(this.userId);
 | 
			
		||||
            await this.competencies.getSource().reload();
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            CoreDomUtils.showErrorModalDefault(error, 'Error getting course competencies data.');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Opens a competency.
 | 
			
		||||
     *
 | 
			
		||||
     * @param competencyId
 | 
			
		||||
     */
 | 
			
		||||
    openCompetency(competencyId: number): void {
 | 
			
		||||
        CoreNavigator.navigate('./' + competencyId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Opens the summary of a competency.
 | 
			
		||||
     *
 | 
			
		||||
@ -105,12 +139,12 @@ export class AddonCompetencyCourseCompetenciesPage implements OnInit {
 | 
			
		||||
     *
 | 
			
		||||
     * @param refresher Refresher.
 | 
			
		||||
     */
 | 
			
		||||
    refreshCourseCompetencies(refresher?: IonRefresher): void {
 | 
			
		||||
        AddonCompetency.invalidateCourseCompetencies(this.courseId, this.userId).finally(() => {
 | 
			
		||||
    async refreshCourseCompetencies(refresher?: IonRefresher): Promise<void> {
 | 
			
		||||
        await this.competencies.getSource().invalidateCache();
 | 
			
		||||
 | 
			
		||||
        this.fetchCourseCompetencies().finally(() => {
 | 
			
		||||
            refresher?.complete();
 | 
			
		||||
        });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -8,11 +8,11 @@
 | 
			
		||||
        </ion-title>
 | 
			
		||||
    </ion-toolbar>
 | 
			
		||||
</ion-header>
 | 
			
		||||
<ion-content>
 | 
			
		||||
    <ion-refresher slot="fixed" [disabled]="!loaded" (ionRefresh)="refreshLearningPlan($event.target)">
 | 
			
		||||
<ion-content [core-swipe-navigation]="plans">
 | 
			
		||||
    <ion-refresher slot="fixed" [disabled]="!competencies.loaded" (ionRefresh)="refreshLearningPlan($event.target)">
 | 
			
		||||
        <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
			
		||||
    </ion-refresher>
 | 
			
		||||
    <core-loading [hideUntil]="loaded">
 | 
			
		||||
    <core-loading [hideUntil]="competencies.loaded">
 | 
			
		||||
        <ion-card *ngIf="user">
 | 
			
		||||
            <ion-item class="ion-text-wrap">
 | 
			
		||||
                <ion-label>
 | 
			
		||||
@ -74,9 +74,8 @@
 | 
			
		||||
                        <p>{{ 'addon.competency.nocompetencies' | translate }}</p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngFor="let competency of plan.competencies"
 | 
			
		||||
                    (click)="openCompetency(competency.competency.id)" [attr.aria-label]="competency.competency.shortname" detail="true"
 | 
			
		||||
                    button>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngFor="let competency of competencies.items" (click)="competencies.select(competency)"
 | 
			
		||||
                    [attr.aria-label]="competency.competency.shortname" detail="true" button>
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <p class="item-heading">{{competency.competency.shortname}} <em>{{competency.competency.idnumber}}</em></p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
 | 
			
		||||
@ -12,13 +12,17 @@
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { Component, OnInit } from '@angular/core';
 | 
			
		||||
import { Component, OnDestroy, OnInit } from '@angular/core';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
import { AddonCompetencyDataForPlanPageWSResponse, AddonCompetency } from '../../services/competency';
 | 
			
		||||
import { AddonCompetencyHelper } from '../../services/competency-helper';
 | 
			
		||||
import { AddonCompetencyDataForPlanPageCompetency, AddonCompetencyDataForPlanPageWSResponse } from '../../services/competency';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CoreUserProfile } from '@features/user/services/user';
 | 
			
		||||
import { IonRefresher } from '@ionic/angular';
 | 
			
		||||
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
 | 
			
		||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
 | 
			
		||||
import { AddonCompetencyPlansSource } from '@addons/competency/classes/competency-plans-source';
 | 
			
		||||
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
 | 
			
		||||
import { AddonCompetencyPlanCompetenciesSource } from '@addons/competency/classes/competency-plan-competencies-source';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page that displays a learning plan.
 | 
			
		||||
@ -27,19 +31,26 @@ import { IonRefresher } from '@ionic/angular';
 | 
			
		||||
    selector: 'page-addon-competency-plan',
 | 
			
		||||
    templateUrl: 'plan.html',
 | 
			
		||||
})
 | 
			
		||||
export class AddonCompetencyPlanPage implements OnInit {
 | 
			
		||||
export class AddonCompetencyPlanPage implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
    protected planId!: number;
 | 
			
		||||
    loaded = false;
 | 
			
		||||
    plan?: AddonCompetencyDataForPlanPageWSResponse;
 | 
			
		||||
    user?: CoreUserProfile;
 | 
			
		||||
    plans!: CoreSwipeNavigationItemsManager;
 | 
			
		||||
    competencies!: CoreListItemsManager<AddonCompetencyDataForPlanPageCompetency, AddonCompetencyPlanCompetenciesSource>;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    ngOnInit(): void {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        try {
 | 
			
		||||
            this.planId = CoreNavigator.getRequiredRouteNumberParam('planId');
 | 
			
		||||
            const planId = CoreNavigator.getRequiredRouteNumberParam('planId');
 | 
			
		||||
            const userId = CoreNavigator.getRouteNumberParam('userId');
 | 
			
		||||
            const plansSource = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
 | 
			
		||||
                AddonCompetencyPlansSource,
 | 
			
		||||
                [userId],
 | 
			
		||||
            );
 | 
			
		||||
            const competenciesSource = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(
 | 
			
		||||
                AddonCompetencyPlanCompetenciesSource,
 | 
			
		||||
                [planId],
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            this.competencies = new CoreListItemsManager(competenciesSource, AddonCompetencyPlanPage);
 | 
			
		||||
            this.plans = new CoreSwipeNavigationItemsManager(plansSource);
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            CoreDomUtils.showErrorModal(error);
 | 
			
		||||
 | 
			
		||||
@ -47,10 +58,31 @@ export class AddonCompetencyPlanPage implements OnInit {
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        this.fetchLearningPlan().finally(() => {
 | 
			
		||||
            this.loaded = true;
 | 
			
		||||
        });
 | 
			
		||||
    get plan(): AddonCompetencyDataForPlanPageWSResponse | undefined {
 | 
			
		||||
        return this.competencies.getSource().plan;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get user(): CoreUserProfile | undefined {
 | 
			
		||||
        return this.competencies.getSource().user;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async ngOnInit(): Promise<void> {
 | 
			
		||||
        await this.fetchLearningPlan();
 | 
			
		||||
        await this.plans.start();
 | 
			
		||||
        await this.competencies.start();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    ngOnDestroy(): void {
 | 
			
		||||
        this.plans.destroy();
 | 
			
		||||
        this.competencies.destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -60,40 +92,23 @@ export class AddonCompetencyPlanPage implements OnInit {
 | 
			
		||||
     */
 | 
			
		||||
    protected async fetchLearningPlan(): Promise<void> {
 | 
			
		||||
        try {
 | 
			
		||||
            const plan = await AddonCompetency.getLearningPlan(this.planId);
 | 
			
		||||
            plan.plan.statusname = AddonCompetencyHelper.getPlanStatusName(plan.plan.status);
 | 
			
		||||
 | 
			
		||||
            // Get the user profile image.
 | 
			
		||||
            this.user = await AddonCompetencyHelper.getProfile(plan.plan.userid);
 | 
			
		||||
 | 
			
		||||
            this.plan = plan;
 | 
			
		||||
            await this.competencies.getSource().reload();
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            CoreDomUtils.showErrorModalDefault(error, 'Error getting learning plan data.');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Navigates to a particular competency.
 | 
			
		||||
     *
 | 
			
		||||
     * @param competencyId
 | 
			
		||||
     */
 | 
			
		||||
    openCompetency(competencyId: number): void {
 | 
			
		||||
        CoreNavigator.navigate('./' + competencyId, {
 | 
			
		||||
            params: { userId: this.user?.id },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Refreshes the learning plan.
 | 
			
		||||
     *
 | 
			
		||||
     * @param refresher Refresher.
 | 
			
		||||
     */
 | 
			
		||||
    refreshLearningPlan(refresher: IonRefresher): void {
 | 
			
		||||
        AddonCompetency.invalidateLearningPlan(this.planId).finally(() => {
 | 
			
		||||
    async refreshLearningPlan(refresher: IonRefresher): Promise<void> {
 | 
			
		||||
        await this.competencies.getSource().invalidateCache();
 | 
			
		||||
 | 
			
		||||
        this.fetchLearningPlan().finally(() => {
 | 
			
		||||
            refresher?.complete();
 | 
			
		||||
        });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,12 +16,10 @@ import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
 | 
			
		||||
import { IonRefresher } from '@ionic/angular';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
 | 
			
		||||
import { AddonCompetencyProvider, AddonCompetencyPlan, AddonCompetency } from '../../services/competency';
 | 
			
		||||
import { AddonCompetencyHelper } from '../../services/competency-helper';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CorePageItemsListManager } from '@classes/page-items-list-manager';
 | 
			
		||||
import { ADDON_COMPETENCY_COMPETENCIES_PAGE } from '@addons/competency/competency.module';
 | 
			
		||||
import { Params } from '@angular/router';
 | 
			
		||||
import { AddonCompetencyPlanFormatted, AddonCompetencyPlansSource } from '@addons/competency/classes/competency-plans-source';
 | 
			
		||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
 | 
			
		||||
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page that displays the list of learning plans.
 | 
			
		||||
@ -34,13 +32,13 @@ export class AddonCompetencyPlanListPage implements AfterViewInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
    @ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
 | 
			
		||||
 | 
			
		||||
    protected userId?: number;
 | 
			
		||||
    plans: AddonCompetencyPlanListManager;
 | 
			
		||||
    plans: CoreListItemsManager<AddonCompetencyPlanFormatted, AddonCompetencyPlansSource>;
 | 
			
		||||
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.userId = CoreNavigator.getRouteNumberParam('userId');
 | 
			
		||||
        const userId = CoreNavigator.getRouteNumberParam('userId');
 | 
			
		||||
        const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(AddonCompetencyPlansSource, [userId]);
 | 
			
		||||
 | 
			
		||||
        this.plans = new AddonCompetencyPlanListManager(AddonCompetencyPlanListPage, this.userId);
 | 
			
		||||
        this.plans = new CoreListItemsManager(source, AddonCompetencyPlanListPage);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -59,23 +57,7 @@ export class AddonCompetencyPlanListPage implements AfterViewInit, OnDestroy {
 | 
			
		||||
     */
 | 
			
		||||
    protected async fetchLearningPlans(): Promise<void> {
 | 
			
		||||
        try {
 | 
			
		||||
            const plans = await AddonCompetency.getLearningPlans(this.userId);
 | 
			
		||||
            plans.forEach((plan: AddonCompetencyPlanFormatted) => {
 | 
			
		||||
                plan.statusname = AddonCompetencyHelper.getPlanStatusName(plan.status);
 | 
			
		||||
                switch (plan.status) {
 | 
			
		||||
                    case AddonCompetencyProvider.STATUS_ACTIVE:
 | 
			
		||||
                        plan.statuscolor = 'success';
 | 
			
		||||
                        break;
 | 
			
		||||
                    case AddonCompetencyProvider.STATUS_COMPLETE:
 | 
			
		||||
                        plan.statuscolor = 'danger';
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        plan.statuscolor = 'warning';
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            this.plans.setItems(plans);
 | 
			
		||||
 | 
			
		||||
            await this.plans.load();
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            CoreDomUtils.showErrorModalDefault(error, 'Error getting learning plans data.');
 | 
			
		||||
        }
 | 
			
		||||
@ -86,12 +68,12 @@ export class AddonCompetencyPlanListPage implements AfterViewInit, OnDestroy {
 | 
			
		||||
     *
 | 
			
		||||
     * @param refresher Refresher.
 | 
			
		||||
     */
 | 
			
		||||
    refreshLearningPlans(refresher: IonRefresher): void {
 | 
			
		||||
        AddonCompetency.invalidateLearningPlans(this.userId).finally(() => {
 | 
			
		||||
    async refreshLearningPlans(refresher: IonRefresher): Promise<void> {
 | 
			
		||||
        await this.plans.getSource().invalidateCache();
 | 
			
		||||
 | 
			
		||||
        this.fetchLearningPlans().finally(() => {
 | 
			
		||||
            refresher?.complete();
 | 
			
		||||
        });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -102,43 +84,3 @@ export class AddonCompetencyPlanListPage implements AfterViewInit, OnDestroy {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Competency plan with some calculated data.
 | 
			
		||||
 */
 | 
			
		||||
type AddonCompetencyPlanFormatted = AddonCompetencyPlan & {
 | 
			
		||||
    statuscolor?: string; // Calculated in the app. Color of the plan's status.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helper class to manage plan list.
 | 
			
		||||
 */
 | 
			
		||||
class AddonCompetencyPlanListManager extends CorePageItemsListManager<AddonCompetencyPlanFormatted> {
 | 
			
		||||
 | 
			
		||||
    private userId?: number;
 | 
			
		||||
 | 
			
		||||
    constructor(pageComponent: unknown, userId?: number) {
 | 
			
		||||
        super(pageComponent);
 | 
			
		||||
 | 
			
		||||
        this.userId = userId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    protected getItemPath(plan: AddonCompetencyPlanFormatted): string {
 | 
			
		||||
        return `${plan.id}/${ADDON_COMPETENCY_COMPETENCIES_PAGE}`;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    protected getItemQueryParams(): Params {
 | 
			
		||||
        if (this.userId) {
 | 
			
		||||
            return { userId: this.userId };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -64,8 +64,10 @@ export class CoreListItemsManager<
 | 
			
		||||
     *
 | 
			
		||||
     * @param splitView Split view component.
 | 
			
		||||
     */
 | 
			
		||||
    async start(splitView: CoreSplitViewComponent): Promise<void> {
 | 
			
		||||
    async start(splitView?: CoreSplitViewComponent): Promise<void> {
 | 
			
		||||
        if (splitView) {
 | 
			
		||||
            this.watchSplitViewOutlet(splitView);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Calculate current selected item.
 | 
			
		||||
        this.updateSelectedItem();
 | 
			
		||||
@ -172,7 +174,7 @@ export class CoreListItemsManager<
 | 
			
		||||
    protected updateSelectedItem(route: ActivatedRouteSnapshot | null = null): void {
 | 
			
		||||
        super.updateSelectedItem(route);
 | 
			
		||||
 | 
			
		||||
        if (CoreScreen.isMobile || this.selectedItem !== null || this.splitView?.isNested) {
 | 
			
		||||
        if (CoreScreen.isMobile || this.selectedItem !== null || !this.splitView || this.splitView.isNested) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user