MOBILE-3629 grades: Handler and route fixes on grades

main
Pau Ferrer Ocaña 2021-03-10 13:56:40 +01:00
parent 5aaf4acea5
commit 29d0f006aa
8 changed files with 80 additions and 55 deletions

View File

@ -39,6 +39,10 @@ const routes: Routes = [
path: CoreGradesMainMenuHandlerService.PAGE_NAME, path: CoreGradesMainMenuHandlerService.PAGE_NAME,
loadChildren: () => import('@features/grades/grades-lazy.module').then(m => m.CoreGradesLazyModule), loadChildren: () => import('@features/grades/grades-lazy.module').then(m => m.CoreGradesLazyModule),
}, },
{
path: 'user-grades/:courseId',
loadChildren: () => import('@features/grades/grades-course-lazy.module').then(m => m.CoreGradesCourseLazyModule),
},
]; ];
const courseIndexRoutes: Routes = [ const courseIndexRoutes: Routes = [

View File

@ -12,7 +12,7 @@
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content> <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
</ion-refresher> </ion-refresher>
<core-loading [hideUntil]="grades.loaded" class="safe-area-page"> <core-loading [hideUntil]="grades.loaded" class="safe-area-page">
<core-empty-box *ngIf="grades.empty" icon="stats" [message]="'core.grades.nogradesreturned' | translate"> <core-empty-box *ngIf="grades.empty" icon="fas-chart-bar" [message]="'core.grades.nogradesreturned' | translate">
</core-empty-box> </core-empty-box>
<div *ngIf="!grades.empty" class="core-grades-container"> <div *ngIf="!grades.empty" class="core-grades-container">
<table cellspacing="0" cellpadding="0" class="core-grades-table"> <table cellspacing="0" cellpadding="0" class="core-grades-table">

View File

@ -45,9 +45,9 @@ export class CoreGradesCoursePage implements AfterViewInit, OnDestroy {
@ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent; @ViewChild(CoreSplitViewComponent) splitView!: CoreSplitViewComponent;
constructor(route: ActivatedRoute) { constructor(protected route: ActivatedRoute) {
const courseId = parseInt(route.snapshot.params.courseId ?? route.snapshot.queryParams.courseId); const courseId = CoreNavigator.getRouteNumberParam('courseId', { route })!;
const userId = parseInt(route.snapshot.queryParams.userId ?? CoreSites.getCurrentSiteUserId()); const userId = CoreNavigator.getRouteNumberParam('userId', { route }) ?? CoreSites.getCurrentSiteUserId();
const useSplitView = route.snapshot.data.useSplitView ?? true; const useSplitView = route.snapshot.data.useSplitView ?? true;
const outsideGradesTab = route.snapshot.data.outsideGradesTab ?? false; const outsideGradesTab = route.snapshot.data.outsideGradesTab ?? false;

View File

@ -14,7 +14,7 @@
<core-loading [hideUntil]="courses.loaded"> <core-loading [hideUntil]="courses.loaded">
<core-empty-box <core-empty-box
*ngIf="courses.empty" *ngIf="courses.empty"
icon="stats" icon="fas-chart-bar"
[message]="'core.grades.nogradesreturned' | translate" [message]="'core.grades.nogradesreturned' | translate"
></core-empty-box> ></core-empty-box>

View File

@ -19,6 +19,8 @@ import { CorePushNotifications } from '@features/pushnotifications/services/push
import { makeSingleton } from '@singletons'; import { makeSingleton } from '@singletons';
import { CoreLogger } from '@singletons/logger'; import { CoreLogger } from '@singletons/logger';
import { CoreWSExternalWarning } from '@services/ws'; import { CoreWSExternalWarning } from '@services/ws';
import { CoreSiteWSPreSets } from '@classes/site';
import { CoreError } from '@classes/errors/error';
/** /**
* Service to provide grade functionalities. * Service to provide grade functionalities.
@ -114,8 +116,8 @@ export class CoreGradesProvider {
const items = await this.getCourseGradesItems(courseId, userId, groupId, siteId, ignoreCache); const items = await this.getCourseGradesItems(courseId, userId, groupId, siteId, ignoreCache);
return items; return items;
} catch (error) { } catch {
// Ignore while solving MDL-57255 // Ignore while solving MDL-57255 (fixed on 3.2.1)
} }
} }
@ -151,13 +153,13 @@ export class CoreGradesProvider {
userid: userId, userid: userId,
groupid: groupId, groupid: groupId,
}; };
const preSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getCourseGradesItemsCacheKey(courseId, userId, groupId), cacheKey: this.getCourseGradesItemsCacheKey(courseId, userId, groupId),
}; };
if (ignoreCache) { if (ignoreCache) {
preSets['getFromCache'] = 0; preSets.getFromCache = false;
preSets['emergencyCache'] = 0; preSets.emergencyCache = false;
} }
const grades = await site.read<CoreGradesGetUserGradeItemsWSResponse>( const grades = await site.read<CoreGradesGetUserGradeItemsWSResponse>(
@ -167,7 +169,7 @@ export class CoreGradesProvider {
); );
if (!grades?.usergrades?.[0]) { if (!grades?.usergrades?.[0]) {
throw new Error('Couldn\'t get course grades items'); throw new CoreError('Couldn\'t get course grades items');
} }
return grades.usergrades[0].gradeitems; return grades.usergrades[0].gradeitems;
@ -198,19 +200,19 @@ export class CoreGradesProvider {
courseid: courseId, courseid: courseId,
userid: userId, userid: userId,
}; };
const preSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getCourseGradesCacheKey(courseId, userId), cacheKey: this.getCourseGradesCacheKey(courseId, userId),
}; };
if (ignoreCache) { if (ignoreCache) {
preSets['getFromCache'] = 0; preSets.getFromCache = false;
preSets['emergencyCache'] = 0; preSets.emergencyCache = false;
} }
const table = await site.read<CoreGradesGetUserGradesTableWSResponse>('gradereport_user_get_grades_table', params, preSets); const table = await site.read<CoreGradesGetUserGradesTableWSResponse>('gradereport_user_get_grades_table', params, preSets);
if (!table?.tables?.[0]) { if (!table?.tables?.[0]) {
throw new Error('Coudln\'t get course grades table'); throw new CoreError('Coudln\'t get course grades table');
} }
return table.tables[0]; return table.tables[0];
@ -228,7 +230,7 @@ export class CoreGradesProvider {
this.logger.debug('Get course grades'); this.logger.debug('Get course grades');
const params: CoreGradesGetOverviewCourseGradesWSParams = {}; const params: CoreGradesGetOverviewCourseGradesWSParams = {};
const preSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getCoursesGradesCacheKey(), cacheKey: this.getCoursesGradesCacheKey(),
}; };
@ -252,9 +254,10 @@ export class CoreGradesProvider {
* @param siteId Site ID (empty for current site). * @param siteId Site ID (empty for current site).
* @return Promise resolved when the data is invalidated. * @return Promise resolved when the data is invalidated.
*/ */
invalidateAllCourseGradesData(courseId: number, siteId?: string): Promise<void> { async invalidateAllCourseGradesData(courseId: number, siteId?: string): Promise<void> {
return CoreSites.getSite(siteId) const site = await CoreSites.getSite(siteId);
.then((site) => site.invalidateWsCacheForKeyStartingWith(this.getCourseGradesPrefixCacheKey(courseId)));
await site.invalidateWsCacheForKeyStartingWith(this.getCourseGradesPrefixCacheKey(courseId));
} }
/** /**
@ -265,12 +268,11 @@ export class CoreGradesProvider {
* @param siteId Site id (empty for current site). * @param siteId Site id (empty for current site).
* @return Promise resolved when the data is invalidated. * @return Promise resolved when the data is invalidated.
*/ */
invalidateCourseGradesData(courseId: number, userId?: number, siteId?: string): Promise<void> { async invalidateCourseGradesData(courseId: number, userId?: number, siteId?: string): Promise<void> {
return CoreSites.getSite(siteId).then((site) => { const site = await CoreSites.getSite(siteId);
userId = userId || site.getUserId(); userId = userId || site.getUserId();
return site.invalidateWsCacheForKey(this.getCourseGradesCacheKey(courseId, userId)); await site.invalidateWsCacheForKey(this.getCourseGradesCacheKey(courseId, userId));
});
} }
/** /**
@ -279,8 +281,10 @@ export class CoreGradesProvider {
* @param siteId Site id (empty for current site). * @param siteId Site id (empty for current site).
* @return Promise resolved when the data is invalidated. * @return Promise resolved when the data is invalidated.
*/ */
invalidateCoursesGradesData(siteId?: string): Promise<void> { async invalidateCoursesGradesData(siteId?: string): Promise<void> {
return CoreSites.getSite(siteId).then((site) => site.invalidateWsCacheForKey(this.getCoursesGradesCacheKey())); const site = await CoreSites.getSite(siteId);
await site.invalidateWsCacheForKey(this.getCoursesGradesCacheKey());
} }
/** /**
@ -292,9 +296,10 @@ export class CoreGradesProvider {
* @param siteId Site id (empty for current site). * @param siteId Site id (empty for current site).
* @return Promise resolved when the data is invalidated. * @return Promise resolved when the data is invalidated.
*/ */
invalidateCourseGradesItemsData(courseId: number, userId: number, groupId?: number, siteId?: string): Promise<void> { async invalidateCourseGradesItemsData(courseId: number, userId: number, groupId?: number, siteId?: string): Promise<void> {
return CoreSites.getSite(siteId) const site = await CoreSites.getSite(siteId);
.then((site) => site.invalidateWsCacheForKey(this.getCourseGradesItemsCacheKey(courseId, userId, groupId)));
await site.invalidateWsCacheForKey(this.getCourseGradesItemsCacheKey(courseId, userId, groupId));
} }
/** /**
@ -304,16 +309,17 @@ export class CoreGradesProvider {
* @return Resolve with true if plugin is enabled, false otherwise. * @return Resolve with true if plugin is enabled, false otherwise.
* @since Moodle 3.2 * @since Moodle 3.2
*/ */
isCourseGradesEnabled(siteId?: string): Promise<boolean> { async isCourseGradesEnabled(siteId?: string): Promise<boolean> {
return CoreSites.getSite(siteId).then((site) => { const site = await CoreSites.getSite(siteId);
if (!site.wsAvailable('gradereport_overview_get_course_grades')) {
return false;
}
// Now check that the configurable mygradesurl is pointing to the gradereport_overview plugin.
const url = site.getStoredConfig('mygradesurl') || '';
return url.indexOf('/grade/report/overview/') !== -1; if (!site.wsAvailable('gradereport_overview_get_course_grades')) {
}); return false;
}
// Now check that the configurable mygradesurl is pointing to the gradereport_overview plugin.
const url = site.getStoredConfig('mygradesurl') || '';
return url.indexOf('/grade/report/overview/') !== -1;
} }
/** /**
@ -323,13 +329,14 @@ export class CoreGradesProvider {
* @param siteId Site ID. If not defined, current site. * @param siteId Site ID. If not defined, current site.
* @return Promise resolved with true if plugin is enabled, rejected or resolved with false otherwise. * @return Promise resolved with true if plugin is enabled, rejected or resolved with false otherwise.
*/ */
isPluginEnabledForCourse(courseId: number, siteId?: string): Promise<boolean> { async isPluginEnabledForCourse(courseId: number, siteId?: string): Promise<boolean> {
if (!courseId) { if (!courseId) {
return Promise.reject(null); return false;
} }
return CoreCourses.getUserCourse(courseId, true, siteId) const course = await CoreCourses.getUserCourse(courseId, true, siteId);
.then((course) => !(course && typeof course.showgrades != 'undefined' && !course.showgrades));
return !(course && typeof course.showgrades != 'undefined' && !course.showgrades);
} }
/** /**
@ -373,9 +380,11 @@ export class CoreGradesProvider {
CorePushNotifications.logViewEvent(courseId, name, 'grades', wsName, { userid: userId }); CorePushNotifications.logViewEvent(courseId, name, 'grades', wsName, { userid: userId });
} }
const site = await CoreSites.getCurrentSite(); const site = CoreSites.getCurrentSite();
await site?.write(wsName, { courseid: courseId, userid: userId }); const params: CoreGradesGradereportViewGradeReportWSParams = { courseid: courseId, userid: userId };
await site?.write(wsName, params);
} }
/** /**
@ -389,13 +398,13 @@ export class CoreGradesProvider {
courseId = CoreSites.getCurrentSiteHomeId(); courseId = CoreSites.getCurrentSiteHomeId();
} }
const params = { const params: CoreGradesGradereportViewGradeReportWSParams = {
courseid: courseId, courseid: courseId,
}; };
CorePushNotifications.logViewListEvent('grades', 'gradereport_overview_view_grade_report', params); CorePushNotifications.logViewListEvent('grades', 'gradereport_overview_view_grade_report', params);
const site = await CoreSites.getCurrentSite(); const site = CoreSites.getCurrentSite();
await site?.write('gradereport_overview_view_grade_report', params); await site?.write('gradereport_overview_view_grade_report', params);
} }
@ -404,6 +413,14 @@ export class CoreGradesProvider {
export const CoreGrades = makeSingleton(CoreGradesProvider); export const CoreGrades = makeSingleton(CoreGradesProvider);
/**
* Params of gradereport_user_view_grade_report and gradereport_overview_view_grade_report WS.
*/
type CoreGradesGradereportViewGradeReportWSParams = {
courseid: number; // Id of the course.
userid?: number; // Id of the user, 0 means current user.
};
/** /**
* Params of gradereport_user_get_grade_items WS. * Params of gradereport_user_get_grade_items WS.
*/ */

View File

@ -54,8 +54,8 @@ export class CoreGradesCourseOptionHandlerService implements CoreCourseOptionsHa
* *
* @return Whether or not the handler is enabled on a site level. * @return Whether or not the handler is enabled on a site level.
*/ */
isEnabled(): Promise<boolean> { async isEnabled(): Promise<boolean> {
return Promise.resolve(true); return true;
} }
/** /**

View File

@ -44,7 +44,7 @@ export class CoreGradesMainMenuHandlerService implements CoreMainMenuHandler {
*/ */
getDisplayData(): CoreMainMenuHandlerData { getDisplayData(): CoreMainMenuHandlerData {
return { return {
icon: 'stats-chart', icon: 'fas-chart-bar',
title: 'core.grades.grades', title: 'core.grades.grades',
page: CoreGradesMainMenuHandlerService.PAGE_NAME, page: CoreGradesMainMenuHandlerService.PAGE_NAME,
class: 'core-grades-coursesgrades-handler', class: 'core-grades-coursesgrades-handler',

View File

@ -67,8 +67,8 @@ export class CoreGradesUserHandlerService implements CoreUserProfileHandler {
* *
* @return Always enabled. * @return Always enabled.
*/ */
isEnabled(): Promise<boolean> { async isEnabled(): Promise<boolean> {
return Promise.resolve(true); return true;
} }
/** /**
@ -86,9 +86,13 @@ export class CoreGradesUserHandlerService implements CoreUserProfileHandler {
return cache; return cache;
} }
const enabled = await CoreUtils.ignoreErrors(CoreGrades.isPluginEnabledForCourse(courseId), false); let enabled = await CoreUtils.ignoreErrors(CoreGrades.isPluginEnabledForCourse(courseId), false);
this.viewGradesEnabledCache[cacheKey] = enabled; if (enabled) {
enabled = await CoreUtils.promiseWorks(CoreGrades.getCourseGradesTable(courseId, user.id));
}
this.viewGradesEnabledCache[cacheKey] = true;
return enabled; return enabled;
} }
@ -100,13 +104,13 @@ export class CoreGradesUserHandlerService implements CoreUserProfileHandler {
*/ */
getDisplayData(): CoreUserProfileHandlerData { getDisplayData(): CoreUserProfileHandlerData {
return { return {
icon: 'stats-chart', icon: 'fas-chart-bar',
title: 'core.grades.grades', title: 'core.grades.grades',
class: 'core-grades-user-handler', class: 'core-grades-user-handler',
action: (event, user, courseId): void => { action: (event, user, courseId): void => {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
CoreNavigator.navigateToSitePath(`/grades/${courseId}`, { CoreNavigator.navigateToSitePath(`/user-grades/${courseId}`, {
params: { userId: user.id }, params: { userId: user.id },
}); });
}, },