Merge pull request #1840 from dpalou/MOBILE-2953

Mobile 2953
main
Juan Leyva 2019-04-25 18:07:54 +02:00 committed by GitHub
commit b73b3d2727
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 215 additions and 133 deletions

View File

@ -37,9 +37,10 @@ export class AddonBadgesPushClickHandler implements CorePushNotificationsClickHa
* @return {boolean} Whether the notification click is handled by this handler * @return {boolean} Whether the notification click is handled by this handler
*/ */
handles(notification: any): boolean | Promise<boolean> { handles(notification: any): boolean | Promise<boolean> {
// @todo: Support 'badgecreatornotice' once we receive the hash or contexturl. const data = notification.customdata || {};
if (this.utils.isTrueOrOne(notification.notif) && notification.moodlecomponent == 'moodle' && if (this.utils.isTrueOrOne(notification.notif) && notification.moodlecomponent == 'moodle' &&
notification.name == 'badgerecipientnotice') { (notification.name == 'badgerecipientnotice' || (notification.name == 'badgecreatornotice' && data.hash))) {
return this.badgesProvider.isPluginEnabled(notification.site); return this.badgesProvider.isPluginEnabled(notification.site);
} }
@ -53,8 +54,14 @@ export class AddonBadgesPushClickHandler implements CorePushNotificationsClickHa
* @return {Promise<any>} Promise resolved when done. * @return {Promise<any>} Promise resolved when done.
*/ */
handleClick(notification: any): Promise<any> { handleClick(notification: any): Promise<any> {
// @todo: Go to the badge page once we receive the hash or contexturl. const data = notification.customdata || {};
if (data.hash) {
// We have the hash, open the badge directly.
return this.loginHelper.redirect('AddonBadgesIssuedBadgePage', {courseId: 0, badgeHash: data.hash}, notification.site);
}
// No hash, open the list of user badges.
return this.badgesProvider.invalidateUserBadges(0, Number(notification.usertoid), notification.site).catch(() => { return this.badgesProvider.invalidateUserBadges(0, Number(notification.usertoid), notification.site).catch(() => {
// Ignore errors. // Ignore errors.
}).then(() => { }).then(() => {

View File

@ -24,7 +24,7 @@ import { AddonBlogProvider } from './blog';
@Injectable() @Injectable()
export class AddonBlogIndexLinkHandler extends CoreContentLinksHandlerBase { export class AddonBlogIndexLinkHandler extends CoreContentLinksHandlerBase {
name = 'AddonBlogIndexLinkHandler'; name = 'AddonBlogIndexLinkHandler';
featureName = 'CoreUserDelegate_AddonBlog'; featureName = 'CoreUserDelegate_AddonBlog:blogs';
pattern = /\/blog\/index\.php/; pattern = /\/blog\/index\.php/;
constructor(private blogProvider: AddonBlogProvider, private loginHelper: CoreLoginHelperProvider) { constructor(private blogProvider: AddonBlogProvider, private loginHelper: CoreLoginHelperProvider) {

View File

@ -38,16 +38,26 @@ export class AddonModForumDiscussionLinkHandler extends CoreContentLinksHandlerB
* @param {string} url The URL to treat. * @param {string} url The URL to treat.
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @param {number} [courseId] Course ID related to the URL. Optional but recommended. * @param {number} [courseId] Course ID related to the URL. Optional but recommended.
* @param {any} [data] Extra data to handle the URL.
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions. * @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
*/ */
getActions(siteIds: string[], url: string, params: any, courseId?: number): getActions(siteIds: string[], url: string, params: any, courseId?: number, data?: any):
CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> { CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
data = data || {};
return [{ return [{
action: (siteId, navCtrl?): void => { action: (siteId, navCtrl?): void => {
const pageParams = { const pageParams: any = {
courseId: courseId || parseInt(params.courseid, 10) || parseInt(params.cid, 10), courseId: courseId || parseInt(params.courseid, 10) || parseInt(params.cid, 10),
discussionId: parseInt(params.d, 10), discussionId: parseInt(params.d, 10),
cmId: data.cmid && parseInt(data.cmid, 10),
forumId: data.instance && parseInt(data.instance, 10)
}; };
if (data.postid || params.urlHash) {
pageParams.postId = parseInt(data.postid || params.urlHash.replace('p', ''));
}
this.linkHelper.goInSite(navCtrl, 'AddonModForumDiscussionPage', pageParams, siteId); this.linkHelper.goInSite(navCtrl, 'AddonModForumDiscussionPage', pageParams, siteId);
} }
}]; }];

View File

@ -50,13 +50,16 @@ export class AddonModForumPushClickHandler implements CorePushNotificationsClick
*/ */
handleClick(notification: any): Promise<any> { handleClick(notification: any): Promise<any> {
const contextUrlParams = this.urlUtils.extractUrlParams(notification.contexturl), const contextUrlParams = this.urlUtils.extractUrlParams(notification.contexturl),
data = notification.customdata || {},
pageParams: any = { pageParams: any = {
courseId: Number(notification.courseid), courseId: Number(notification.courseid),
discussionId: Number(contextUrlParams.d), discussionId: Number(contextUrlParams.d || data.discussionid),
cmId: Number(data.cmid),
forumId: Number(data.instance)
}; };
if (contextUrlParams.urlHash) { if (data.postid || contextUrlParams.urlHash) {
pageParams.postId = Number(contextUrlParams.urlHash.replace('p', '')); pageParams.postId = Number(data.postid || contextUrlParams.urlHash.replace('p', ''));
} }
return this.forumProvider.invalidateDiscussionPosts(pageParams.discussionId, notification.site).catch(() => { return this.forumProvider.invalidateDiscussionPosts(pageParams.discussionId, notification.site).catch(() => {

View File

@ -14,12 +14,9 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CorePushNotificationsClickHandler } from '@core/pushnotifications/providers/delegate'; import { CorePushNotificationsClickHandler } from '@core/pushnotifications/providers/delegate';
import { CoreLoginHelperProvider } from '@core/login/providers/helper';
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
import { CoreGradesProvider } from '@core/grades/providers/grades'; import { CoreGradesProvider } from '@core/grades/providers/grades';
import { AddonModLessonProvider } from './lesson'; import { CoreGradesHelperProvider } from '@core/grades/providers/helper';
/** /**
* Handler for lesson push notifications clicks. * Handler for lesson push notifications clicks.
@ -30,9 +27,8 @@ export class AddonModLessonPushClickHandler implements CorePushNotificationsClic
priority = 200; priority = 200;
featureName = 'CoreCourseModuleDelegate_AddonModLesson'; featureName = 'CoreCourseModuleDelegate_AddonModLesson';
constructor(private utils: CoreUtilsProvider, private lessonProvider: AddonModLessonProvider, constructor(private utils: CoreUtilsProvider, private gradesHelper: CoreGradesHelperProvider,
private loginHelper: CoreLoginHelperProvider, private domUtils: CoreDomUtilsProvider, private gradesProvider: CoreGradesProvider) {}
private courseHelper: CoreCourseHelperProvider, private gradesProvider: CoreGradesProvider) {}
/** /**
* Check if a notification click is handled by this handler. * Check if a notification click is handled by this handler.
@ -44,7 +40,7 @@ export class AddonModLessonPushClickHandler implements CorePushNotificationsClic
if (this.utils.isTrueOrOne(notification.notif) && notification.moodlecomponent == 'mod_lesson' && if (this.utils.isTrueOrOne(notification.notif) && notification.moodlecomponent == 'mod_lesson' &&
notification.name == 'graded_essay') { notification.name == 'graded_essay') {
return this.lessonProvider.isPluginEnabled(notification.site); return this.gradesProvider.isPluginEnabledForCourse(Number(notification.courseid), notification.site);
} }
return false; return false;
@ -59,59 +55,8 @@ export class AddonModLessonPushClickHandler implements CorePushNotificationsClic
handleClick(notification: any): Promise<any> { handleClick(notification: any): Promise<any> {
const data = notification.customdata || {}, const data = notification.customdata || {},
courseId = Number(notification.courseid), courseId = Number(notification.courseid),
moduleId = Number(data.cmid), moduleId = Number(data.cmid);
modal = this.domUtils.showModalLoading();
let promise;
if (moduleId) { return this.gradesHelper.goToGrades(courseId, undefined, moduleId, undefined, notification.site);
// Try to open the module grade directly. Check if it's possible.
promise = this.gradesProvider.isGradeItemsAvalaible(notification.site).catch(() => {
return false;
});
} else {
promise = Promise.resolve(false);
}
return promise.then((getGrades) => {
if (getGrades) {
return this.gradesProvider.getGradeItems(courseId, undefined, undefined, notification.site).then((items) => {
// Find the item of th module.
const item = items.find((item) => {
return moduleId == item.cmid;
});
if (item) {
// Open the item directly.
const pageParams: any = {
courseId: courseId,
gradeId: item.id
};
this.loginHelper.redirect('CoreGradesGradePage', pageParams, notification.site);
}
return Promise.reject(null);
});
} else {
return Promise.reject(null);
}
}).catch(() => {
// Cannot get grade items or there's no need to. Open the course with the grades tab selected.
return this.courseHelper.getCourse(courseId, notification.site).then((result) => {
const pageParams: any = {
course: result.course,
selectedTab: 'CoreGrades'
};
this.loginHelper.redirect('CoreCourseSectionPage', pageParams, notification.site);
});
}).catch(() => {
// Cannot get course for some reason, just open the grades page.
return this.loginHelper.redirect('CoreGradesCoursePage', {course: {id: courseId}}, notification.site);
}).finally(() => {
modal.dismiss();
});
} }
} }

View File

@ -54,12 +54,13 @@ export class AddonModQuizPushClickHandler implements CorePushNotificationsClickH
*/ */
handleClick(notification: any): Promise<any> { handleClick(notification: any): Promise<any> {
const contextUrlParams = this.urlUtils.extractUrlParams(notification.contexturl), const contextUrlParams = this.urlUtils.extractUrlParams(notification.contexturl),
data = notification.customdata || {},
courseId = Number(notification.courseid); courseId = Number(notification.courseid);
if (notification.name == 'submission') { if (notification.name == 'submission') {
// A student made a submission, go to view the attempt. // A student made a submission, go to view the attempt.
return this.quizHelper.handleReviewLink(undefined, Number(contextUrlParams.attempt), Number(contextUrlParams.page), return this.quizHelper.handleReviewLink(undefined, Number(contextUrlParams.attempt), Number(contextUrlParams.page),
courseId, undefined, notification.site); courseId, Number(data.instance), notification.site);
} else { } else {
// Open the activity. // Open the activity.
const moduleId = Number(contextUrlParams.id); const moduleId = Number(contextUrlParams.id);

View File

@ -38,19 +38,22 @@ export class AddonModQuizReviewLinkHandler extends CoreContentLinksHandlerBase {
* @param {string} url The URL to treat. * @param {string} url The URL to treat.
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @param {number} [courseId] Course ID related to the URL. Optional but recommended. * @param {number} [courseId] Course ID related to the URL. Optional but recommended.
* @param {any} [data] Extra data to handle the URL.
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions. * @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
*/ */
getActions(siteIds: string[], url: string, params: any, courseId?: number): getActions(siteIds: string[], url: string, params: any, courseId?: number, data?: any):
CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> { CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
courseId = courseId || params.courseid || params.cid; courseId = courseId || params.courseid || params.cid;
data = data || {};
return [{ return [{
action: (siteId, navCtrl?): void => { action: (siteId, navCtrl?): void => {
const attemptId = parseInt(params.attempt, 10), const attemptId = parseInt(params.attempt, 10),
page = parseInt(params.page, 10); page = parseInt(params.page, 10),
quizId = data.instance && parseInt(data.instance, 10);
this.quizHelper.handleReviewLink(navCtrl, attemptId, page, courseId, undefined, siteId); this.quizHelper.handleReviewLink(navCtrl, attemptId, page, courseId, quizId, siteId);
} }
}]; }];
} }

View File

@ -13,7 +13,9 @@
// limitations under the License. // limitations under the License.
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input, OnInit } from '@angular/core';
import { NavController } from 'ionic-angular';
import { CoreContentLinksDelegate, CoreContentLinksAction } from '@core/contentlinks/providers/delegate'; import { CoreContentLinksDelegate, CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
import { CoreSitesProvider } from '@providers/sites';
/** /**
* Component that displays the actions for a notification. * Component that displays the actions for a notification.
@ -25,17 +27,42 @@ import { CoreContentLinksDelegate, CoreContentLinksAction } from '@core/contentl
export class AddonNotificationsActionsComponent implements OnInit { export class AddonNotificationsActionsComponent implements OnInit {
@Input() contextUrl: string; @Input() contextUrl: string;
@Input() courseId: number; @Input() courseId: number;
@Input() data?: any; // Extra data to handle the URL.
actions: CoreContentLinksAction[] = []; actions: CoreContentLinksAction[] = [];
constructor(private contentLinksDelegate: CoreContentLinksDelegate) {} constructor(private contentLinksDelegate: CoreContentLinksDelegate, private sitesProvider: CoreSitesProvider) {}
/** /**
* Component being initialized. * Component being initialized.
*/ */
ngOnInit(): void { ngOnInit(): void {
this.contentLinksDelegate.getActionsFor(this.contextUrl, this.courseId).then((actions) => { if (!this.contextUrl) {
// No contexturl, nothing to do.
return;
}
this.contentLinksDelegate.getActionsFor(this.contextUrl, this.courseId, undefined, this.data).then((actions) => {
if (!actions.length) {
// URL is not supported. Add an action to open it in browser.
actions.push({
message: 'core.view',
icon: 'eye',
action: this.defaultAction.bind(this)
});
}
this.actions = actions; this.actions = actions;
}); });
} }
/**
* Default action. Open in browser.
*
* @param {string} siteId Site ID to use.
* @param {NavController} [navCtrl] NavController.
*/
protected defaultAction(siteId: string, navCtrl?: NavController): void {
this.sitesProvider.getCurrentSite().openInBrowserWithAutoLogin(this.contextUrl);
}
} }

View File

@ -27,7 +27,7 @@
<ion-item text-wrap> <ion-item text-wrap>
<p><core-format-text [text]="notification.mobiletext | coreCreateLinks"></core-format-text></p> <p><core-format-text [text]="notification.mobiletext | coreCreateLinks"></core-format-text></p>
</ion-item> </ion-item>
<addon-notifications-actions [contextUrl]="notification.contexturl" [courseId]="notification.courseid"></addon-notifications-actions> <addon-notifications-actions [contextUrl]="notification.contexturl" [courseId]="notification.courseid" [data]="notification.customdata"></addon-notifications-actions>
</ion-card> </ion-card>
<core-empty-box *ngIf="!notifications || notifications.length <= 0" icon="notifications" [message]="'addon.notifications.therearentnotificationsyet' | translate"></core-empty-box> <core-empty-box *ngIf="!notifications || notifications.length <= 0" icon="notifications" [message]="'addon.notifications.therearentnotificationsyet' | translate"></core-empty-box>
<core-infinite-loading [enabled]="canLoadMore" (action)="loadMoreNotifications($event)" [error]="loadMoreError"></core-infinite-loading> <core-infinite-loading [enabled]="canLoadMore" (action)="loadMoreNotifications($event)" [error]="loadMoreError"></core-infinite-loading>

View File

@ -16,6 +16,7 @@ import { Injectable } from '@angular/core';
import { CoreAppProvider } from '@providers/app'; import { CoreAppProvider } from '@providers/app';
import { CoreLoggerProvider } from '@providers/logger'; import { CoreLoggerProvider } from '@providers/logger';
import { CoreSitesProvider } from '@providers/sites'; import { CoreSitesProvider } from '@providers/sites';
import { CoreTextUtilsProvider } from '@providers/utils/text';
import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreTimeUtilsProvider } from '@providers/utils/time';
import { CoreUserProvider } from '@core/user/providers/user'; import { CoreUserProvider } from '@core/user/providers/user';
import { CoreEmulatorHelperProvider } from '@core/emulator/providers/helper'; import { CoreEmulatorHelperProvider } from '@core/emulator/providers/helper';
@ -37,7 +38,8 @@ export class AddonNotificationsProvider {
constructor(logger: CoreLoggerProvider, private appProvider: CoreAppProvider, private sitesProvider: CoreSitesProvider, constructor(logger: CoreLoggerProvider, private appProvider: CoreAppProvider, private sitesProvider: CoreSitesProvider,
private timeUtils: CoreTimeUtilsProvider, private userProvider: CoreUserProvider, private timeUtils: CoreTimeUtilsProvider, private userProvider: CoreUserProvider,
private emulatorHelper: CoreEmulatorHelperProvider, private messageProvider: AddonMessagesProvider) { private emulatorHelper: CoreEmulatorHelperProvider, private messageProvider: AddonMessagesProvider,
private textUtils: CoreTextUtilsProvider) {
this.logger = logger.getInstance('AddonNotificationsProvider'); this.logger = logger.getInstance('AddonNotificationsProvider');
} }
@ -57,11 +59,27 @@ export class AddonNotificationsProvider {
notification.mobiletext = notification.fullmessage; notification.mobiletext = notification.fullmessage;
} }
notification.moodlecomponent = notification.component;
notification.notification = 1;
notification.notif = 1;
if (typeof read != 'undefined') {
notification.read = read;
}
if (typeof notification.customdata == 'string') {
notification.customdata = this.textUtils.parseJSON(notification.customdata, {});
}
// Try to set courseid the notification belongs to. // Try to set courseid the notification belongs to.
if (notification.customdata && notification.customdata.courseid) {
notification.courseid = notification.customdata.courseid;
} else {
const cid = notification.fullmessagehtml.match(/course\/view\.php\?id=([^"]*)/); const cid = notification.fullmessagehtml.match(/course\/view\.php\?id=([^"]*)/);
if (cid && cid[1]) { if (cid && cid[1]) {
notification.courseid = cid[1]; notification.courseid = cid[1];
} }
}
if (notification.useridfrom > 0) { if (notification.useridfrom > 0) {
// Try to get the profile picture of the user. // Try to get the profile picture of the user.
return this.userProvider.getProfile(notification.useridfrom, notification.courseid, true).then((user) => { return this.userProvider.getProfile(notification.useridfrom, notification.courseid, true).then((user) => {
@ -73,13 +91,6 @@ export class AddonNotificationsProvider {
}); });
} }
notification.moodlecomponent = notification.component;
notification.notification = 1;
notification.notif = 1;
if (typeof read != 'undefined') {
notification.read = read;
}
return Promise.resolve(notification); return Promise.resolve(notification);
}); });

View File

@ -56,9 +56,10 @@ export interface CoreContentLinksHandler {
* @param {string} url The URL to treat. * @param {string} url The URL to treat.
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @param {number} [courseId] Course ID related to the URL. Optional but recommended. * @param {number} [courseId] Course ID related to the URL. Optional but recommended.
* @param {any} [data] Extra data to handle the URL.
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions. * @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
*/ */
getActions(siteIds: string[], url: string, params: any, courseId?: number): getActions(siteIds: string[], url: string, params: any, courseId?: number, data?: any):
CoreContentLinksAction[] | Promise<CoreContentLinksAction[]>; CoreContentLinksAction[] | Promise<CoreContentLinksAction[]>;
/** /**
@ -157,9 +158,10 @@ export class CoreContentLinksDelegate {
* @param {string} url URL to handle. * @param {string} url URL to handle.
* @param {number} [courseId] Course ID related to the URL. Optional but recommended. * @param {number} [courseId] Course ID related to the URL. Optional but recommended.
* @param {string} [username] Username to use to filter sites. * @param {string} [username] Username to use to filter sites.
* @param {any} [data] Extra data to handle the URL.
* @return {Promise<CoreContentLinksAction[]>} Promise resolved with the actions. * @return {Promise<CoreContentLinksAction[]>} Promise resolved with the actions.
*/ */
getActionsFor(url: string, courseId?: number, username?: string): Promise<CoreContentLinksAction[]> { getActionsFor(url: string, courseId?: number, username?: string, data?: any): Promise<CoreContentLinksAction[]> {
if (!url) { if (!url) {
return Promise.resolve([]); return Promise.resolve([]);
} }
@ -187,7 +189,7 @@ export class CoreContentLinksDelegate {
return; return;
} }
return Promise.resolve(handler.getActions(siteIds, url, params, courseId)).then((actions) => { return Promise.resolve(handler.getActions(siteIds, url, params, courseId, data)).then((actions) => {
if (actions && actions.length) { if (actions && actions.length) {
// Set default values if any value isn't supplied. // Set default values if any value isn't supplied.
actions.forEach((action) => { actions.forEach((action) => {

View File

@ -23,6 +23,7 @@ import { CoreSitesProvider } from '@providers/sites';
import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTextUtilsProvider } from '@providers/utils/text';
import { CoreUrlUtilsProvider } from '@providers/utils/url'; import { CoreUrlUtilsProvider } from '@providers/utils/url';
import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreLoginHelperProvider } from '@core/login/providers/helper'; import { CoreLoginHelperProvider } from '@core/login/providers/helper';
import { CoreContentLinksDelegate, CoreContentLinksAction } from './delegate'; import { CoreContentLinksDelegate, CoreContentLinksAction } from './delegate';
import { CoreConstants } from '@core/constants'; import { CoreConstants } from '@core/constants';
@ -40,7 +41,7 @@ export class CoreContentLinksHelperProvider {
private contentLinksDelegate: CoreContentLinksDelegate, private appProvider: CoreAppProvider, private contentLinksDelegate: CoreContentLinksDelegate, private appProvider: CoreAppProvider,
private domUtils: CoreDomUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private translate: TranslateService, private domUtils: CoreDomUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private translate: TranslateService,
private initDelegate: CoreInitDelegate, eventsProvider: CoreEventsProvider, private textUtils: CoreTextUtilsProvider, private initDelegate: CoreInitDelegate, eventsProvider: CoreEventsProvider, private textUtils: CoreTextUtilsProvider,
private sitePluginsProvider: CoreSitePluginsProvider, private zone: NgZone) { private sitePluginsProvider: CoreSitePluginsProvider, private zone: NgZone, private utils: CoreUtilsProvider) {
this.logger = logger.getInstance('CoreContentLinksHelperProvider'); this.logger = logger.getInstance('CoreContentLinksHelperProvider');
// Listen for app launched URLs. If we receive one, check if it's a content link. // Listen for app launched URLs. If we receive one, check if it's a content link.
@ -88,18 +89,23 @@ export class CoreContentLinksHelperProvider {
* @param {string} pageName Name of the page to go. * @param {string} pageName Name of the page to go.
* @param {any} [pageParams] Params to send to the page. * @param {any} [pageParams] Params to send to the page.
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when done.
*/ */
goInSite(navCtrl: NavController, pageName: string, pageParams: any, siteId?: string): void { goInSite(navCtrl: NavController, pageName: string, pageParams: any, siteId?: string): Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId(); siteId = siteId || this.sitesProvider.getCurrentSiteId();
const deferred = this.utils.promiseDefer();
// Execute the code in the Angular zone, so change detection doesn't stop working. // Execute the code in the Angular zone, so change detection doesn't stop working.
this.zone.run(() => { this.zone.run(() => {
if (navCtrl && siteId == this.sitesProvider.getCurrentSiteId()) { if (navCtrl && siteId == this.sitesProvider.getCurrentSiteId()) {
navCtrl.push(pageName, pageParams); navCtrl.push(pageName, pageParams).then(deferred.resolve, deferred.reject);
} else { } else {
this.loginHelper.redirect(pageName, pageParams, siteId); this.loginHelper.redirect(pageName, pageParams, siteId).then(deferred.resolve, deferred.reject);
} }
}); });
return deferred.promise;
} }
/** /**

View File

@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { NavController } from 'ionic-angular';
import { CoreLoggerProvider } from '@providers/logger'; import { CoreLoggerProvider } from '@providers/logger';
import { CoreSitesProvider } from '@providers/sites'; import { CoreSitesProvider } from '@providers/sites';
import { CoreCoursesProvider } from '@core/courses/providers/courses'; import { CoreCoursesProvider } from '@core/courses/providers/courses';
@ -22,6 +23,9 @@ import { CoreTextUtilsProvider } from '@providers/utils/text';
import { CoreUrlUtilsProvider } from '@providers/utils/url'; import { CoreUrlUtilsProvider } from '@providers/utils/url';
import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
import { CoreLoginHelperProvider } from '@core/login/providers/helper';
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
/** /**
* Service that provides some features regarding grades information. * Service that provides some features regarding grades information.
@ -33,7 +37,9 @@ export class CoreGradesHelperProvider {
constructor(logger: CoreLoggerProvider, private coursesProvider: CoreCoursesProvider, constructor(logger: CoreLoggerProvider, private coursesProvider: CoreCoursesProvider,
private gradesProvider: CoreGradesProvider, private sitesProvider: CoreSitesProvider, private gradesProvider: CoreGradesProvider, private sitesProvider: CoreSitesProvider,
private textUtils: CoreTextUtilsProvider, private courseProvider: CoreCourseProvider, private textUtils: CoreTextUtilsProvider, private courseProvider: CoreCourseProvider,
private domUtils: CoreDomUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private utils: CoreUtilsProvider) { private domUtils: CoreDomUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private utils: CoreUtilsProvider,
private linkHelper: CoreContentLinksHelperProvider, private loginHelper: CoreLoginHelperProvider,
private courseHelper: CoreCourseHelperProvider) {
this.logger = logger.getInstance('CoreGradesHelperProvider'); this.logger = logger.getInstance('CoreGradesHelperProvider');
} }
@ -381,6 +387,95 @@ export class CoreGradesHelperProvider {
return []; return [];
} }
/**
* Go to view grades.
*
* @param {number} courseId Course ID t oview.
* @param {number} [userId] User to view. If not defined, current user.
* @param {number} [moduleId] Module to view. If not defined, view all course grades.
* @param {NavController} [navCtrl] NavController to use.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when done.
*/
goToGrades(courseId: number, userId?: number, moduleId?: number, navCtrl?: NavController, siteId?: string): Promise<any> {
const modal = this.domUtils.showModalLoading();
let currentUserId;
return this.sitesProvider.getSite(siteId).then((site) => {
siteId = site.id;
currentUserId = site.getUserId();
if (moduleId) {
// Try to open the module grade directly. Check if it's possible.
return this.gradesProvider.isGradeItemsAvalaible(siteId).then((getGrades) => {
if (!getGrades) {
return Promise.reject(null);
}
});
} else {
return Promise.reject(null);
}
}).then(() => {
// Can get grades. Do it.
return this.gradesProvider.getGradeItems(courseId, userId, undefined, siteId).then((items) => {
// Find the item of the module.
const item = items.find((item) => {
return moduleId == item.cmid;
});
if (item) {
// Open the item directly.
const pageParams: any = {
courseId: courseId,
userId: userId,
gradeId: item.id
};
return this.linkHelper.goInSite(navCtrl, 'CoreGradesGradePage', pageParams, siteId).catch(() => {
// Ignore errors.
});
}
return Promise.reject(null);
});
}).catch(() => {
// Cannot get grade items or there's no need to.
if (userId && userId != currentUserId) {
// View another user grades. Open the grades page directly.
const pageParams = {
course: {id: courseId},
userId: userId
};
return this.linkHelper.goInSite(navCtrl, 'CoreGradesCoursePage', pageParams, siteId).catch(() => {
// Ignore errors.
});
}
// View own grades. Open the course with the grades tab selected.
return this.courseHelper.getCourse(courseId, siteId).then((result) => {
const pageParams: any = {
course: result.course,
selectedTab: 'CoreGrades'
};
return this.loginHelper.redirect('CoreCourseSectionPage', pageParams, siteId).catch(() => {
// Ignore errors.
});
});
}).catch(() => {
// Cannot get course for some reason, just open the grades page.
return this.linkHelper.goInSite(navCtrl, 'CoreGradesCoursePage', {course: {id: courseId}}, siteId);
}).finally(() => {
modal.dismiss();
});
}
/** /**
* Invalidate the grade items for a certain module. * Invalidate the grade items for a certain module.
* *

View File

@ -15,11 +15,8 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler'; import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler';
import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate'; import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
import { CoreLoginHelperProvider } from '@core/login/providers/helper';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreGradesProvider } from './grades'; import { CoreGradesProvider } from './grades';
import { CoreGradesHelperProvider } from './helper';
/** /**
* Handler to treat links to user grades. * Handler to treat links to user grades.
@ -29,9 +26,7 @@ export class CoreGradesUserLinkHandler extends CoreContentLinksHandlerBase {
name = 'CoreGradesUserLinkHandler'; name = 'CoreGradesUserLinkHandler';
pattern = /\/grade\/report\/user\/index.php/; pattern = /\/grade\/report\/user\/index.php/;
constructor(private linkHelper: CoreContentLinksHelperProvider, private gradesProvider: CoreGradesProvider, constructor(private gradesProvider: CoreGradesProvider, private gradesHelper: CoreGradesHelperProvider) {
private domUtils: CoreDomUtilsProvider, private courseHelper: CoreCourseHelperProvider,
private loginHelper: CoreLoginHelperProvider) {
super(); super();
} }
@ -42,43 +37,20 @@ export class CoreGradesUserLinkHandler extends CoreContentLinksHandlerBase {
* @param {string} url The URL to treat. * @param {string} url The URL to treat.
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @param {number} [courseId] Course ID related to the URL. Optional but recommended. * @param {number} [courseId] Course ID related to the URL. Optional but recommended.
* @param {any} [data] Extra data to handle the URL.
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions. * @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
*/ */
getActions(siteIds: string[], url: string, params: any, courseId?: number): getActions(siteIds: string[], url: string, params: any, courseId?: number, data?: any):
CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> { CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
courseId = courseId || params.id; courseId = courseId || params.id;
data = data || {};
return [{ return [{
action: (siteId, navCtrl?): void => { action: (siteId, navCtrl?): void => {
const userId = params.userid ? parseInt(params.userid, 10) : false; const userId = params.userid && parseInt(params.userid, 10),
moduleId = data.cmid && parseInt(data.cmid, 10);
if (userId) { this.gradesHelper.goToGrades(courseId, userId, moduleId, navCtrl, siteId);
// Open the grades page directly.
const pageParams = {
course: {id: courseId},
userId: userId,
};
this.linkHelper.goInSite(navCtrl, 'CoreGradesCoursePage', pageParams, siteId);
} else {
// No userid, open the course with the grades tab selected.
const modal = this.domUtils.showModalLoading();
this.courseHelper.getCourse(courseId, siteId).then((result) => {
const pageParams: any = {
course: result.course,
selectedTab: 'CoreGrades'
};
// Use redirect to prevent loops in the navigation.
return this.loginHelper.redirect('CoreCourseSectionPage', pageParams, siteId);
}).catch(() => {
// Cannot get course for some reason, just open the grades page.
return this.linkHelper.goInSite(navCtrl, 'CoreGradesCoursePage', {course: {id: courseId}}, siteId);
}).finally(() => {
modal.dismiss();
});
}
} }
}]; }];
} }