From 9987c3bcf9bb7d90ba7712abc17c86a9555d482e Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Wed, 17 Nov 2021 12:35:44 +0100 Subject: [PATCH] MOBILE-3926 badges: Implement swipe navigation --- .../badges/classes/user-badges-source.ts | 42 ++ .../pages/issued-badge/issued-badge.html | 440 +++++++++--------- .../pages/issued-badge/issued-badge.page.ts | 50 +- .../pages/user-badges/user-badges.page.ts | 51 +- .../items-manager-sources-tracker.ts | 4 +- 5 files changed, 332 insertions(+), 255 deletions(-) create mode 100644 src/addons/badges/classes/user-badges-source.ts diff --git a/src/addons/badges/classes/user-badges-source.ts b/src/addons/badges/classes/user-badges-source.ts new file mode 100644 index 000000000..ee1b6ed5f --- /dev/null +++ b/src/addons/badges/classes/user-badges-source.ts @@ -0,0 +1,42 @@ +// (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 { CoreItemsManagerSource } from '@classes/items-management/items-manager-source'; +import { AddonBadges, AddonBadgesUserBadge } from '../services/badges'; + +/** + * Provides a collection of user badges. + */ +export class AddonBadgesUserBadgesSource extends CoreItemsManagerSource { + + readonly COURSE_ID: number; + readonly USER_ID: number; + + constructor(courseId: number, userId: number) { + super(); + + this.COURSE_ID = courseId; + this.USER_ID = userId; + } + + /** + * @inheritdoc + */ + protected async loadPageItems(): Promise<{ items: AddonBadgesUserBadge[]; hasMoreItems: boolean }> { + const badges = await AddonBadges.getUserBadges(this.COURSE_ID, this.USER_ID); + + return { items: badges, hasMoreItems: false }; + } + +} diff --git a/src/addons/badges/pages/issued-badge/issued-badge.html b/src/addons/badges/pages/issued-badge/issued-badge.html index d4865c4c9..4e7ac334e 100644 --- a/src/addons/badges/pages/issued-badge/issued-badge.html +++ b/src/addons/badges/pages/issued-badge/issued-badge.html @@ -10,239 +10,241 @@ - - - - - - - - - - {{ 'addon.badges.expired' | translate }} - - - - - - - - -

{{ 'addon.badges.recipientdetails' | translate}}

-
-
- - -

{{ 'core.name' | translate}}

-

{{ user.fullname }}

-
-
-
- - - - + + + + + + + -

{{ 'addon.badges.issuerdetails' | translate}}

-
-
- - -

{{ 'addon.badges.issuername' | translate}}

-

{{ badge.issuername }}

-
-
- - -

{{ 'addon.badges.contact' | translate}}

-

- {{ badge.issuercontact }} -

+ + + {{ 'addon.badges.expired' | translate }} +
- + -

{{ 'addon.badges.badgedetails' | translate}}

+

{{ 'addon.badges.recipientdetails' | translate}}

- +

{{ 'core.name' | translate}}

-

{{ badge.name }}

-
-
- - -

{{ 'addon.badges.version' | translate}}

-

{{ badge.version }}

-
-
- - -

{{ 'addon.badges.language' | translate}}

-

{{ badge.language }}

-
-
- - -

{{ 'core.description' | translate}}

-

{{ badge.description }}

-
-
- - -

{{ 'addon.badges.imageauthorname' | translate}}

-

{{ badge.imageauthorname }}

-
-
- - -

{{ 'addon.badges.imageauthoremail' | translate}}

-

- {{ badge.imageauthoremail }} -

-
-
- - -

{{ 'addon.badges.imageauthorurl' | translate}}

-

{{ badge.imageauthorurl }}

-
-
- - -

{{ 'addon.badges.imagecaption' | translate}}

-

{{ badge.imagecaption }}

-
-
- - -

{{ 'core.course' | translate}}

-

- - -

-
-
- -
- - - - -

{{ 'addon.badges.issuancedetails' | translate}}

-
-
- - -

{{ 'addon.badges.dateawarded' | translate}}

-

{{badge.dateissued * 1000 | coreFormatDate }}

-
-
- - -

{{ 'addon.badges.expirydate' | translate}}

-

- {{ badge.dateexpire * 1000 | coreFormatDate }} - - {{ 'addon.badges.warnexpired' | translate }} - -

-
-
- -
- - - - - -

{{ 'addon.badges.bendorsement' | translate}}

-
-
- - -

{{ 'addon.badges.issuername' | translate}}

-

{{ badge.endorsement.issuername }}

-
-
- - -

{{ 'addon.badges.issueremail' | translate}}

-

- - {{ badge.endorsement.issueremail }} - -

-
-
- - -

{{ 'addon.badges.issuerurl' | translate}}

-

{{ badge.endorsement.issuerurl }}

-
-
- - -

{{ 'addon.badges.dateawarded' | translate}}

-

{{ badge.endorsement.dateissued * 1000 | coreFormatDate }}

-
-
- - -

{{ 'addon.badges.claimid' | translate}}

-

{{ badge.endorsement.claimid }}

