forked from CIT/Vmeda.Online
		
	Merge pull request #4181 from albertgasset/MOBILE-4639
MOBILE-4639 badges: Support links to badges/badgeclass.php?id=X
This commit is contained in:
		
						commit
						1ef4aa6b2c
					
				
							
								
								
									
										36
									
								
								src/addons/badges/badgeclass-lazy.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/addons/badges/badgeclass-lazy.module.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
// (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 { NgModule } from '@angular/core';
 | 
			
		||||
import { RouterModule, Routes } from '@angular/router';
 | 
			
		||||
import { AddonBadgesBadgeClassPage } from './pages/badge-class/badge-class';
 | 
			
		||||
import { CoreSharedModule } from '@/core/shared.module';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
        path: ':badgeId',
 | 
			
		||||
        component: AddonBadgesBadgeClassPage,
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    imports: [
 | 
			
		||||
        RouterModule.forChild(routes),
 | 
			
		||||
        CoreSharedModule,
 | 
			
		||||
    ],
 | 
			
		||||
    declarations: [
 | 
			
		||||
        AddonBadgesBadgeClassPage,
 | 
			
		||||
    ],
 | 
			
		||||
})
 | 
			
		||||
export class AddonBadgeClassLazyModule {}
 | 
			
		||||
@ -17,6 +17,7 @@ import { Routes } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
import { AddonBadgesMyBadgesLinkHandler } from './services/handlers/mybadges-link';
 | 
			
		||||
import { AddonBadgesBadgeLinkHandler } from './services/handlers/badge-link';
 | 
			
		||||
import { AddonBadgesBadgeClassLinkHandler } from './services/handlers/badgeclass-link';
 | 
			
		||||
import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate';
 | 
			
		||||
import { CoreUserDelegate } from '@features/user/services/user-delegate';
 | 
			
		||||
import { AddonBadgesUserHandler } from './services/handlers/user';
 | 
			
		||||
