MOBILE-3648 lesson: Implement link and push handlers

main
Dani Palou 2021-02-04 09:22:35 +01:00
parent e04c19596f
commit feb0319d3f
24 changed files with 732 additions and 73 deletions

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
import { CoreNavigator } from '@services/navigator';
@ -39,7 +39,7 @@ export class AddonBadgesBadgeLinkHandlerService extends CoreContentLinksHandlerB
* @param courseId Course ID related to the URL. Optional but recommended.
* @return List of (or promise resolved with list of) actions.
*/
getActions(siteIds: string[], url: string, params: Params): CoreContentLinksAction[] {
getActions(siteIds: string[], url: string, params: Record<string, string>): CoreContentLinksAction[] {
return [{
action: (siteId: string): void => {

View File

@ -49,7 +49,7 @@ export class AddonBadgesMyBadgesLinkHandlerService extends CoreContentLinksHandl
* @param siteId The site ID.
* @return Whether the handler is enabled for the URL and site.
*/
isEnabled(siteId: string): boolean | Promise<boolean> {
async isEnabled(siteId: string): Promise<boolean> {
return AddonBadges.instance.isPluginEnabled(siteId);
}

View File

@ -14,6 +14,7 @@
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
import { CoreNavigator } from '@services/navigator';
@ -39,7 +40,11 @@ export class AddonCalendarViewLinkHandlerService extends CoreContentLinksHandler
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @return List of (or promise resolved with list of) actions.
*/
getActions(siteIds: string[], url: string, params: Params): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
getActions(
siteIds: string[],
url: string,
params: Record<string, string>,
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
return [{
action: (siteId?: string): void => {
if (!params.view || params.view == 'month' || params.view == 'mini' || params.view == 'minithree') {
@ -47,7 +52,7 @@ export class AddonCalendarViewLinkHandlerService extends CoreContentLinksHandler
const stateParams: Params = {
courseId: params.course,
};
const timestamp = params.time ? params.time * 1000 : Date.now();
const timestamp = params.time ? Number(params.time) * 1000 : Date.now();
const date = new Date(timestamp);
stateParams.year = date.getFullYear();
@ -61,7 +66,7 @@ export class AddonCalendarViewLinkHandlerService extends CoreContentLinksHandler
const stateParams: Params = {
courseId: params.course,
};
const timestamp = params.time ? params.time * 1000 : Date.now();
const timestamp = params.time ? Number(params.time) * 1000 : Date.now();
const date = new Date(timestamp);
stateParams.year = date.getFullYear();
@ -94,7 +99,7 @@ export class AddonCalendarViewLinkHandlerService extends CoreContentLinksHandler
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @return Whether the handler is enabled for the URL and site.
*/
isEnabled(siteId: string, url: string, params: Params): boolean | Promise<boolean> {
async isEnabled(siteId: string, url: string, params: Record<string, string>): Promise<boolean> {
if (params.view && SUPPORTED_VIEWS.indexOf(params.view) == -1) {
// This type of view isn't supported in the app.
return false;

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
import { CoreNavigator } from '@services/navigator';
@ -39,7 +39,11 @@ export class AddonMessagesDiscussionLinkHandlerService extends CoreContentLinksH
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @return List of (or promise resolved with list of) actions.
*/
getActions(siteIds: string[], url: string, params: Params): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
getActions(
siteIds: string[],
url: string,
params: Record<string, string>,
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
return [{
action: (siteId): void => {
const stateParams = {
@ -59,7 +63,7 @@ export class AddonMessagesDiscussionLinkHandlerService extends CoreContentLinksH
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @return Whether the handler is enabled for the URL and site.
*/
async isEnabled(siteId: string, url: string, params: Params): Promise<boolean> {
async isEnabled(siteId: string, url: string, params: Record<string, string>): Promise<boolean> {
const enabled = await AddonMessages.instance.isPluginEnabled(siteId);
if (!enabled) {
return false;

View File

@ -14,16 +14,23 @@
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { Routes } from '@angular/router';
import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate';
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module';
import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate';
import { CoreCronDelegate } from '@services/cron';
import { CORE_SITE_SCHEMAS } from '@services/sites';
import { AddonModLessonComponentsModule } from './components/components.module';
import { SITE_SCHEMA, OFFLINE_SITE_SCHEMA } from './services/database/lesson';
import { SITE_SCHEMA, OFFLINE_SITE_SCHEMA, SYNC_SITE_SCHEMA } from './services/database/lesson';
import { AddonModLessonGradeLinkHandler } from './services/handlers/grade-link';
import { AddonModLessonIndexLinkHandler } from './services/handlers/index-link';
import { AddonModLessonListLinkHandler } from './services/handlers/list-link';
import { AddonModLessonModuleHandler, AddonModLessonModuleHandlerService } from './services/handlers/module';
import { AddonModLessonPrefetchHandler } from './services/handlers/prefetch';
import { AddonModLessonPushClickHandler } from './services/handlers/push-click';
import { AddonModLessonReportLinkHandler } from './services/handlers/report-link';
import { AddonModLessonSyncCronHandler } from './services/handlers/sync-cron';
const routes: Routes = [
@ -41,7 +48,7 @@ const routes: Routes = [
providers: [
{
provide: CORE_SITE_SCHEMAS,
useValue: [SITE_SCHEMA, OFFLINE_SITE_SCHEMA],
useValue: [SITE_SCHEMA, OFFLINE_SITE_SCHEMA, SYNC_SITE_SCHEMA],
multi: true,
},
{
@ -52,6 +59,11 @@ const routes: Routes = [
CoreCourseModuleDelegate.instance.registerHandler(AddonModLessonModuleHandler.instance);
CoreCourseModulePrefetchDelegate.instance.registerHandler(AddonModLessonPrefetchHandler.instance);
CoreCronDelegate.instance.register(AddonModLessonSyncCronHandler.instance);
CoreContentLinksDelegate.instance.registerHandler(AddonModLessonGradeLinkHandler.instance);
CoreContentLinksDelegate.instance.registerHandler(AddonModLessonIndexLinkHandler.instance);
CoreContentLinksDelegate.instance.registerHandler(AddonModLessonListLinkHandler.instance);
CoreContentLinksDelegate.instance.registerHandler(AddonModLessonReportLinkHandler.instance);
CorePushNotificationsDelegate.instance.registerClickHandler(AddonModLessonPushClickHandler.instance);
},
},
],

View File

@ -0,0 +1,102 @@
// (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 { Injectable } from '@angular/core';
import { CoreContentLinksModuleGradeHandler } from '@features/contentlinks/classes/module-grade-handler';
import { CoreCourse } from '@features/course/services/course';
import { CoreCourseHelper } from '@features/course/services/course-helper';
import { CoreNavigator } from '@services/navigator';
import { CoreDomUtils } from '@services/utils/dom';
import { makeSingleton } from '@singletons';
import { AddonModLesson } from '../lesson';
import { AddonModLessonModuleHandlerService } from './module';
/**
* Handler to treat links to lesson grade.
*/
@Injectable({ providedIn: 'root' })
export class AddonModLessonGradeLinkHandlerService extends CoreContentLinksModuleGradeHandler {
name = 'AddonModLessonGradeLinkHandler';
canReview = true;
constructor() {
super('AddonModLesson', 'lesson');
}
/**
* Go to the page to review.
*
* @param url The URL to treat.
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @param courseId Course ID related to the URL.
* @param siteId Site to use.
* @return Promise resolved when done.
*/
protected async goToReview(
url: string,
params: Record<string, unknown>,
courseId: number,
siteId: string,
): Promise<void> {
const moduleId = Number(params.id);
const modal = await CoreDomUtils.instance.showModalLoading();
try {
const module = await CoreCourse.instance.getModuleBasicInfo(moduleId, siteId);
courseId = Number(module.course || courseId || params.courseid || params.cid);
// Check if the user can see the user reports in the lesson.
const accessInfo = await AddonModLesson.instance.getAccessInformation(module.instance, { cmId: module.id, siteId });
if (accessInfo.canviewreports) {
// User can view reports, go to view the report.
CoreNavigator.instance.navigateToSitePath(
AddonModLessonModuleHandlerService.PAGE_NAME + `/user-retake/${courseId}/${module.instance}`,
{
params: { userId: Number(params.userid) },
siteId,
},
);
} else {
// User cannot view the report, go to lesson index.
CoreCourseHelper.instance.navigateToModule(moduleId, siteId, courseId, module.section);
}
} catch (error) {
CoreDomUtils.instance.showErrorModalDefault(error, 'core.course.errorgetmodule', true);
} finally {
modal.dismiss();
}
}
/**
* Check if the handler is enabled for a certain site (site + user) and a URL.
* If not defined, defaults to true.
*
* @param siteId The site ID.
* @param url The URL to treat.
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @param courseId Course ID related to the URL. Optional but recommended.
* @return Whether the handler is enabled for the URL and site.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async isEnabled(siteId: string, url: string, params: Record<string, string>, courseId?: number): Promise<boolean> {
return AddonModLesson.instance.isPluginEnabled(siteId);
}
}
export class AddonModLessonGradeLinkHandler extends makeSingleton(AddonModLessonGradeLinkHandlerService) {}

View File

@ -0,0 +1,121 @@
// (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 { Injectable } from '@angular/core';
import { CoreContentLinksModuleIndexHandler } from '@features/contentlinks/classes/module-index-handler';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
import { CoreCourse } from '@features/course/services/course';
import { CoreCourseHelper } from '@features/course/services/course-helper';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { makeSingleton } from '@singletons';
import { AddonModLesson } from '../lesson';
/**
* Handler to treat links to lesson index.
*/
@Injectable({ providedIn: 'root' })
export class AddonModLessonIndexLinkHandlerService extends CoreContentLinksModuleIndexHandler {
name = 'AddonModLessonIndexLinkHandler';
constructor() {
super('AddonModLesson', 'lesson');
}
/**
* Get the list of actions for a link (url).
*
* @param siteIds List of sites the URL belongs to.
* @param url The URL to treat.
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @param courseId Course ID related to the URL. Optional but recommended.
* @return List of (or promise resolved with list of) actions.
*/
getActions(
siteIds: string[],
url: string,
params: Record<string, string>,
courseId?: number,
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
courseId = Number(courseId || params.courseid || params.cid);
return [{
action: (siteId): void => {
/* Ignore the pageid param. If we open the lesson player with a certain page and the user hasn't started
the lesson, an error is thrown: could not find lesson_timer records. */
if (params.userpassword) {
this.navigateToModuleWithPassword(parseInt(params.id, 10), courseId!, params.userpassword, siteId);
} else {
CoreCourseHelper.instance.navigateToModule(parseInt(params.id, 10), siteId, courseId);
}
},
}];
}
/**
* Check if the handler is enabled for a certain site (site + user) and a URL.
* If not defined, defaults to true.
*
* @param siteId The site ID.
* @param url The URL to treat.
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @param courseId Course ID related to the URL. Optional but recommended.
* @return Whether the handler is enabled for the URL and site.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isEnabled(siteId: string, url: string, params: Record<string, string>, courseId?: number): Promise<boolean> {
return AddonModLesson.instance.isPluginEnabled(siteId);
}
/**
* Navigate to a lesson module (index page) with a fixed password.
*
* @param moduleId Module ID.
* @param courseId Course ID.
* @param password Password.
* @param siteId Site ID.
* @return Promise resolved when navigated.
*/
protected async navigateToModuleWithPassword(
moduleId: number,
courseId: number,
password: string,
siteId: string,
): Promise<void> {
const modal = await CoreDomUtils.instance.showModalLoading();
try {
// Get the module.
const module = await CoreCourse.instance.getModuleBasicInfo(moduleId, siteId);
courseId = courseId || module.course;
// Store the password so it's automatically used.
await CoreUtils.instance.ignoreErrors(AddonModLesson.instance.storePassword(module.instance, password, siteId));
await CoreCourseHelper.instance.navigateToModule(moduleId, siteId, courseId, module.section);
} catch {
// Error, go to index page.
await CoreCourseHelper.instance.navigateToModule(moduleId, siteId, courseId);
} finally {
modal.dismiss();
}
}
}
export class AddonModLessonIndexLinkHandler extends makeSingleton(AddonModLessonIndexLinkHandlerService) {}

View File

@ -0,0 +1,45 @@
// (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 { Injectable } from '@angular/core';
import { CoreContentLinksModuleListHandler } from '@features/contentlinks/classes/module-list-handler';
import { makeSingleton } from '@singletons';
import { AddonModLesson } from '../lesson';
/**
* Handler to treat links to lesson list page.
*/
@Injectable({ providedIn: 'root' })
export class AddonModLessonListLinkHandlerService extends CoreContentLinksModuleListHandler {
name = 'AddonModLessonListLinkHandler';
constructor() {
super('AddonModLesson', 'lesson');
}
/**
* Check if the handler is enabled on a site level.
*
* @return Promise resolved with boolean: whether or not the handler is enabled on a site level.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isEnabled(siteId: string, url: string, params: Record<string, string>, courseId?: number): Promise<boolean> {
return AddonModLesson.instance.isPluginEnabled(siteId);
}
}
export class AddonModLessonListLinkHandler extends makeSingleton(AddonModLessonListLinkHandlerService) {}

View File

@ -0,0 +1,70 @@
// (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 { Injectable } from '@angular/core';
import { CoreGrades } from '@features/grades/services/grades';
import { CoreGradesHelper } from '@features/grades/services/grades-helper';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreUtils } from '@services/utils/utils';
import { makeSingleton } from '@singletons';
/**
* Handler for lesson push notifications clicks.
*/
@Injectable({ providedIn: 'root' })
export class AddonModLessonPushClickHandlerService implements CorePushNotificationsClickHandler {
name = 'AddonModLessonPushClickHandler';
priority = 200;
featureName = 'CoreCourseModuleDelegate_AddonModLesson';
/**
* Check if a notification click is handled by this handler.
*
* @param notification The notification to check.
* @return Whether the notification click is handled by this handler.
*/
async handles(notification: NotificationData): Promise<boolean> {
if (CoreUtils.instance.isTrueOrOne(notification.notif) && notification.moodlecomponent == 'mod_lesson' &&
notification.name == 'graded_essay') {
return CoreGrades.instance.isPluginEnabledForCourse(Number(notification.courseid), notification.site);
}
return false;
}
/**
* Handle the notification click.
*
* @param notification The notification to check.
* @return Promise resolved when done.
*/
handleClick(notification: NotificationData): Promise<void> {
const data = notification.customdata || {};
const courseId = Number(notification.courseid);
const moduleId = Number(data.cmid);
return CoreGradesHelper.instance.goToGrades(courseId, undefined, moduleId, notification.site);
}
}
export class AddonModLessonPushClickHandler extends makeSingleton(AddonModLessonPushClickHandlerService) {}
type NotificationData = CorePushNotificationsNotificationBasicData & {
courseid: number;
};

View File

@ -0,0 +1,165 @@
// (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 { Injectable } from '@angular/core';
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
import { CoreCourse } from '@features/course/services/course';
import { CoreNavigator } from '@services/navigator';
import { CoreDomUtils } from '@services/utils/dom';
import { makeSingleton } from '@singletons';
import { AddonModLesson } from '../lesson';
import { AddonModLessonModuleHandlerService } from './module';
/**
* Handler to treat links to lesson report.
*/
@Injectable({ providedIn: 'root' })
export class AddonModLessonReportLinkHandlerService extends CoreContentLinksHandlerBase {
name = 'AddonModLessonReportLinkHandler';
featureName = 'CoreCourseModuleDelegate_AddonModLesson';
pattern = /\/mod\/lesson\/report\.php.*([&?]id=\d+)/;
/**
* Get the list of actions for a link (url).
*
* @param siteIds List of sites the URL belongs to.
* @param url The URL to treat.
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @param courseId Course ID related to the URL. Optional but recommended.
* @param data Extra data to handle the URL.
* @return List of (or promise resolved with list of) actions.
*/
getActions(
siteIds: string[],
url: string,
params: Record<string, string>,
courseId?: number,
data?: unknown, // eslint-disable-line @typescript-eslint/no-unused-vars
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
courseId = Number(courseId || params.courseid || params.cid);
return [{
action: (siteId) => {
if (!params.action || params.action == 'reportoverview') {
// Go to overview.
this.openReportOverview(Number(params.id), courseId, Number(params.group), siteId);
} else if (params.action == 'reportdetail') {
this.openUserRetake(Number(params.id), Number(params.userid), Number(params.try), siteId, courseId);
}
},
}];
}
/**
* Check if the handler is enabled for a certain site (site + user) and a URL.
* If not defined, defaults to true.
*
* @param siteId The site ID.
* @param url The URL to treat.
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @param courseId Course ID related to the URL. Optional but recommended.
* @return Whether the handler is enabled for the URL and site.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async isEnabled(siteId: string, url: string, params: Record<string, string>, courseId?: number): Promise<boolean> {
if (params.action == 'reportdetail' && !params.userid) {
// Individual details are only available if the teacher is seeing a certain user.
return false;
}
return AddonModLesson.instance.isPluginEnabled(siteId);
}
/**
* Open report overview.
*
* @param moduleId Module ID.
* @param courseId Course ID.
* @param groupId Group ID.
* @param siteId Site ID.
* @param navCtrl The NavController to use to navigate.
* @return Promise resolved when done.
*/
protected async openReportOverview(moduleId: number, courseId?: number, groupId?: number, siteId?: string): Promise<void> {
const modal = await CoreDomUtils.instance.showModalLoading();
try {
// Get the module object.
const module = await CoreCourse.instance.getModuleBasicInfo(moduleId, siteId);
const params = {
module: module,
courseId: courseId || module.course,
action: 'report',
group: groupId === undefined || isNaN(groupId) ? null : groupId,
};
CoreNavigator.instance.navigateToSitePath(AddonModLessonModuleHandlerService.PAGE_NAME, { params, siteId });
} catch (error) {
CoreDomUtils.instance.showErrorModalDefault(error, 'Error processing link.');
} finally {
modal.dismiss();
}
}
/**
* Open a user's retake.
*
* @param moduleId Module ID.
* @param userId User ID.
* @param courseId Course ID.
* @param retake Retake to open.
* @param groupId Group ID.
* @param siteId Site ID.
* @param navCtrl The NavController to use to navigate.
* @return Promise resolved when done.
*/
protected async openUserRetake(
moduleId: number,
userId: number,
retake: number,
siteId: string,
courseId?: number,
): Promise<void> {
const modal = await CoreDomUtils.instance.showModalLoading();
try {
// Get the module object.
const module = await CoreCourse.instance.getModuleBasicInfo(moduleId, siteId);
courseId = courseId || module.course;
const params = {
userId: userId,
retake: retake || 0,
};
CoreNavigator.instance.navigateToSitePath(
AddonModLessonModuleHandlerService.PAGE_NAME + `/user-retake/${courseId}/${module.instance}`,
{ params, siteId },
);
} catch (error) {
CoreDomUtils.instance.showErrorModalDefault(error, 'Error processing link.');
} finally {
modal.dismiss();
}
}
}
export class AddonModLessonReportLinkHandler extends makeSingleton(AddonModLessonReportLinkHandlerService) {}

View File

@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Params } from '@angular/router';
import { CoreContentLinksHandler, CoreContentLinksAction } from '../services/contentlinks-delegate';
/**
@ -67,7 +66,7 @@ export class CoreContentLinksHandlerBase implements CoreContentLinksHandler {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
url: string,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
params: Params,
params: Record<string, string>,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
courseId?: number,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@ -112,7 +111,7 @@ export class CoreContentLinksHandlerBase implements CoreContentLinksHandler {
* @return Whether the handler is enabled for the URL and site.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isEnabled(siteId: string, url: string, params: Params, courseId?: number): boolean | Promise<boolean> {
async isEnabled(siteId: string, url: string, params: Record<string, string>, courseId?: number): Promise<boolean> {
return true;
}

View File

@ -16,8 +16,7 @@ import { CoreContentLinksAction } from '../services/contentlinks-delegate';
import { CoreContentLinksHandlerBase } from './base-handler';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
// import { CoreCourseHelper } from '@features/course/services/helper';
import { Params } from '@angular/router';
import { CoreCourseHelper } from '@features/course/services/course-helper';
/**
* Handler to handle URLs pointing to the grade of a module.
@ -64,21 +63,26 @@ export class CoreContentLinksModuleGradeHandler extends CoreContentLinksHandlerB
getActions(
siteIds: string[],
url: string,
params: Params,
params: Record<string, string>,
courseId?: number,
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
courseId = courseId || params.courseid || params.cid;
courseId = Number(courseId || params.courseid || params.cid);
return [{
action: async (siteId): Promise<void> => {
// Check if userid is the site's current user.
const modal = await CoreDomUtils.instance.showModalLoading();
const site = await CoreSites.instance.getSite(siteId);
if (!params.userid || params.userid == site.getUserId()) {
if (!params.userid || Number(params.userid) == site.getUserId()) {
// No user specified or current user. Navigate to module.
// @todo CoreCourseHelper.instance.navigateToModule(parseInt(params.id, 10), siteId, courseId, undefined,
// this.useModNameToGetModule ? this.modName : undefined, undefined, navCtrl);
CoreCourseHelper.instance.navigateToModule(
Number(params.id),
siteId,
courseId,
undefined,
this.useModNameToGetModule ? this.modName : undefined,
);
} else if (this.canReview) {
// Use the goToReview function.
this.goToReview(url, params, courseId!, siteId);
@ -103,7 +107,7 @@ export class CoreContentLinksModuleGradeHandler extends CoreContentLinksHandlerB
*/
protected async goToReview(
url: string, // eslint-disable-line @typescript-eslint/no-unused-vars
params: Params, // eslint-disable-line @typescript-eslint/no-unused-vars
params: Record<string, string>, // eslint-disable-line @typescript-eslint/no-unused-vars
courseId: number, // eslint-disable-line @typescript-eslint/no-unused-vars
siteId: string, // eslint-disable-line @typescript-eslint/no-unused-vars
): Promise<void> {

View File

@ -15,6 +15,7 @@
import { CoreContentLinksHandlerBase } from './base-handler';
import { Params } from '@angular/router';
import { CoreContentLinksAction } from '../services/contentlinks-delegate';
import { CoreCourseHelper } from '@features/course/services/course-helper';
/**
* Handler to handle URLs pointing to the index of a module.
@ -59,8 +60,8 @@ export class CoreContentLinksModuleIndexHandler extends CoreContentLinksHandlerB
* @return List of params to pass to navigateToModule / navigateToModuleByInstance.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
getPageParams(url: string, params: Params, courseId?: number): Params {
return [];
getPageParams(url: string, params: Record<string, string>, courseId?: number): Params {
return {};
}
/**
@ -73,34 +74,45 @@ export class CoreContentLinksModuleIndexHandler extends CoreContentLinksHandlerB
* @return List of (or promise resolved with list of) actions.
*/
getActions(
siteIds: string[], // eslint-disable-line @typescript-eslint/no-unused-vars
url: string, // eslint-disable-line @typescript-eslint/no-unused-vars
params: Params, // eslint-disable-line @typescript-eslint/no-unused-vars
courseId?: number, // eslint-disable-line @typescript-eslint/no-unused-vars
siteIds: string[],
url: string,
params: Record<string, string>,
courseId?: number,
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
return [];
/*
courseId = courseId || params.courseid || params.cid;
courseId = Number(courseId || params.courseid || params.cid);
const pageParams = this.getPageParams(url, params, courseId);
if (this.instanceIdParam && typeof params[this.instanceIdParam] != 'undefined') {
const instanceId = parseInt(params[this.instanceIdParam], 10);
return [{
action: (siteId): void => {
this.courseHelper.navigateToModuleByInstance(instanceId, this.modName, siteId, courseId, undefined,
this.useModNameToGetModule, pageParams);
action: (siteId) => {
CoreCourseHelper.instance.navigateToModuleByInstance(
instanceId,
this.modName,
siteId,
courseId,
undefined,
this.useModNameToGetModule,
pageParams,
);
},
}];
}
return [{
action: (siteId): void => {
this.courseHelper.navigateToModule(parseInt(params.id, 10), siteId, courseId, undefined,
this.useModNameToGetModule ? this.modName : undefined, pageParams);
action: (siteId) => {
CoreCourseHelper.instance.navigateToModule(
parseInt(params.id, 10),
siteId,
courseId,
undefined,
this.useModNameToGetModule ? this.modName : undefined,
pageParams,
);
},
}];
*/
}
}

View File

@ -14,7 +14,7 @@
import { CoreContentLinksHandlerBase } from './base-handler';
import { Translate } from '@singletons';
import { Params } from '@angular/router';
import { CoreContentLinksAction } from '../services/contentlinks-delegate';
import { CoreNavigator } from '@services/navigator';
@ -53,7 +53,11 @@ export class CoreContentLinksModuleListHandler extends CoreContentLinksHandlerBa
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @return List of (or promise resolved with list of) actions.
*/
getActions(siteIds: string[], url: string, params: Params): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
getActions(
siteIds: string[],
url: string,
params: Record<string, string>,
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
return [{
action: (siteId): void => {

View File

@ -17,7 +17,6 @@ import { CoreLogger } from '@singletons/logger';
import { CoreSites } from '@services/sites';
import { CoreUrlUtils } from '@services/utils/url';
import { CoreUtils } from '@services/utils/utils';
import { Params } from '@angular/router';
import { makeSingleton } from '@singletons';
/**
@ -56,8 +55,13 @@ export interface CoreContentLinksHandler {
* @param data Extra data to handle the URL.
* @return List of (or promise resolved with list of) actions.
*/
getActions(siteIds: string[], url: string, params: Params, courseId?: number, data?: unknown):
CoreContentLinksAction[] | Promise<CoreContentLinksAction[]>;
getActions(
siteIds: string[],
url: string,
params: Record<string, string>,
courseId?: number,
data?: unknown,
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]>;
/**
* Check if a URL is handled by this handler.
@ -85,7 +89,7 @@ export interface CoreContentLinksHandler {
* @param courseId Course ID related to the URL. Optional but recommended.
* @return Whether the handler is enabled for the URL and site.
*/
isEnabled?(siteId: string, url: string, params: Params, courseId?: number): boolean | Promise<boolean>;
isEnabled?(siteId: string, url: string, params: Record<string, string>, courseId?: number): Promise<boolean>;
}
/**
@ -244,7 +248,7 @@ export class CoreContentLinksDelegateService {
protected async isHandlerEnabled(
handler: CoreContentLinksHandler,
url: string,
params: Params,
params: Record<string, string>,
courseId: number,
siteId: string,
): Promise<boolean> {
@ -264,7 +268,7 @@ export class CoreContentLinksDelegateService {
return true;
}
return handler.isEnabled(siteId, url, params, courseId);
return await handler.isEnabled(siteId, url, params, courseId);
}
/**

View File

@ -64,6 +64,9 @@ import { CoreTimeUtils } from '@services/utils/time';
import { CoreEventObserver, CoreEventPackageStatusChanged, CoreEvents } from '@singletons/events';
import { CoreFilterHelper } from '@features/filter/services/filter-helper';
import { CoreNetworkError } from '@classes/errors/network-error';
import { CoreSiteHome } from '@features/sitehome/services/sitehome';
import { CoreNavigator } from '@services/navigator';
import { CoreSiteHomeHomeHandlerService } from '@features/sitehome/services/handlers/sitehome-home';
/**
* Prefetch info of a module.
@ -1392,8 +1395,35 @@ export class CoreCourseHelperProvider {
* @param modParams Params to pass to the module
* @return Promise resolved when done.
*/
navigateToModuleByInstance(): void {
// @todo params and logic
async navigateToModuleByInstance(
instanceId: number,
modName: string,
siteId?: string,
courseId?: number,
sectionId?: number,
useModNameToGetModule: boolean = false,
modParams?: Params,
): Promise<void> {
const modal = await CoreDomUtils.instance.showModalLoading();
try {
const module = await CoreCourse.instance.getModuleBasicInfoByInstance(instanceId, modName, siteId);
this.navigateToModule(
module.id,
siteId,
module.course,
sectionId,
useModNameToGetModule ? modName : undefined,
modParams,
);
} catch (error) {
CoreDomUtils.instance.showErrorModalDefault(error, 'core.course.errorgetmodule', true);
} finally {
// Just in case. In fact we need to dismiss the modal before showing a toast or error message.
modal.dismiss();
}
}
/**
@ -1408,8 +1438,82 @@ export class CoreCourseHelperProvider {
* @param modParams Params to pass to the module
* @return Promise resolved when done.
*/
navigateToModule(): void {
// @todo params and logic
async navigateToModule(
moduleId: number,
siteId?: string,
courseId?: number,
sectionId?: number,
modName?: string,
modParams?: Params,
): Promise<void> {
siteId = siteId || CoreSites.instance.getCurrentSiteId();
const modal = await CoreDomUtils.instance.showModalLoading();
try {
if (!courseId) {
// We don't have courseId.
const module = await CoreCourse.instance.getModuleBasicInfo(moduleId, siteId);
courseId = module.course;
sectionId = module.section;
} else if (!sectionId) {
// We don't have sectionId but we have courseId.
sectionId = await CoreCourse.instance.getModuleSectionId(moduleId, siteId);
}
// Get the site.
const site = await CoreSites.instance.getSite(siteId);
// Get the module.
const module = <CoreCourseModule>
await CoreCourse.instance.getModule(moduleId, courseId, sectionId, false, false, siteId, modName);
if (CoreSites.instance.getCurrentSiteId() == site.getId()) {
// Try to use the module's handler to navigate cleanly.
module.handlerData = CoreCourseModuleDelegate.instance.getModuleDataFor(
module.modname,
module,
courseId,
sectionId,
false,
);
if (module.handlerData?.action) {
modal.dismiss();
return module.handlerData.action(new Event('click'), module, courseId, { params: modParams });
}
}
this.logger.warn('navCtrl was not passed to navigateToModule by the link handler for ' + module.modname);
const params = {
course: { id: courseId },
module: module,
sectionId: sectionId,
modParams: modParams,
};
if (courseId == site.getSiteHomeId()) {
// Check if site home is available.
const isAvailable = await CoreSiteHome.instance.isAvailable();
if (isAvailable) {
await CoreNavigator.instance.navigateToSitePath(CoreSiteHomeHomeHandlerService.PAGE_NAME, { params, siteId });
return;
}
}
modal.dismiss();
await this.getAndOpenCourse(courseId, params, siteId);
} catch (error) {
CoreDomUtils.instance.showErrorModalDefault(error, 'core.course.errorgetmodule', true);
} finally {
modal.dismiss();
}
}
/**
@ -1744,9 +1848,7 @@ export class CoreCourseHelperProvider {
params = params || {};
Object.assign(params, { course: course });
// @todo implement open course.
// await CoreNavigator.instance.navigateToSitePath('/course/.../...', { siteId, queryParams: params });
// return CoreNavigator.instance.openInSiteMainMenu(CoreNavigatorService.OPEN_COURSE, params, siteId);
await CoreNavigator.instance.navigateToSitePath('course', { siteId, params });
}
}

View File

@ -48,7 +48,7 @@ export class CoreCoursesDashboardLinkHandlerService extends CoreContentLinksHand
* @param siteId The site ID.
* @return Whether the handler is enabled for the URL and site.
*/
isEnabled(siteId: string): boolean | Promise<boolean> {
async isEnabled(siteId: string): Promise<boolean> {
return CoreDashboardHomeHandler.instance.isEnabledForSite(siteId);
}

View File

@ -48,7 +48,7 @@ export class CoreGradesOverviewLinkHandlerService extends CoreContentLinksHandle
* @param siteId The site ID.
* @return Whether the handler is enabled for the URL and site.
*/
isEnabled(siteId: string): boolean | Promise<boolean> {
async isEnabled(siteId: string): Promise<boolean> {
return CoreGrades.instance.isCourseGradesEnabled(siteId);
}

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
import { CoreGrades } from '@features/grades/services/grades';
@ -42,16 +42,16 @@ export class CoreGradesUserLinkHandlerService extends CoreContentLinksHandlerBas
getActions(
siteIds: string[],
url: string,
params: Params,
params: Record<string, string>,
courseId?: number,
data?: { cmid?: string },
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
courseId = courseId || params.id;
courseId = courseId || Number(params.id);
data = data || {};
return [{
action: (siteId): void => {
const userId = params.userid && parseInt(params.userid, 10);
const userId = params.userid ? parseInt(params.userid, 10) : undefined;
const moduleId = data?.cmid && parseInt(data.cmid, 10) || undefined;
CoreGradesHelper.instance.goToGrades(courseId!, userId, moduleId, siteId);
@ -69,12 +69,12 @@ export class CoreGradesUserLinkHandlerService extends CoreContentLinksHandlerBas
* @param courseId Course ID related to the URL. Optional but recommended.
* @return Whether the handler is enabled for the URL and site.
*/
isEnabled(siteId: string, url: string, params: Params, courseId?: number): boolean | Promise<boolean> {
async isEnabled(siteId: string, url: string, params: Record<string, string>, courseId?: number): Promise<boolean> {
if (!courseId && !params.id) {
return false;
}
return CoreGrades.instance.isPluginEnabledForCourse(courseId || params.id, siteId);
return CoreGrades.instance.isPluginEnabledForCourse(courseId || Number(params.id), siteId);
}
}

View File

@ -15,6 +15,8 @@
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { CoreCronDelegate } from '@services/cron';
import { CORE_SITE_SCHEMAS } from '@services/sites';
import { SITE_SCHEMA } from './services/database/pushnotifications';
import { CorePushNotificationsRegisterCronHandler } from './services/handlers/register-cron';
import { CorePushNotificationsUnregisterCronHandler } from './services/handlers/unregister-cron';
import { CorePushNotifications } from './services/pushnotifications';
@ -25,6 +27,11 @@ import { CorePushNotifications } from './services/pushnotifications';
imports: [
],
providers: [
{
provide: CORE_SITE_SCHEMAS,
useValue: [SITE_SCHEMA],
multi: true,
},
{
provide: APP_INITIALIZER,
multi: true,

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { CoreSites } from '@services/sites';
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
@ -59,7 +59,7 @@ export class CoreSiteHomeIndexLinkHandlerService extends CoreContentLinksHandler
* @param courseId Course ID related to the URL. Optional but recommended.
* @return Whether the handler is enabled for the URL and site.
*/
async isEnabled(siteId: string, url: string, params: Params, courseId?: number): Promise<boolean> {
async isEnabled(siteId: string, url: string, params: Record<string, string>, courseId?: number): Promise<boolean> {
courseId = parseInt(params.id, 10);
if (!courseId) {
return false;

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
import { CoreNavigator } from '@services/navigator';
@ -42,7 +42,7 @@ export class CoreTagIndexLinkHandlerService extends CoreContentLinksHandlerBase
getActions(
siteIds: string[],
url: string,
params: Params,
params: Record<string, string>,
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
return [{
action: (siteId): void => {
@ -77,7 +77,7 @@ export class CoreTagIndexLinkHandlerService extends CoreContentLinksHandlerBase
* @param courseId Course ID related to the URL. Optional but recommended.
* @return Whether the handler is enabled for the URL and site.
*/
isEnabled(siteId: string): boolean | Promise<boolean> {
async isEnabled(siteId: string): Promise<boolean> {
return CoreTag.instance.areTagsAvailable(siteId);
}

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
import { CoreNavigator } from '@services/navigator';
@ -39,7 +39,11 @@ export class CoreTagSearchLinkHandlerService extends CoreContentLinksHandlerBase
* @param data Extra data to handle the URL.
* @return List of (or promise resolved with list of) actions.
*/
getActions(siteIds: string[], url: string, params: Params): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
getActions(
siteIds: string[],
url: string,
params: Record<string, string>,
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
return [{
action: (siteId): void => {
const pageParams = {
@ -59,7 +63,7 @@ export class CoreTagSearchLinkHandlerService extends CoreContentLinksHandlerBase
* @param siteId The site ID.
* @return Whether the handler is enabled for the URL and site.
*/
isEnabled(siteId: string): boolean | Promise<boolean> {
async isEnabled(siteId: string): Promise<boolean> {
return CoreTag.instance.areTagsAvailable(siteId);
}

View File

@ -13,7 +13,6 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
@ -43,7 +42,7 @@ export class CoreUserProfileLinkHandlerService extends CoreContentLinksHandlerBa
getActions(
siteIds: string[],
url: string,
params: Params,
params: Record<string, string>,
courseId?: number, // eslint-disable-line @typescript-eslint/no-unused-vars
data?: unknown, // eslint-disable-line @typescript-eslint/no-unused-vars
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
@ -70,7 +69,7 @@ export class CoreUserProfileLinkHandlerService extends CoreContentLinksHandlerBa
* @return Whether the handler is enabled for the URL and site.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isEnabled(siteId: string, url: string, params: Params, courseId?: number): boolean | Promise<boolean> {
async isEnabled(siteId: string, url: string, params: Record<string, string>, courseId?: number): Promise<boolean> {
return url.indexOf('/grade/report/') == -1;
}