-
-
- - -

{{ 'addon.badges.claimcomment' | translate}}

-

{{ badge.endorsement.claimcomment }}

+

{{ user.fullname }}

- - - - -

{{ 'addon.badges.relatedbages' | translate}}

-
-
- - -

{{ relatedBadge.name }}

-
-
- - -

{{ 'addon.badges.norelated' | translate}}

-
-
-
+ + + + +

{{ 'addon.badges.issuerdetails' | translate}}

+
+
+ + +

{{ 'addon.badges.issuername' | translate}}

+

{{ badge.issuername }}

+
+
+ + +

{{ 'addon.badges.contact' | translate}}

+

+ {{ badge.issuercontact }} +

+
+
+
- - - - -

{{ 'addon.badges.alignment' | translate}}

-
-
- - -

{{ alignment.targetname }}

-
-
- - -

{{ 'addon.badges.noalignment' | translate}}

-
-
-
-
-
+ + + +

{{ 'addon.badges.badgedetails' | translate}}

+
+
+ + +

{{ 'core.name' | translate}}

+

{{ badge.name }}

+
+
+ + +

{{ 'addon.badges.version' | translate}}

+

{{ badge.version }}

+
+
+ + +

{{ 'addon.badges.language' | translate}}

+

{{ badge.language }}

+
+
+ + +

{{ 'core.description' | translate}}

+

{{ badge.description }}

+
+
+ + +

{{ 'addon.badges.imageauthorname' | translate}}

+

{{ badge.imageauthorname }}

+
+
+ + +

{{ 'addon.badges.imageauthoremail' | translate}}

+

+ {{ badge.imageauthoremail }} +

+
+
+ + +

{{ 'addon.badges.imageauthorurl' | translate}}

+

{{ badge.imageauthorurl }}

+
+
+ + +

{{ 'addon.badges.imagecaption' | translate}}

+

{{ badge.imagecaption }}

+
+
+ + +

{{ 'core.course' | translate}}

+

+ + +

+
+
+ +
+ + + + +

{{ 'addon.badges.issuancedetails' | translate}}

+
+
+ + +

{{ 'addon.badges.dateawarded' | translate}}

+

{{badge.dateissued * 1000 | coreFormatDate }}

+
+
+ + +

{{ 'addon.badges.expirydate' | translate}}

+

+ {{ badge.dateexpire * 1000 | coreFormatDate }} + + {{ 'addon.badges.warnexpired' | translate }} + +

+
+
+ +
+ + + + + +

{{ 'addon.badges.bendorsement' | translate}}

+
+
+ + +

{{ 'addon.badges.issuername' | translate}}

+

{{ badge.endorsement.issuername }}

+
+
+ + +

{{ 'addon.badges.issueremail' | translate}}

+

+ + {{ badge.endorsement.issueremail }} + +

+
+
+ + +

{{ 'addon.badges.issuerurl' | translate}}

+

{{ badge.endorsement.issuerurl }}

+
+
+ + +

{{ 'addon.badges.dateawarded' | translate}}

+

{{ badge.endorsement.dateissued * 1000 | coreFormatDate }}

+
+
+ + +

{{ 'addon.badges.claimid' | translate}}

+

{{ badge.endorsement.claimid }}

+
+
+ + +

{{ 'addon.badges.claimcomment' | translate}}

+

{{ badge.endorsement.claimcomment }}

+
+
+
+ + + + + +

{{ 'addon.badges.relatedbages' | translate}}

+
+
+ + +

{{ relatedBadge.name }}

+
+
+ + +

{{ 'addon.badges.norelated' | translate}}

+
+
+
+ + + + + +

{{ 'addon.badges.alignment' | translate}}

+
+
+ + +

{{ alignment.targetname }}

+
+
+ + +

{{ 'addon.badges.noalignment' | translate}}