@ -48,6 +49,10 @@ const mainMenuRoutes: Routes = [
 | 
			
		||||
        path: 'badges',
 | 
			
		||||
        loadChildren: () => import('./badges-lazy.module').then(m => m.AddonBadgesLazyModule),
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        path: 'badgeclass',
 | 
			
		||||
        loadChildren: () => import('./badgeclass-lazy.module').then(m => m.AddonBadgeClassLazyModule),
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
@ -61,6 +66,7 @@ const mainMenuRoutes: Routes = [
 | 
			
		||||
            useValue: () => {
 | 
			
		||||
                CoreContentLinksDelegate.registerHandler(AddonBadgesMyBadgesLinkHandler.instance);
 | 
			
		||||
                CoreContentLinksDelegate.registerHandler(AddonBadgesBadgeLinkHandler.instance);
 | 
			
		||||
                CoreContentLinksDelegate.registerHandler(AddonBadgesBadgeClassLinkHandler.instance);
 | 
			
		||||
                CoreUserDelegate.registerHandler(AddonBadgesUserHandler.instance);
 | 
			
		||||
                CorePushNotificationsDelegate.registerClickHandler(AddonBadgesPushClickHandler.instance);
 | 
			
		||||
                CoreTagAreaDelegate.registerHandler(AddonBadgesTagAreaHandler.instance);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										68
									
								
								src/addons/badges/pages/badge-class/badge-class.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/addons/badges/pages/badge-class/badge-class.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,68 @@
 | 
			
		||||
<ion-header>
 | 
			
		||||
    <ion-toolbar>
 | 
			
		||||
        <ion-buttons slot="start">
 | 
			
		||||
            <ion-back-button [text]="'core.back' | translate" />
 | 
			
		||||
        </ion-buttons>
 | 
			
		||||
        <ion-title>
 | 
			
		||||
            <h1 *ngIf="badge">{{ badge.name }}</h1>
 | 
			
		||||
            <h1 *ngIf="!badge">{{ 'addon.badges.badgedetails' | translate }}</h1>
 | 
			
		||||
        </ion-title>
 | 
			
		||||
    </ion-toolbar>
 | 
			
		||||
</ion-header>
 | 
			
		||||
<ion-content class="limited-width">
 | 
			
		||||
    <ion-refresher slot="fixed" [disabled]="!badgeLoaded" (ionRefresh)="refreshBadgeClass($event.target)">
 | 
			
		||||
        <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}" />
 | 
			
		||||
    </ion-refresher>
 | 
			
		||||
    <core-loading [hideUntil]="badgeLoaded">
 | 
			
		||||
        <ng-container *ngIf="badge">
 | 
			
		||||
            <ion-item-group>
 | 
			
		||||
                <ion-item class="ion-text-wrap ion-text-center">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <img *ngIf="badge.image" class="large-avatar" [url]="badge.image" core-external-content [alt]="badge.name" />
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="badge.name">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <p class="item-heading">{{ 'core.name' | translate}}</p>
 | 
			
		||||
                        <p>{{ badge.name }}</p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="badge.issuer">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <p class="item-heading">{{ 'addon.badges.issuername' | translate}}</p>
 | 
			
		||||
                        <p>{{ badge.issuer }}</p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="badge.coursefullname">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <p class="item-heading">{{ 'core.course' | translate}}</p>
 | 
			
		||||
                        <p>
 | 
			
		||||
                            <core-format-text [text]="badge.coursefullname" contextLevel="course" [contextInstanceId]="badge.courseid" />
 | 
			
		||||
                        </p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="badge.description">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <p class="item-heading">{{ 'core.description' | translate}}</p>
 | 
			
		||||
                        <p>{{ badge.description }}</p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
            </ion-item-group>
 | 
			
		||||
 | 
			
		||||
            <!-- Competencies alignment -->
 | 
			
		||||
            <ion-item-group *ngIf="badge.alignment?.length">
 | 
			
		||||
                <ion-item-divider>
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <h2>{{ 'addon.badges.alignment' | translate}}</h2>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item-divider>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngFor="let alignment of badge.alignment" [href]="alignment.targetUrl" core-link
 | 
			
		||||
                    [autoLogin]="false">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <p class="item-heading">{{ alignment.targetName }}</p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
            </ion-item-group>
 | 
			
		||||
        </ng-container>
 | 
			
		||||
    </core-loading>
 | 
			
		||||
</ion-content>
 | 
			
		||||
							
								
								
									
										91
									
								
								src/addons/badges/pages/badge-class/badge-class.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/addons/badges/pages/badge-class/badge-class.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
			
		||||
// (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 { Component, OnInit } from '@angular/core';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
import { CoreUtils } from '@services/utils/utils';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { ActivatedRoute } from '@angular/router';
 | 
			
		||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
 | 
			
		||||
import { CoreTime } from '@singletons/time';
 | 
			
		||||
import { AddonBadges, AddonBadgesBadgeClass } from '../../services/badges';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page that displays a badge class.
 | 
			
		||||
 */
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'page-addon-badges-badge-class',
 | 
			
		||||
    templateUrl: 'badge-class.html',
 | 
			
		||||
})
 | 
			
		||||
export class AddonBadgesBadgeClassPage implements OnInit {
 | 
			
		||||
 | 
			
		||||
    protected badgeId = 0;
 | 
			
		||||
    protected logView: (badge: AddonBadgesBadgeClass) => void;
 | 
			
		||||
 | 
			
		||||
    badge?: AddonBadgesBadgeClass;
 | 
			
		||||
    badgeLoaded = false;
 | 
			
		||||
    currentTime = 0;
 | 
			
		||||
 | 
			
