diff --git a/src/addons/badges/badges-lazy.module.ts b/src/addons/badges/badges-lazy.module.ts index f88a84958..2245f6fdb 100644 --- a/src/addons/badges/badges-lazy.module.ts +++ b/src/addons/badges/badges-lazy.module.ts @@ -12,29 +12,60 @@ // See the License for the specific language governing permissions and // limitations under the License. +import { CommonModule } from '@angular/common'; +import { IonicModule } from '@ionic/angular'; import { NgModule } from '@angular/core'; -import { Route, RouterModule, Routes } from '@angular/router'; +import { RouterModule, Routes } from '@angular/router'; +import { TranslateModule } from '@ngx-translate/core'; +import { conditionalRoutes } from '@/app/app-routing.module'; +import { CoreScreen } from '@services/screen'; +import { CoreSharedModule } from '@/core/shared.module'; -export const AddonBadgesIssueRoute: Route = { - path: 'issue', - loadChildren: () => import('./pages/issued-badge/issued-badge.module').then( m => m.AddonBadgesIssuedBadgePageModule), -}; +import { AddonBadgesIssuedBadgePage } from './pages/issued-badge/issued-badge'; +import { AddonBadgesUserBadgesPage } from './pages/user-badges/user-badges'; -const routes: Routes = [ +const mobileRoutes: Routes = [ { path: '', - redirectTo: 'user', pathMatch: 'full', + component: AddonBadgesUserBadgesPage, }, - AddonBadgesIssueRoute, { - path: 'user', - loadChildren: () => import('./pages/user-badges/user-badges.module').then( m => m.AddonBadgesUserBadgesPageModule), + path: ':badgeHash', + component: AddonBadgesIssuedBadgePage, }, ]; +const tabletRoutes: Routes = [ + { + path: '', + component: AddonBadgesUserBadgesPage, + children: [ + { + path: ':badgeHash', + component: AddonBadgesIssuedBadgePage, + }, + ], + }, +]; + +const routes: Routes = [ + ...conditionalRoutes(mobileRoutes, () => CoreScreen.instance.isMobile), + ...conditionalRoutes(tabletRoutes, () => CoreScreen.instance.isTablet), +]; + @NgModule({ - imports: [RouterModule.forChild(routes)], + imports: [ + RouterModule.forChild(routes), + CommonModule, + IonicModule, + TranslateModule.forChild(), + CoreSharedModule, + ], + declarations: [ + AddonBadgesUserBadgesPage, + AddonBadgesIssuedBadgePage, + ], }) export class AddonBadgesLazyModule {} diff --git a/src/addons/badges/pages/issued-badge/issued-badge.module.ts b/src/addons/badges/pages/issued-badge/issued-badge.module.ts deleted file mode 100644 index dcf0c421c..000000000 --- a/src/addons/badges/pages/issued-badge/issued-badge.module.ts +++ /dev/null @@ -1,44 +0,0 @@ -// (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 { IonicModule } from '@ionic/angular'; -import { TranslateModule } from '@ngx-translate/core'; -import { RouterModule, Routes } from '@angular/router'; -import { CommonModule } from '@angular/common'; - -import { CoreSharedModule } from '@/core/shared.module'; -import { AddonBadgesIssuedBadgePage } from './issued-badge.page'; - -const routes: Routes = [ - { - path: '', - component: AddonBadgesIssuedBadgePage, - }, -]; - -@NgModule({ - imports: [ - RouterModule.forChild(routes), - CommonModule, - IonicModule, - TranslateModule.forChild(), - CoreSharedModule, - ], - declarations: [ - AddonBadgesIssuedBadgePage, - ], - exports: [RouterModule], -}) -export class AddonBadgesIssuedBadgePageModule {} diff --git a/src/addons/badges/pages/issued-badge/issued-badge.page.ts b/src/addons/badges/pages/issued-badge/issued-badge.ts similarity index 100% rename from src/addons/badges/pages/issued-badge/issued-badge.page.ts rename to src/addons/badges/pages/issued-badge/issued-badge.ts diff --git a/src/addons/badges/pages/user-badges/user-badges.html b/src/addons/badges/pages/user-badges/user-badges.html index 684182843..509496363 100644 --- a/src/addons/badges/pages/user-badges/user-badges.html +++ b/src/addons/badges/pages/user-badges/user-badges.html @@ -8,17 +8,17 @@ - + - - + - - + + diff --git a/src/addons/badges/pages/user-badges/user-badges.module.ts b/src/addons/badges/pages/user-badges/user-badges.module.ts deleted file mode 100644 index 10d3a6e86..000000000 --- a/src/addons/badges/pages/user-badges/user-badges.module.ts +++ /dev/null @@ -1,63 +0,0 @@ -// (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 { IonicModule } from '@ionic/angular'; -import { TranslateModule } from '@ngx-translate/core'; -import { RouterModule, Routes } from '@angular/router'; -import { CommonModule } from '@angular/common'; -import { conditionalRoutes } from '@/app/app-routing.module'; -import { CoreScreen } from '@services/screen'; - -import { CoreSharedModule } from '@/core/shared.module'; -import { AddonBadgesUserBadgesPage } from './user-badges.page'; -import { AddonBadgesIssueRoute } from '@addons/badges/badges-lazy.module'; - -const mobileRoutes: Routes = [ - { - path: '', - component: AddonBadgesUserBadgesPage, - }, - AddonBadgesIssueRoute, -]; - -const tabletRoutes: Routes = [ - { - path: '', - component: AddonBadgesUserBadgesPage, - children: [ - AddonBadgesIssueRoute, - ], - }, -]; - -const routes: Routes = [ - ...conditionalRoutes(mobileRoutes, () => CoreScreen.instance.isMobile), - ...conditionalRoutes(tabletRoutes, () => CoreScreen.instance.isTablet), -]; - -@NgModule({ - imports: [ - RouterModule.forChild(routes), - CommonModule, - IonicModule, - TranslateModule.forChild(), - CoreSharedModule, - ], - declarations: [ - AddonBadgesUserBadgesPage, - ], - exports: [RouterModule], -}) -export class AddonBadgesUserBadgesPageModule {} diff --git a/src/addons/badges/pages/user-badges/user-badges.page.ts b/src/addons/badges/pages/user-badges/user-badges.page.ts deleted file mode 100644 index 75087bfc4..000000000 --- a/src/addons/badges/pages/user-badges/user-badges.page.ts +++ /dev/null @@ -1,106 +0,0 @@ -// (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 { IonRefresher } from '@ionic/angular'; -import { AddonBadges, AddonBadgesUserBadge } from '../../services/badges'; -import { CoreTimeUtils } from '@services/utils/time'; -import { CoreDomUtils } from '@services/utils/dom'; -import { CoreSites } from '@services/sites'; -import { CoreUtils } from '@services/utils/utils'; -import { CoreNavigator } from '@services/navigator'; -import { CoreScreen } from '@services/screen'; - -/** - * Page that displays the list of calendar events. - */ -@Component({ - selector: 'page-addon-badges-user-badges', - templateUrl: 'user-badges.html', -}) -export class AddonBadgesUserBadgesPage implements OnInit { - - courseId = 0; - userId!: number; - - badgesLoaded = false; - badges: AddonBadgesUserBadge[] = []; - currentTime = 0; - badgeHash!: string; - - /** - * View loaded. - */ - ngOnInit(): void { - - this.courseId = CoreNavigator.instance.getRouteNumberParam('courseId') || this.courseId; // Use 0 for site badges. - this.userId = CoreNavigator.instance.getRouteNumberParam('userId') || CoreSites.instance.getCurrentSite()!.getUserId(); - - this.fetchBadges().finally(() => { - if (!this.badgeHash && CoreScreen.instance.isTablet && this.badges.length > 0) { - // Take first and load it. - this.loadIssuedBadge(this.badges[0].uniquehash); - } - this.badgesLoaded = true; - }); - } - - /** - * Fetch all the badges required for the view. - * - * @return Promise resolved when done. - */ - async fetchBadges(): Promise { - this.currentTime = CoreTimeUtils.instance.timestamp(); - - try { - this.badges = await AddonBadges.instance.getUserBadges(this.courseId, this.userId); - } catch (message) { - CoreDomUtils.instance.showErrorModalDefault(message, 'Error getting badges data.'); - } - } - - /** - * Refresh the badges. - * - * @param refresher Refresher. - */ - async refreshBadges(refresher?: CustomEvent): Promise { - await CoreUtils.instance.ignoreErrors(Promise.all([ - AddonBadges.instance.invalidateUserBadges(this.courseId, this.userId), - ])); - - await CoreUtils.instance.ignoreErrors(Promise.all([ - this.fetchBadges(), - ])); - - refresher?.detail.complete(); - } - - /** - * Navigate to a particular badge. - * - * @param badgeHash Badge to load. - */ - loadIssuedBadge(badgeHash: string): void { - this.badgeHash = badgeHash; - const params = { courseId: this.courseId, userId: this.userId, badgeHash: badgeHash }; - - const splitViewLoaded = CoreNavigator.instance.isCurrentPathInTablet('**/badges/user/issue'); - const path = (splitViewLoaded ? '../' : '') + 'issue'; - - CoreNavigator.instance.navigate(path, { params }); - } - -} diff --git a/src/addons/badges/pages/user-badges/user-badges.ts b/src/addons/badges/pages/user-badges/user-badges.ts new file mode 100644 index 000000000..7144fec28 --- /dev/null +++ b/src/addons/badges/pages/user-badges/user-badges.ts @@ -0,0 +1,142 @@ +// (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 { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core'; +import { IonRefresher } from '@ionic/angular'; +import { AddonBadges, AddonBadgesUserBadge } from '../../services/badges'; +import { CoreTimeUtils } from '@services/utils/time'; +import { CoreDomUtils } from '@services/utils/dom'; +import { CoreSites } from '@services/sites'; +import { CoreUtils } from '@services/utils/utils'; +import { CorePageItemsListManager } from '@classes/page-items-list-manager'; +import { ActivatedRoute, ActivatedRouteSnapshot, Params } from '@angular/router'; +import { CoreSplitViewComponent } from '@components/split-view/split-view'; +import { CoreObject } from '@singletons/object'; + +/** + * Page that displays the list of calendar events. + */ +@Component({ + selector: 'page-addon-badges-user-badges', + templateUrl: 'user-badges.html', +}) +export class AddonBadgesUserBadgesPage implements AfterViewInit, OnDestroy { + + currentTime = 0; + badges: AddonBadgesUserBadgesManager; + + @ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent; + + constructor(route: ActivatedRoute) { + const courseId = parseInt(route.snapshot.queryParams.courseId ?? 0); // Use 0 for site badges. + const userId = parseInt(route.snapshot.queryParams.userId ?? CoreSites.instance.getCurrentSiteUserId()); + + this.badges = new AddonBadgesUserBadgesManager(AddonBadgesUserBadgesPage, courseId, userId); + } + + /** + * @inheritdoc + */ + async ngAfterViewInit(): Promise { + await this.fetchInitialBadges(); + + this.badges.watchSplitViewOutlet(this.splitView); + this.badges.start(); + } + + /** + * @inheritdoc + */ + ngOnDestroy(): void { + this.badges.destroy(); + } + + /** + * Refresh the badges. + * + * @param refresher Refresher. + */ + async refreshBadges(refresher?: IonRefresher): Promise { + await CoreUtils.instance.ignoreErrors(AddonBadges.instance.invalidateUserBadges(this.badges.courseId, this.badges.userId)); + await CoreUtils.instance.ignoreErrors(this.fetchBadges()); + + refresher?.complete(); + } + + /** + * Obtain the initial list of badges. + */ + private async fetchInitialBadges(): Promise { + this.currentTime = CoreTimeUtils.instance.timestamp(); + + try { + await this.fetchBadges(); + } catch (message) { + CoreDomUtils.instance.showErrorModalDefault(message, 'Error loading badges'); + + this.badges.setItems([]); + } + } + + /** + * Update the list of badges. + */ + private async fetchBadges(): Promise { + const badges = await AddonBadges.instance.getUserBadges(this.badges.courseId, this.badges.userId); + + this.badges.setItems(badges); + } + +} + +/** + * Helper class to manage badges. + */ +class AddonBadgesUserBadgesManager extends CorePageItemsListManager { + + courseId: number; + userId: number; + + constructor(pageComponent: unknown, courseId: number, userId: number) { + super(pageComponent); + + this.courseId = courseId; + this.userId = userId; + } + + /** + * @inheritdoc + */ + protected getItemPath(badge: AddonBadgesUserBadge): string { + return badge.uniquehash; + } + + /** + * @inheritdoc + */ + protected getItemQueryParams(): Params { + return CoreObject.withoutEmpty({ + courseId: this.courseId, + userId: this.userId, + }); + } + + /** + * @inheritdoc + */ + protected getSelectedItemPath(route: ActivatedRouteSnapshot): string | null { + return route.params.badgeHash ?? null; + } + +} diff --git a/src/addons/badges/services/handlers/badge-link.ts b/src/addons/badges/services/handlers/badge-link.ts index 617bddc50..7d2ffb80f 100644 --- a/src/addons/badges/services/handlers/badge-link.ts +++ b/src/addons/badges/services/handlers/badge-link.ts @@ -43,13 +43,7 @@ export class AddonBadgesBadgeLinkHandlerService extends CoreContentLinksHandlerB return [{ action: (siteId: string): void => { - CoreNavigator.instance.navigateToSitePath( - '/badges/issue', - { - siteId, - params: { courseId: 0, badgeHash: params.hash }, - }, - ); + CoreNavigator.instance.navigateToSitePath(`/badges/${params.hash}`, { siteId }); }, }]; } diff --git a/src/addons/badges/services/handlers/mybadges-link.ts b/src/addons/badges/services/handlers/mybadges-link.ts index 519b8990a..aab4b9a01 100644 --- a/src/addons/badges/services/handlers/mybadges-link.ts +++ b/src/addons/badges/services/handlers/mybadges-link.ts @@ -37,7 +37,7 @@ export class AddonBadgesMyBadgesLinkHandlerService extends CoreContentLinksHandl getActions(): CoreContentLinksAction[] { return [{ action: (siteId: string): void => { - CoreNavigator.instance.navigateToSitePath('/badges/user', { siteId }); + CoreNavigator.instance.navigateToSitePath('/badges', { siteId }); }, }]; } diff --git a/src/addons/badges/services/handlers/push-click.ts b/src/addons/badges/services/handlers/push-click.ts index e3a834f3c..28e829f64 100644 --- a/src/addons/badges/services/handlers/push-click.ts +++ b/src/addons/badges/services/handlers/push-click.ts @@ -59,9 +59,8 @@ export class AddonBadgesPushClickHandlerService implements CorePushNotifications if (data.hash) { // We have the hash, open the badge directly. - await CoreNavigator.instance.navigateToSitePath('/badges/issue', { + await CoreNavigator.instance.navigateToSitePath(`/badges/${data.hash}`, { siteId: notification.site, - params: { courseId: 0, badgeHash: data.hash }, }); return; @@ -76,7 +75,7 @@ export class AddonBadgesPushClickHandlerService implements CorePushNotifications ), ); - await CoreNavigator.instance.navigateToSitePath('/badges/user', { siteId: notification.site }); + await CoreNavigator.instance.navigateToSitePath('/badges', { siteId: notification.site }); } } diff --git a/src/addons/badges/services/handlers/user.ts b/src/addons/badges/services/handlers/user.ts index 0aed8ef9c..0c422af21 100644 --- a/src/addons/badges/services/handlers/user.ts +++ b/src/addons/badges/services/handlers/user.ts @@ -18,6 +18,7 @@ import { CoreUserProfile } from '@features/user/services/user'; import { CoreUserDelegateService, CoreUserProfileHandler, CoreUserProfileHandlerData } from '@features/user/services/user-delegate'; import { CoreNavigator } from '@services/navigator'; import { makeSingleton } from '@singletons'; +import { CoreObject } from '@singletons/object'; import { AddonBadges } from '../badges'; /** @@ -72,10 +73,9 @@ export class AddonBadgesUserHandlerService implements CoreUserProfileHandler { action: (event, user, courseId): void => { event.preventDefault(); event.stopPropagation(); - CoreNavigator.instance.navigateToSitePath( - '/badges/user', - { params: { courseId: courseId || 0, userId: user.id } }, - ); + CoreNavigator.instance.navigateToSitePath('/badges', { + params: CoreObject.withoutEmpty({ courseId, userId: user.id }), + }); }, }; }