+
+
+
+ + +
diff --git a/src/addons/badges/pages/issued-badge/issued-badge.page.ts b/src/addons/badges/pages/issued-badge/issued-badge.page.ts index 959ac2dac..bd9764a36 100644 --- a/src/addons/badges/pages/issued-badge/issued-badge.page.ts +++ b/src/addons/badges/pages/issued-badge/issued-badge.page.ts @@ -22,7 +22,10 @@ import { AddonBadges, AddonBadgesUserBadge } from '../../services/badges'; import { CoreUtils } from '@services/utils/utils'; import { CoreCourses, CoreEnrolledCourseData } from '@features/courses/services/courses'; import { CoreNavigator } from '@services/navigator'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, ActivatedRouteSnapshot, Params } from '@angular/router'; +import { CoreSwipeItemsManager } from '@classes/items-management/swipe-items-manager'; +import { CoreItemsManagerSourcesTracker } from '@classes/items-management/items-manager-sources-tracker'; +import { AddonBadgesUserBadgesSource } from '@addons/badges/classes/user-badges-source'; /** * Page that displays the list of calendar events. @@ -40,12 +43,11 @@ export class AddonBadgesIssuedBadgePage implements OnInit { user?: CoreUserProfile; course?: CoreEnrolledCourseData; badge?: AddonBadgesUserBadge; + badges?: AddonBadgesUserBadgesSwipeManager; badgeLoaded = false; currentTime = 0; - constructor( - protected route: ActivatedRoute, - ) { } + constructor(protected route: ActivatedRoute) { } /** * View loaded. @@ -58,6 +60,11 @@ export class AddonBadgesIssuedBadgePage implements OnInit { this.fetchIssuedBadge().finally(() => { this.badgeLoaded = true; }); + + const source = CoreItemsManagerSourcesTracker.getOrCreateSource(AddonBadgesUserBadgesSource, [this.courseId, this.userId]); + this.badges = new AddonBadgesUserBadgesSwipeManager(source); + + this.badges.start(); } /** @@ -110,3 +117,38 @@ export class AddonBadgesIssuedBadgePage implements OnInit { } } + +/** + * Helper to manage swiping within a collection of user badges. + */ +class AddonBadgesUserBadgesSwipeManager extends CoreSwipeItemsManager { + + /** + * @inheritdoc + */ + protected getItemPath(badge: AddonBadgesUserBadge): string { + return String(badge.uniquehash); + } + + /** + * @inheritdoc + */ + protected getItemQueryParams(): Params { + return { + courseId: this.getSource().COURSE_ID, + userId: this.getSource().USER_ID, + }; + } + + /** + * @inheritdoc + */ + protected getSelectedItemPath(route?: ActivatedRouteSnapshot | null): string | null { + if (!route) { + return null; + } + + return route.params.badgeHash; + } + +} diff --git a/src/addons/badges/pages/user-badges/user-badges.page.ts b/src/addons/badges/pages/user-badges/user-badges.page.ts index b5eef4a15..5900ff36a 100644 --- a/src/addons/badges/pages/user-badges/user-badges.page.ts +++ b/src/addons/badges/pages/user-badges/user-badges.page.ts @@ -19,10 +19,12 @@ 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 { Params } from '@angular/router'; import { CoreSplitViewComponent } from '@components/split-view/split-view'; import { CoreNavigator } from '@services/navigator'; +import { CoreListItemsManager } from '@classes/items-management/list-items-manager'; +import { AddonBadgesUserBadgesSource } from '@addons/badges/classes/user-badges-source'; +import { CoreItemsManagerSourcesTracker } from '@classes/items-management/items-manager-sources-tracker'; /** * Page that displays the list of calendar events. @@ -34,7 +36,7 @@ import { CoreNavigator } from '@services/navigator'; export class AddonBadgesUserBadgesPage implements AfterViewInit, OnDestroy { currentTime = 0; - badges: AddonBadgesUserBadgesManager; + badges: AddonBadgesUserBadgesListManager; @ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent; @@ -47,7 +49,10 @@ export class AddonBadgesUserBadgesPage implements AfterViewInit, OnDestroy { courseId = 0; } - this.badges = new AddonBadgesUserBadgesManager(AddonBadgesUserBadgesPage, courseId, userId); + this.badges = new AddonBadgesUserBadgesListManager( + CoreItemsManagerSourcesTracker.getOrCreateSource(AddonBadgesUserBadgesSource, [courseId, userId]), + AddonBadgesUserBadgesPage, + ); } /** @@ -72,8 +77,13 @@ export class AddonBadgesUserBadgesPage implements AfterViewInit, OnDestroy { * @param refresher Refresher. */ async refreshBadges(refresher?: IonRefresher): Promise { - await CoreUtils.ignoreErrors(AddonBadges.invalidateUserBadges(this.badges.courseId, this.badges.userId)); - await CoreUtils.ignoreErrors(this.fetchBadges()); + await CoreUtils.ignoreErrors( + AddonBadges.invalidateUserBadges( + this.badges.getSource().COURSE_ID, + this.badges.getSource().USER_ID, + ), + ); + await CoreUtils.ignoreErrors(this.badges.reload()); refresher?.complete(); } @@ -85,39 +95,20 @@ export class AddonBadgesUserBadgesPage implements AfterViewInit, OnDestroy { this.currentTime = CoreTimeUtils.timestamp(); try { - await this.fetchBadges(); + await this.badges.reload(); } catch (message) { CoreDomUtils.showErrorModalDefault(message, 'Error loading badges'); - this.badges.setItems([]); + this.badges.reset(); } } - /** - * Update the list of badges. - */ - private async fetchBadges(): Promise { - const badges = await AddonBadges.getUserBadges(this.badges.courseId, this.badges.userId); - - this.badges.setItems(badges); - } - } /** - * Helper class to manage badges. + * Helper class to manage badges list. */ -class AddonBadgesUserBadgesManager extends CorePageItemsListManager { - - courseId: number; - userId: number; - - constructor(pageComponent: unknown, courseId: number, userId: number) { - super(pageComponent); - - this.courseId = courseId; - this.userId = userId; - } +class AddonBadgesUserBadgesListManager extends CoreListItemsManager { /** * @inheritdoc @@ -131,8 +122,8 @@ class AddonBadgesUserBadgesManager extends CorePageItemsListManager