MOBILE-3934 grades: Add swipe navigation

main
Noel De Martin 2022-01-12 11:53:11 +01:00
parent 275991d9ef
commit 11c2468d58
5 changed files with 79 additions and 29 deletions

View File

@ -0,0 +1,41 @@
// (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 { CoreGrades } from '../services/grades';
import { CoreGradesGradeOverviewWithCourseData, CoreGradesHelper } from '../services/grades-helper';
/**
* Provides a collection of courses.
*/
export class CoreGradesCoursesSource extends CoreRoutedItemsManagerSource<CoreGradesGradeOverviewWithCourseData> {
/**
* @inheritdoc
*/
protected async loadPageItems(): Promise<{ items: CoreGradesGradeOverviewWithCourseData[] }> {
const grades = await CoreGrades.getCoursesGrades();
const courses = await CoreGradesHelper.getGradesCourseData(grades);
return { items: courses };
}
/**
* @inheritdoc
*/
getItemPath(course: CoreGradesGradeOverviewWithCourseData): string {
return course.courseid.toString();
}
}

View File

@ -22,6 +22,7 @@ const routes: Routes = [
{
path: '',
component: CoreGradesCoursePage,
data: { swipeEnabled: false },
},
];

View File

@ -4,11 +4,11 @@
<ion-back-button [text]="'core.back' | translate"></ion-back-button>
</ion-buttons>
<ion-title>
<h1>{{ 'core.grades.grades' | translate }}</h1>
<h1>{{ title }}</h1>
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-content [core-swipe-navigation]="courses">
<ion-refresher slot="fixed" [disabled]="!columns || !rows" (ionRefresh)="refreshGrades($event.target)">
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
</ion-refresher>

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { ActivatedRoute } from '@angular/router';
import { AfterViewInit, Component, ElementRef } from '@angular/core';
import { AfterViewInit, Component, ElementRef, OnDestroy } from '@angular/core';
import { IonRefresher } from '@ionic/angular';
import { CoreDomUtils } from '@services/utils/dom';
@ -28,6 +28,9 @@ import { CoreUtils } from '@services/utils/utils';
import { CoreNavigator } from '@services/navigator';
import { CoreScreen } from '@services/screen';
import { Translate } from '@singletons';
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
import { CoreGradesCoursesSource } from '@features/grades/classes/grades-courses-source';
/**
* Page that displays a course grades.
@ -37,12 +40,14 @@ import { Translate } from '@singletons';
templateUrl: 'course.html',
styleUrls: ['course.scss'],
})
export class CoreGradesCoursePage implements AfterViewInit {
export class CoreGradesCoursePage implements AfterViewInit, OnDestroy {
courseId!: number;
userId!: number;
expandLabel!: string;
collapseLabel!: string;
title?: string;
courses?: CoreSwipeNavigationItemsManager;
columns?: CoreGradesFormattedTableColumn[];
rows?: CoreGradesFormattedTableRow[];
totalColumnsSpan?: number;
@ -54,6 +59,12 @@ export class CoreGradesCoursePage implements AfterViewInit {
this.userId = CoreNavigator.getRouteNumberParam('userId', { route }) ?? CoreSites.getCurrentSiteUserId();
this.expandLabel = Translate.instant('core.expand');
this.collapseLabel = Translate.instant('core.collapse');
if (route.snapshot.data.swipeEnabled ?? true) {
const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(CoreGradesCoursesSource, []);
this.courses = new CoreSwipeNavigationItemsManager(source);
}
} catch (error) {
CoreDomUtils.showErrorModal(error);
@ -73,10 +84,18 @@ export class CoreGradesCoursePage implements AfterViewInit {
async ngAfterViewInit(): Promise<void> {
this.withinSplitView = !!this.element.nativeElement.parentElement?.closest('core-split-view');
await this.courses?.start();
await this.fetchInitialGrades();
await CoreGrades.logCourseGradesView(this.courseId, this.userId);
}
/**
* @inheritdoc
*/
ngOnDestroy(): void {
this.courses?.destroy();
}
/**
* Get aria label for row.
*
@ -151,6 +170,7 @@ export class CoreGradesCoursePage implements AfterViewInit {
const table = await CoreGrades.getCourseGradesTable(this.courseId, this.userId);
const formattedTable = await CoreGradesHelper.formatGradesTable(table);
this.title = formattedTable.rows[0]?.gradeitem ?? Translate.instant('core.grades.grades');
this.columns = formattedTable.columns;
this.rows = formattedTable.rows;
this.totalColumnsSpan = formattedTable.columns.reduce((total, column) => total + column.colspan, 0);

View File

@ -13,11 +13,12 @@
// limitations under the License.
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
import { CorePageItemsListManager } from '@classes/page-items-list-manager';
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
import { CoreSplitViewComponent } from '@components/split-view/split-view';
import { CoreGradesCoursesSource } from '@features/grades/classes/grades-courses-source';
import { CoreGrades } from '@features/grades/services/grades';
import { CoreGradesGradeOverviewWithCourseData, CoreGradesHelper } from '@features/grades/services/grades-helper';
import { IonRefresher } from '@ionic/angular';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
@ -31,10 +32,16 @@ import { CoreUtils } from '@services/utils/utils';
})
export class CoreGradesCoursesPage implements OnDestroy, AfterViewInit {
courses: CoreGradesCoursesManager = new CoreGradesCoursesManager(CoreGradesCoursesPage);
courses: CoreGradesCoursesManager;
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
constructor() {
const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(CoreGradesCoursesSource, []);
this.courses = new CoreGradesCoursesManager(source, CoreGradesCoursesPage);
}
/**
* @inheritdoc
*/
@ -58,7 +65,7 @@ export class CoreGradesCoursesPage implements OnDestroy, AfterViewInit {
*/
async refreshCourses(refresher: IonRefresher): Promise<void> {
await CoreUtils.ignoreErrors(CoreGrades.invalidateCoursesGradesData());
await CoreUtils.ignoreErrors(this.fetchCourses());
await CoreUtils.ignoreErrors(this.courses.reload());
refresher?.complete();
}
@ -68,37 +75,18 @@ export class CoreGradesCoursesPage implements OnDestroy, AfterViewInit {
*/
private async fetchInitialCourses(): Promise<void> {
try {
await this.fetchCourses();
await this.courses.load();
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'Error loading courses');
this.courses.setItems([]);
}
}
/**
* Update the list of courses.
*/
private async fetchCourses(): Promise<void> {
const grades = await CoreGrades.getCoursesGrades();
const courses = await CoreGradesHelper.getGradesCourseData(grades);
this.courses.setItems(courses);
}
}
/**
* Helper class to manage courses.
*/
class CoreGradesCoursesManager extends CorePageItemsListManager<CoreGradesGradeOverviewWithCourseData> {
/**
* @inheritdoc
*/
protected getItemPath(courseGrade: CoreGradesGradeOverviewWithCourseData): string {
return courseGrade.courseid.toString();
}
class CoreGradesCoursesManager extends CoreListItemsManager {
/**
* @inheritdoc