		||||
    constructor(protected route: ActivatedRoute) {
 | 
			
		||||
        this.badgeId = CoreNavigator.getRequiredRouteNumberParam('badgeId');
 | 
			
		||||
 | 
			
		||||
        this.logView = CoreTime.once((badge) => {
 | 
			
		||||
            CoreAnalytics.logEvent({
 | 
			
		||||
                type: CoreAnalyticsEventType.VIEW_ITEM,
 | 
			
		||||
                ws: 'core_badges_get_badge',
 | 
			
		||||
                name: badge.name,
 | 
			
		||||
                data: { id: this.badgeId, category: 'badges' },
 | 
			
		||||
                url: `/badges/badgeclass.php?id=${this.badgeId}`,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * View loaded.
 | 
			
		||||
     */
 | 
			
		||||
    ngOnInit(): void {
 | 
			
		||||
        this.fetchBadgeClass().finally(() => {
 | 
			
		||||
            this.badgeLoaded = true;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Fetch the badge class required for the view.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns Promise resolved when done.
 | 
			
		||||
     */
 | 
			
		||||
    async fetchBadgeClass(): Promise<void> {
 | 
			
		||||
        try {
 | 
			
		||||
            this.badge = await AddonBadges.getBadgeClass(this.badgeId);
 | 
			
		||||
 | 
			
		||||
            this.logView(this.badge);
 | 
			
		||||
        } catch (message) {
 | 
			
		||||
            CoreDomUtils.showErrorModalDefault(message, 'Error getting badge data.');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Refresh the badge class.
 | 
			
		||||
     *
 | 
			
		||||
     * @param refresher Refresher.
 | 
			
		||||
     */
 | 
			
		||||
    async refreshBadgeClass(refresher?: HTMLIonRefresherElement): Promise<void> {
 | 
			
		||||
        await CoreUtils.ignoreErrors(AddonBadges.invalidateBadgeClass(this.badgeId));
 | 
			
		||||
 | 
			
		||||
        await this.fetchBadgeClass();
 | 
			
		||||
 | 
			
		||||
        refresher?.complete();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -111,11 +111,11 @@
 | 
			
		||||
                        <p>{{ badge.imagecaption }}</p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="course">
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="badge.coursefullname">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <p class="item-heading">{{ 'core.course' | translate}}</p>
 | 
			
		||||
                        <p>
 | 
			
		||||
                            <core-format-text [text]="course.fullname" contextLevel="course" [contextInstanceId]="courseId" />
 | 
			
		||||
                            <core-format-text [text]="badge.coursefullname" contextLevel="course" [contextInstanceId]="badge.courseid" />
 | 
			
		||||
                        </p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
@ -217,21 +217,16 @@
 | 
			
		||||
            </ion-item-group>
 | 
			
		||||
 | 
			
		||||
            <!-- Competencies alignment -->
 | 
			
		||||
            <ion-item-group *ngIf="badge.alignment">
 | 
			
		||||
            <ion-item-group *ngIf="badge.alignment?.length">
 | 
			
		||||
                <ion-item-divider>
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <h2>{{ 'addon.badges.alignment' | translate}}</h2>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item-divider>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngFor="let alignment of badge.alignment" [href]="alignment.targeturl" core-link
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngFor="let alignment of badge.alignment" [href]="alignment.targetUrl" core-link
 | 
			
		||||
                    [autoLogin]="false">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <p class="item-heading">{{ alignment.targetname }}</p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
                <ion-item class="ion-text-wrap" *ngIf="badge.alignment.length === 0">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <p class="item-heading">{{ 'addon.badges.noalignment' | translate}}</p>
 | 
			
		||||
                        <p class="item-heading">{{ alignment.targetName }}</p>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
            </ion-item-group>
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@ import { CoreSites } from '@services/sites';
 | 
			
		||||
import { CoreUser } from '@features/user/services/user';
 | 
			
		||||
import { AddonBadges, AddonBadgesUserBadge } from '../../services/badges';
 | 
			
		||||
import { CoreUtils } from '@services/utils/utils';
 | 
			
		||||
import { CoreCourses, CoreEnrolledCourseData } from '@features/courses/services/courses';
 | 
			
		||||
import { CoreCourses } from '@features/courses/services/courses';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { ActivatedRoute } from '@angular/router';
 | 
			
		||||
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
 | 
			
		||||
@ -30,7 +30,7 @@ import { CoreTime } from '@singletons/time';
 | 
			
		||||
import { CoreSharedModule } from '@/core/shared.module';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page that displays the list of calendar events.
 | 
			
		||||
 * Page that displays an issued badge.
 | 
			
		||||
 */
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'page-addon-badges-issued-badge',
 | 
			
		||||
@ -47,7 +47,6 @@ export class AddonBadgesIssuedBadgePage implements OnInit, OnDestroy {
 | 
			
		||||
    protected logView: (badge: AddonBadgesUserBadge) => void;
 | 
			
		||||
 | 
			
		||||
    courseId = 0;
 | 
			
		||||
    course?: CoreEnrolledCourseData;
 | 
			
		||||
    badge?: AddonBadgesUserBadge;
 | 
			
		||||
    badges?: CoreSwipeNavigationItemsManager;
 | 
			
		||||
    badgeLoaded = false;
 | 
			
		||||
@ -128,16 +127,18 @@ export class AddonBadgesIssuedBadgePage implements OnInit, OnDestroy {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.badge = badge;
 | 
			
		||||
            if (badge.courseid) {
 | 
			
		||||
            // Try to get course full name if not returned by the WS.
 | 
			
		||||
            if (badge.courseid && !badge.coursefullname) {
 | 
			
		||||
                try {
 | 
			
		||||
                    this.course = await CoreCourses.getUserCourse(badge.courseid, true);
 | 
			
		||||
                    const course = await CoreCourses.getUserCourse(badge.courseid, true);
 | 
			
		||||
                    badge.coursefullname = course.fullname;
 | 
			
		||||
                } catch {
 | 
			
		||||
                    // Maybe an old deleted course.
 | 
			
		||||
                    this.course = undefined;
 | 
			
		||||
                    // User is not enrolled in the course.
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.badge = badge;
 | 
			
		||||
 | 
			
		||||
            this.logView(badge);
 | 
			
		||||
        } catch (message) {
 | 
			
		||||
            CoreDomUtils.showErrorModalDefault(message, 'Error getting badge data.');
 | 
			
		||||
 | 
			
		||||
@ -78,15 +78,18 @@ export class AddonBadgesProvider {
 | 
			
		||||
            throw new CoreError('Invalid badges response');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // In 3.7, competencies was renamed to alignment. Rename the property in 3.6 too.
 | 
			
		||||
        response.badges.forEach((badge) => {
 | 
			
		||||
            // In 3.7, competencies was renamed to alignment.
 | 
			
		||||
            if (!badge.alignment && badge.competencies) {
 | 
			
		||||
                badge.alignment = badge.competencies.map((competency) => ({
 | 
			
		||||
                    targetName: competency.targetname,
 | 
			
		||||
                    targetUrl: competency.targeturl,
 | 
			
		||||
                }));
 | 
			
		||||
            }
 | 
			
		||||
            badge.alignment = badge.alignment || badge.competencies;
 | 
			
		||||
 | 
			
		||||
            // Check that the alignment is valid, they were broken in 3.7.
 | 
			
		||||
            if (badge.alignment && badge.alignment[0] && badge.alignment[0].targetname === undefined) {
 | 
			
		||||
                // If any badge lacks targetname it means they are affected by the Moodle bug, don't display them.
 | 
			
		||||
                delete badge.alignment;
 | 
			
		||||
            }
 | 
			
		||||
            // Exclude alignments without targetName, we can't display them.
 | 
			
		||||
            badge.alignment = badge.alignment?.filter((alignment) => alignment.targetName);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return response.badges;
 | 
			
		||||
@ -138,11 +141,15 @@ export class AddonBadgesProvider {
 | 
			
		||||
            data,
 | 
			
		||||
            preSets,
 | 
			
		||||
        );
 | 
			
		||||
        if (!response || !response.badge?.[0]) {
 | 
			
		||||
        const badge = response?.badge?.[0];
 | 
			
		||||
        if (!badge) {
 | 
			
		||||
            throw new CoreError('Invalid badge response');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return response.badge[0];
 | 
			
		||||
        // Exclude alignments without targetName, we can't display them.
 | 
			
		||||
        badge.alignment = badge.alignment?.filter((alignment) => alignment.targetName);
 | 
			
		||||
 | 
			
		||||
        return badge;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -158,6 +165,76 @@ export class AddonBadgesProvider {
 | 
			
		||||
        await site.invalidateWsCacheForKey(this.getUserBadgeByHashCacheKey(hash));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the cache key for the get badge class WS call.
 | 
			
		||||
     *
 | 
			
		||||
     * @param id Badge ID.
 | 
			
		||||
     * @returns Cache key.
 | 
			
		||||
     */
 | 
			
		||||
    protected getBadgeClassCacheKey(id: number): string {
 | 
			
		||||
        return ROOT_CACHE_KEY + 'badgeclass:' + id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get badge class.
 | 
			
		||||
     *
 | 
			
		||||
     * @param id Badge ID.
 | 
			
		||||
     * @param siteId Site ID. If not defined, current site.
 | 
			
		||||
     * @returns Promise to be resolved when the badge is retrieved.
 | 
			
		||||
     * @since 4.5
 | 
			
		||||
     */
 | 
			
		||||
    async getBadgeClass(id: number, siteId?: string): Promise<AddonBadgesBadgeClass> {
 | 
			
		||||
        const site = await CoreSites.getSite(siteId);
 | 
			
		||||
        const data: AddonBadgesGetBadgeClassWSParams = {
 | 
			
		||||
            id,
 | 
			
		||||
        };
 | 
			
		||||
        const preSets = {
 | 
			
		||||
            cacheKey: this.getBadgeClassCacheKey(id),
 | 
			
		||||
            updateFrequency: CoreSite.FREQUENCY_RARELY,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const response = await site.read<AddonBadgesGetBadgeClassWSResponse>(
 | 
			
		||||
            'core_badges_get_badge',
 | 
			
		||||
            data,
 | 
			
		||||
            preSets,
 | 
			
		||||
        );
 | 
			
		||||
        const badge = response?.badge;
 | 
			
		||||
        if (!badge) {
 | 
			
		||||
            throw new CoreError('Invalid badge response');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Exclude alignments without targetName, we can't display them.
 | 
			
		||||
        badge.alignment = badge.alignment?.filter((alignment) => alignment.targetName);
 | 
			
		||||
 | 
			
		||||
        return badge;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Invalidate get badge class WS call.
 | 
			
		||||
     *
 | 
			
		||||
     * @param id Badge ID.
 | 
			
		||||
     * @param siteId Site ID. If not defined, current site.
 | 
			
		||||
     * @returns Promise resolved when data is invalidated.ç
 | 
			
		||||
     * @since 4.5
 | 
			
		||||
     */
 | 
			
		||||
    async invalidateBadgeClass(id: number, siteId?: string): Promise<void> {
 | 
			
		||||
        const site = await CoreSites.getSite(siteId);
 | 
			
		||||
 | 
			
		||||
        await site.invalidateWsCacheForKey(this.getBadgeClassCacheKey(id));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns whether get badge class WS is available.
 | 
			
		||||
     *
 | 
			
		||||
     * @param siteId Site ID. If not defined, current site.
 | 
			
		||||
     * @returns If WS is available.
 | 
			
		||||
     */
 | 
			
		||||
    async isGetBadgeClassAvailable(siteId?: string): Promise<boolean> {
 | 
			
		||||
        const site = await CoreSites.getSite(siteId);
 | 
			
		||||
 | 
			
		||||
        return site.wsAvailable('core_badges_get_badge');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const AddonBadges = makeSingleton(AddonBadgesProvider);
 | 
			
		||||
@ -208,6 +285,7 @@ export type AddonBadgesUserBadge = {
 | 
			
		||||
    expireperiod?: number; // Expire period.
 | 
			
		||||
    type?: number; // Type.
 | 
			
		||||
    courseid?: number; // Course id.
 | 
			
		||||
    coursefullname?: string; // Full name of the course.
 | 
			
		||||
    message?: string; // Message.
 | 
			
		||||
    messagesubject?: string; // Message subject.
 | 
			
		||||
    attachment?: number; // Attachment.
 | 
			
		||||
@ -242,11 +320,11 @@ export type AddonBadgesUserBadge = {
 | 
			
		||||
    alignment?: { // @since 3.7. Calculated by the app for 3.6 sites. Badge alignments.
 | 
			
		||||
        id?: number; // Alignment id.
 | 
			
		||||
        badgeid?: number; // Badge id.
 | 
			
		||||
        targetname?: string; // Target name.
 | 
			
		||||
        targeturl?: string; // Target URL.
 | 
			
		||||
        targetdescription?: string; // Target description.
 | 
			
		||||
        targetframework?: string; // Target framework.
 | 
			
		||||
        targetcode?: string; // Target code.
 | 
			
		||||
        targetName?: string; // Target name.
 | 
			
		||||
        targetUrl?: string; // Target URL.
 | 
			
		||||
        targetDescription?: string; // Target description.
 | 
			
		||||
        targetFramework?: string; // Target framework.
 | 
			
		||||
        targetCode?: string; // Target code.
 | 
			
		||||
    }[];
 | 
			
		||||
    competencies?: { // @deprecatedonmoodle since 3.7. @since 3.6. In 3.7 it was renamed to alignment.
 | 
			
		||||
        id?: number; // Alignment id.
 | 
			
		||||
@ -280,3 +358,44 @@ type AddonBadgesGetUserBadgeByHashWSResponse = {
 | 
			
		||||
    badge: AddonBadgesUserBadge[];
 | 
			
		||||
    warnings?: CoreWSExternalWarning[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Params of core_badges_get_badge WS.
 | 
			
		||||
 */
 | 
			
		||||
type AddonBadgesGetBadgeClassWSParams = {
 | 
			
		||||
    id: number; // Badge ID.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Data returned by core_badges_get_badge WS.
 | 
			
		||||
 */
 | 
			
		||||
type AddonBadgesGetBadgeClassWSResponse = {
 | 
			
		||||
    badge: AddonBadgesBadgeClass;
 | 
			
		||||
    warnings?: CoreWSExternalWarning[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Badge data returned by core_badges_get_badge WS.
 | 
			
		||||
 */
 | 
			
		||||
export type AddonBadgesBadgeClass = {
 | 
			
		||||
    type: string; // BadgeClass.
 | 
			
		||||
    id: string; // Unique identifier for this badgeclass (URL).
 | 
			
		||||
    issuer?: string; // Issuer for this badgeclass.
 | 
			
		||||
    name: string; // Name of the badgeclass.
 | 
			
		||||
    image: string; // URL to the image.
 | 
			
		||||
    description: string; // Description of the badge class.
 | 
			
		||||
    hostedUrl?: string; // Identifier of the open badge for this assertion.
 | 
			
		||||
    courseid?: number; // Course ID.
 | 
			
		||||
    coursefullname?: string; // Full name of the course.
 | 
			
		||||
    alignment?: { // Badge alignments.
 | 
			
		||||
        id?: number; // Alignment id.
 | 
			
		||||
        badgeid?: number; // Badge id.
 | 
			
		||||
        targetName?: string; // Target name.
 | 
			
		||||
        targetUrl?: string; // Target URL.
 | 
			
		||||
        targetDescription?: string; // Target description.
 | 
			
		||||
        targetFramework?: string; // Target framework.
 | 
			
		||||
        targetCode?: string; // Target code.
 | 
			
		||||
    }[];
 | 
			
		||||
    criteriaUrl?: string; // Criteria URL.
 | 
			
		||||
    criteriaNarrative?: string; // Criteria narrative.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,7 @@ import { makeSingleton } from '@singletons';
 | 
			
		||||
import { AddonBadgesHelper } from '../badges-helper';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handler to treat links to user participants page.
 | 
			
		||||
 * Handler to treat links to issued badges.
 | 
			
		||||
 */
 | 
			
		||||
@Injectable({ providedIn: 'root' })
 | 
			
		||||
export class AddonBadgesBadgeLinkHandlerService extends CoreContentLinksHandlerBase {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										56
									
								
								src/addons/badges/services/handlers/badgeclass-link.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/addons/badges/services/handlers/badgeclass-link.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
			
		||||
// (C) Copyright 2015 Moodle Pty Ltd.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
 | 
			
		||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { makeSingleton } from '@singletons';
 | 
			
		||||
import { AddonBadges } from '../badges';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handler to treat links to badge classes.
 | 
			
		||||
 */
 | 
			
		||||
@Injectable({ providedIn: 'root' })
 | 
			
		||||
export class AddonBadgesBadgeClassLinkHandlerService extends CoreContentLinksHandlerBase {
 | 
			
		||||
 | 
			
		||||
    name = 'AddonBadgesBadgeClassLinkHandler';
 | 
			
		||||
    pattern = /\/badges\/badgeclass\.php.*([?&]id=)/;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    getActions(siteIds: string[], url: string, params: Record<string, string>): CoreContentLinksAction[] {
 | 
			
		||||
 | 
			
		||||
        return [{
 | 
			
		||||
            action: async (siteId: string): Promise<void> => {
 | 
			
		||||
                await CoreNavigator.navigateToSitePath(`/badgeclass/${params.id}`, { siteId });
 | 
			
		||||
            },
 | 
			
		||||
        }];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async isEnabled(siteId: string): Promise<boolean> {
 | 
			
		||||
        const pluginEnabled = await AddonBadges.isPluginEnabled(siteId);
 | 
			
		||||
        const wsAvailable = await AddonBadges.isGetBadgeClassAvailable(siteId);
 | 
			
		||||
 | 
			
		||||
        return pluginEnabled && wsAvailable;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const AddonBadgesBadgeClassLinkHandler = makeSingleton(AddonBadgesBadgeClassLinkHandlerService);
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user