MOBILE-2326 grades: Courses grades page
parent
97b53123ee
commit
abd25cf6ac
|
@ -61,6 +61,7 @@ import { CoreCourseModule } from '../core/course/course.module';
|
||||||
import { CoreSiteHomeModule } from '../core/sitehome/sitehome.module';
|
import { CoreSiteHomeModule } from '../core/sitehome/sitehome.module';
|
||||||
import { CoreContentLinksModule } from '../core/contentlinks/contentlinks.module';
|
import { CoreContentLinksModule } from '../core/contentlinks/contentlinks.module';
|
||||||
import { CoreUserModule } from '../core/user/user.module';
|
import { CoreUserModule } from '../core/user/user.module';
|
||||||
|
import { CoreGradesModule } from '../core/grades/grades.module';
|
||||||
|
|
||||||
// Addon modules.
|
// Addon modules.
|
||||||
import { AddonCalendarModule } from '../addon/calendar/calendar.module';
|
import { AddonCalendarModule } from '../addon/calendar/calendar.module';
|
||||||
|
@ -102,6 +103,7 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
|
||||||
CoreSiteHomeModule,
|
CoreSiteHomeModule,
|
||||||
CoreContentLinksModule,
|
CoreContentLinksModule,
|
||||||
CoreUserModule,
|
CoreUserModule,
|
||||||
|
CoreGradesModule,
|
||||||
AddonCalendarModule,
|
AddonCalendarModule,
|
||||||
AddonUserProfileFieldModule,
|
AddonUserProfileFieldModule,
|
||||||
AddonFilesModule,
|
AddonFilesModule,
|
||||||
|
|
|
@ -143,7 +143,7 @@ export class CoreSplitViewComponent implements OnInit {
|
||||||
activateSplitView(): void {
|
activateSplitView(): void {
|
||||||
const currentView = this.masterNav.getActive(),
|
const currentView = this.masterNav.getActive(),
|
||||||
currentPageName = currentView.component.name;
|
currentPageName = currentView.component.name;
|
||||||
if (this.masterNav.getPrevious().component.name == this.masterPageName) {
|
if (this.masterNav.getPrevious() && this.masterNav.getPrevious().component.name == this.masterPageName) {
|
||||||
if (currentPageName != this.masterPageName) {
|
if (currentPageName != this.masterPageName) {
|
||||||
// CurrentView is a 'Detail' page remove it from the 'master' nav stack.
|
// CurrentView is a 'Detail' page remove it from the 'master' nav stack.
|
||||||
this.masterNav.pop();
|
this.masterNav.pop();
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 { CoreGradesProvider } from './providers/grades';
|
||||||
|
import { CoreGradesHelperProvider } from './providers/helper';
|
||||||
|
import { CoreMainMenuDelegate } from '../mainmenu/providers/delegate';
|
||||||
|
import { CoreGradesMainMenuHandler } from './providers/mainmenu-handler';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
CoreGradesProvider,
|
||||||
|
CoreGradesHelperProvider,
|
||||||
|
CoreGradesMainMenuHandler
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class CoreGradesModule {
|
||||||
|
constructor(mainMenuDelegate: CoreMainMenuDelegate, gradesMenuHandler: CoreGradesMainMenuHandler) {
|
||||||
|
mainMenuDelegate.registerHandler(gradesMenuHandler);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"grades": "Grades",
|
||||||
|
"nogradesreturned": "No grades returned"
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<ion-header>
|
||||||
|
<ion-navbar>
|
||||||
|
<ion-title>{{ 'core.grades.grades' | translate }}</ion-title>
|
||||||
|
</ion-navbar>
|
||||||
|
</ion-header>
|
||||||
|
<core-split-view>
|
||||||
|
<ion-content>
|
||||||
|
<ion-refresher [enabled]="gradesLoaded" (ionRefresh)="refreshGrades($event)">
|
||||||
|
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||||
|
</ion-refresher>
|
||||||
|
<core-loading [hideUntil]="gradesLoaded">
|
||||||
|
<core-empty-box *ngIf="grades && grades.length == 0" icon="stats" [message]="'core.grades.nogradesreturned' | translate">
|
||||||
|
</core-empty-box>
|
||||||
|
|
||||||
|
<ion-list *ngIf="grades && grades.length > 0">
|
||||||
|
<a ion-item text-wrap *ngFor="let grade of grades" [title]="grade.coursefullname" (click)="gotoCourseGrades(grade.courseid)" [class.core-split-item-selected]="grade.courseid == courseId">
|
||||||
|
<h2><core-format-text [text]="grade.coursefullname"></core-format-text></h2>
|
||||||
|
<ion-badge item-end color="light">{{grade.grade}}</ion-badge>
|
||||||
|
</a>
|
||||||
|
</ion-list>
|
||||||
|
</core-loading>
|
||||||
|
</ion-content>
|
||||||
|
</core-split-view>
|
|
@ -0,0 +1,33 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 { IonicPageModule } from 'ionic-angular';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { CoreGradesCoursesPage } from './courses';
|
||||||
|
import { CoreComponentsModule } from '../../../../components/components.module';
|
||||||
|
import { CoreDirectivesModule } from '../../../../directives/directives.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
CoreGradesCoursesPage
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CoreComponentsModule,
|
||||||
|
CoreDirectivesModule,
|
||||||
|
IonicPageModule.forChild(CoreGradesCoursesPage),
|
||||||
|
TranslateModule.forChild()
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class CoreGradesCoursesPageModule {}
|
|
@ -0,0 +1,92 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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, ViewChild } from '@angular/core';
|
||||||
|
import { IonicPage, Content } from 'ionic-angular';
|
||||||
|
import { CoreGradesProvider } from '../../providers/grades';
|
||||||
|
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
|
||||||
|
import { CoreSplitViewComponent } from '../../../../components/split-view/split-view';
|
||||||
|
import { CoreGradesHelperProvider } from '../../providers/helper';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page that displays courses grades (main menu option).
|
||||||
|
*/
|
||||||
|
@IonicPage({ segment: 'core-grades-courses' })
|
||||||
|
@Component({
|
||||||
|
selector: 'page-core-grades-courses',
|
||||||
|
templateUrl: 'courses.html',
|
||||||
|
})
|
||||||
|
export class CoreGradesCoursesPage {
|
||||||
|
@ViewChild(Content) content: Content;
|
||||||
|
@ViewChild(CoreSplitViewComponent) splitviewCtrl: CoreSplitViewComponent;
|
||||||
|
|
||||||
|
grades = [];
|
||||||
|
courseId: number;
|
||||||
|
userId: number;
|
||||||
|
gradesLoaded = false;
|
||||||
|
|
||||||
|
constructor(private gradesProvider: CoreGradesProvider, private domUtils: CoreDomUtilsProvider,
|
||||||
|
private courseHelper: CoreGradesHelperProvider) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View loaded.
|
||||||
|
*/
|
||||||
|
ionViewDidLoad(): void {
|
||||||
|
// Get first participants.
|
||||||
|
this.fetchData().then(() => {
|
||||||
|
// Add log in Moodle.
|
||||||
|
return this.gradesProvider.logCoursesGradesView();
|
||||||
|
}).finally(() => {
|
||||||
|
this.gradesLoaded = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch all the data required for the view.
|
||||||
|
*
|
||||||
|
* @return {Promise<any>} Resolved when done.
|
||||||
|
*/
|
||||||
|
fetchData(): Promise<any> {
|
||||||
|
return this.gradesProvider.getCoursesGrades().then((grades) => {
|
||||||
|
return this.courseHelper.getGradesCourseData(grades).then((grades) => {
|
||||||
|
this.grades = grades;
|
||||||
|
});
|
||||||
|
}).catch((error) => {
|
||||||
|
this.domUtils.showErrorModalDefault(error, 'Error loading grades');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh data.
|
||||||
|
*
|
||||||
|
* @param {any} refresher Refresher.
|
||||||
|
*/
|
||||||
|
refreshGrades(refresher: any): void {
|
||||||
|
this.gradesProvider.invalidateCoursesGradesData().finally(() => {
|
||||||
|
this.fetchData().finally(() => {
|
||||||
|
refresher.complete();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate to the grades of the selected course.
|
||||||
|
* @param {number} courseId Course Id where to navigate.
|
||||||
|
*/
|
||||||
|
gotoCourseGrades(courseId: number): void {
|
||||||
|
this.courseId = courseId;
|
||||||
|
this.splitviewCtrl.push('CoreGradesCoursePage', {courseId: courseId, userId: this.userId, forcephoneview: 1});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 { CoreLoggerProvider } from '../../../providers/logger';
|
||||||
|
import { CoreSite } from '../../../classes/site';
|
||||||
|
import { CoreSitesProvider } from '../../../providers/sites';
|
||||||
|
import { CoreUtilsProvider } from '../../../providers/utils/utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service to provide grade functionalities.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class CoreGradesProvider {
|
||||||
|
protected ROOT_CACHE_KEY = 'mmGrades:';
|
||||||
|
|
||||||
|
protected logger;
|
||||||
|
|
||||||
|
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider) {
|
||||||
|
this.logger = logger.getInstance('CoreGradesProvider');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cache key for courses grade WS calls.
|
||||||
|
*
|
||||||
|
* @return {string} Cache key.
|
||||||
|
*/
|
||||||
|
protected getCoursesGradesCacheKey(): string {
|
||||||
|
return this.ROOT_CACHE_KEY + 'coursesgrades';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the grades for a certain course.
|
||||||
|
*
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<any>} Promise to be resolved when the grades are retrieved.
|
||||||
|
*/
|
||||||
|
getCoursesGrades(siteId?: string): Promise<any> {
|
||||||
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
|
this.logger.debug('Get course grades');
|
||||||
|
|
||||||
|
const preSets = {
|
||||||
|
cacheKey: this.getCoursesGradesCacheKey()
|
||||||
|
};
|
||||||
|
|
||||||
|
return site.read('gradereport_overview_get_course_grades', undefined, preSets).then((data) => {
|
||||||
|
if (data && data.grades) {
|
||||||
|
return data.grades;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.reject(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates courses grade data WS calls.
|
||||||
|
*
|
||||||
|
* @param {string} [siteId] Site id (empty for current site).
|
||||||
|
* @return {Promise<any>} Promise resolved when the data is invalidated.
|
||||||
|
*/
|
||||||
|
invalidateCoursesGradesData(siteId?: string): Promise<any> {
|
||||||
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
|
return site.invalidateWsCacheForKey(this.getCoursesGradesCacheKey());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the plugin is enabled for a certain site.
|
||||||
|
*
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<boolean>} Resolve with true if plugin is enabled, false otherwise.
|
||||||
|
* @since Moodle 3.2
|
||||||
|
*/
|
||||||
|
isCourseGradesEnabled(siteId?: string): Promise<boolean> {
|
||||||
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log Courses grades view in Moodle.
|
||||||
|
*
|
||||||
|
* @param {number} courseId Course ID.
|
||||||
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
|
*/
|
||||||
|
logCoursesGradesView(courseId?: number): Promise<any> {
|
||||||
|
if (!courseId) {
|
||||||
|
courseId = this.sitesProvider.getCurrentSiteHomeId();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.sitesProvider.getCurrentSite().write('gradereport_overview_view_grade_report', {
|
||||||
|
courseid: courseId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 { CoreLoggerProvider } from '../../../providers/logger';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { CoreCoursesProvider } from '../../courses/providers/courses';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service that provides some features regarding users information.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class CoreGradesHelperProvider {
|
||||||
|
protected logger;
|
||||||
|
|
||||||
|
constructor(logger: CoreLoggerProvider, private coursesProvider: CoreCoursesProvider) {
|
||||||
|
this.logger = logger.getInstance('CoreGradesHelperProvider');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get course data for grades since they only have courseid.
|
||||||
|
*
|
||||||
|
* @param {Object[]} grades Grades to get the data for.
|
||||||
|
* @return {Promise<any>} Promise always resolved. Resolve param is the formatted grades.
|
||||||
|
*/
|
||||||
|
getGradesCourseData(grades: any): Promise<any> {
|
||||||
|
// We ommit to use $mmCourses.getUserCourse for performance reasons.
|
||||||
|
return this.coursesProvider.getUserCourses(true).then((courses) => {
|
||||||
|
const indexedCourses = {};
|
||||||
|
courses.forEach((course) => {
|
||||||
|
indexedCourses[course.id] = course;
|
||||||
|
});
|
||||||
|
|
||||||
|
grades.forEach((grade) => {
|
||||||
|
if (typeof indexedCourses[grade.courseid] != 'undefined') {
|
||||||
|
grade.coursefullname = indexedCourses[grade.courseid].fullname;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return grades;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// 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 { CoreGradesProvider } from './grades';
|
||||||
|
import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '../../mainmenu/providers/delegate';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler to inject an option into main menu.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class CoreGradesMainMenuHandler implements CoreMainMenuHandler {
|
||||||
|
name = 'CoreGrades';
|
||||||
|
priority = 950;
|
||||||
|
|
||||||
|
constructor(private gradesProvider: CoreGradesProvider) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the handler is enabled on a site level.
|
||||||
|
*
|
||||||
|
* @return {boolean | Promise<boolean>} Whether or not the handler is enabled on a site level.
|
||||||
|
*/
|
||||||
|
isEnabled(): boolean | Promise<boolean> {
|
||||||
|
return this.gradesProvider.isCourseGradesEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the data needed to render the handler.
|
||||||
|
*
|
||||||
|
* @return {CoreMainMenuHandlerData} Data needed to render the handler.
|
||||||
|
*/
|
||||||
|
getDisplayData(): CoreMainMenuHandlerData {
|
||||||
|
return {
|
||||||
|
icon: 'stats',
|
||||||
|
title: 'core.grades.grades',
|
||||||
|
page: 'CoreGradesCoursesPage',
|
||||||
|
class: 'core-grades-coursesgrades-handler'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue