MOBILE-4577 course: Implement course section link handler
parent
86477e69c5
commit
b3492a5fbf
|
@ -38,6 +38,7 @@ import {
|
|||
} from './services/handlers/my-courses-mainmenu';
|
||||
import { CoreCoursesRequestPushClickHandler } from './services/handlers/request-push-click';
|
||||
import { CoreCoursesMyCoursesLinkHandler } from './services/handlers/my-courses-link';
|
||||
import { CoreCoursesSectionLinkHandler } from '@features/courses/services/handlers/section-link';
|
||||
|
||||
/**
|
||||
* Get courses services.
|
||||
|
@ -89,6 +90,7 @@ const routes: Routes = [
|
|||
CoreContentLinksDelegate.registerHandler(CoreCoursesIndexLinkHandler.instance);
|
||||
CoreContentLinksDelegate.registerHandler(CoreCoursesMyCoursesLinkHandler.instance);
|
||||
CoreContentLinksDelegate.registerHandler(CoreCoursesDashboardLinkHandler.instance);
|
||||
CoreContentLinksDelegate.registerHandler(CoreCoursesSectionLinkHandler.instance);
|
||||
CorePushNotificationsDelegate.registerClickHandler(CoreCoursesEnrolPushClickHandler.instance);
|
||||
CorePushNotificationsDelegate.registerClickHandler(CoreCoursesRequestPushClickHandler.instance);
|
||||
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
// (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 { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||
import { CoreCourses } from '../courses';
|
||||
import { Params } from '@angular/router';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
|
||||
/**
|
||||
* Base handler to treat course links.
|
||||
*/
|
||||
export class CoreCoursesLinksHandlerBase extends CoreContentLinksHandlerBase {
|
||||
|
||||
/**
|
||||
* Get actions to open course content.
|
||||
*/
|
||||
protected getCourseActions(url: string, courseId: number, pageParams: Params = {}): CoreContentLinksAction[] {
|
||||
return [{
|
||||
action: async (siteId): Promise<void> => {
|
||||
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||
if (siteId === CoreSites.getCurrentSiteId()) {
|
||||
// Check if we already are in the course index page.
|
||||
if (CoreCourse.currentViewIsCourse(courseId)) {
|
||||
// Current view is this course, just select the contents tab.
|
||||
CoreCourse.selectCourseTab('', pageParams);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(this.actionOpen(courseId, url, pageParams));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Make the course the new history root (to avoid "loops" in history).
|
||||
await CoreCourseHelper.getAndOpenCourse(courseId, pageParams, siteId);
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to open the course, asking the user to enrol if needed.
|
||||
*
|
||||
* @param courseId Course ID.
|
||||
* @param url Treated URL.
|
||||
* @param pageParams Params to send to the new page.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
protected async actionOpen(courseId: number, url: string, pageParams: Params): Promise<void> {
|
||||
const isEnrolUrl = !!url.match(/(\/enrol\/index\.php)|(\/course\/enrol\.php)/);
|
||||
if (isEnrolUrl) {
|
||||
this.navigateCourseSummary(courseId, pageParams);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const modal = await CoreDomUtils.showModalLoading();
|
||||
|
||||
// Check if user is enrolled in the course.
|
||||
const hasAccess = await CoreCourseHelper.userHasAccessToCourse(courseId);
|
||||
|
||||
const guestInfo = await CoreCourseHelper.courseUsesGuestAccessInfo(courseId);
|
||||
pageParams.isGuest = guestInfo.guestAccess;
|
||||
|
||||
if (hasAccess && !guestInfo.guestAccess && !guestInfo.requiresUserInput) {
|
||||
// Direct access.
|
||||
const course = await CoreUtils.ignoreErrors(CoreCourses.getUserCourse(courseId), { id: courseId });
|
||||
|
||||
CoreCourseHelper.openCourse(course, { params: pageParams });
|
||||
} else {
|
||||
this.navigateCourseSummary(courseId, pageParams);
|
||||
|
||||
}
|
||||
|
||||
modal.dismiss();
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate course summary.
|
||||
*
|
||||
* @param courseId Course ID.
|
||||
* @param pageParams Params to send to the new page.
|
||||
*/
|
||||
protected navigateCourseSummary(courseId: number, pageParams: Params): void {
|
||||
CoreNavigator.navigateToSitePath(
|
||||
`/course/${courseId}/summary`,
|
||||
{ params: pageParams },
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -14,36 +14,20 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||
import { CoreCourses } from '../courses';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
import { Params } from '@angular/router';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreCoursesLinksHandlerBase } from '@features/courses/services/handlers/base-link-handler';
|
||||
|
||||
/**
|
||||
* Handler to treat links to course view or enrol (except site home).
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandlerBase {
|
||||
export class CoreCoursesCourseLinkHandlerService extends CoreCoursesLinksHandlerBase {
|
||||
|
||||
name = 'CoreCoursesCourseLinkHandler';
|
||||
pattern = /((\/enrol\/index\.php)|(\/course\/enrol\.php)|(\/course\/view\.php)).*([?&]id=\d+)/;
|
||||
|
||||
protected waitStart = 0;
|
||||
protected logger: CoreLogger;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.logger = CoreLogger.getInstance('CoreCoursesCourseLinkHandler');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
|
@ -77,27 +61,7 @@ export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandler
|
|||
}
|
||||
}
|
||||
|
||||
return [{
|
||||
action: async (siteId): Promise<void> => {
|
||||
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||
if (siteId === CoreSites.getCurrentSiteId()) {
|
||||
// Check if we already are in the course index page.
|
||||
if (CoreCourse.currentViewIsCourse(courseId)) {
|
||||
// Current view is this course, just select the contents tab.
|
||||
CoreCourse.selectCourseTab('', pageParams);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(this.actionOpen(courseId, url, pageParams));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Make the course the new history root (to avoid "loops" in history).
|
||||
await CoreCourseHelper.getAndOpenCourse(courseId, pageParams, siteId);
|
||||
},
|
||||
}];
|
||||
return this.getCourseActions(url, courseId, pageParams);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,56 +78,6 @@ export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandler
|
|||
return CoreSites.getSiteHomeId(siteId).then((siteHomeId) => courseId != siteHomeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to open the course, asking the user to enrol if needed.
|
||||
*
|
||||
* @param courseId Course ID.
|
||||
* @param url Treated URL.
|
||||
* @param pageParams Params to send to the new page.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
protected async actionOpen(courseId: number, url: string, pageParams: Params): Promise<void> {
|
||||
const isEnrolUrl = !!url.match(/(\/enrol\/index\.php)|(\/course\/enrol\.php)/);
|
||||
if (isEnrolUrl) {
|
||||
this.navigateCourseSummary(courseId, pageParams);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const modal = await CoreDomUtils.showModalLoading();
|
||||
|
||||
// Check if user is enrolled in the course.
|
||||
const hasAccess = await CoreCourseHelper.userHasAccessToCourse(courseId);
|
||||
|
||||
const guestInfo = await CoreCourseHelper.courseUsesGuestAccessInfo(courseId);
|
||||
pageParams.isGuest = guestInfo.guestAccess;
|
||||
|
||||
if (hasAccess && !guestInfo.guestAccess && !guestInfo.requiresUserInput) {
|
||||
// Direct access.
|
||||
const course = await CoreUtils.ignoreErrors(CoreCourses.getUserCourse(courseId), { id: courseId });
|
||||
|
||||
CoreCourseHelper.openCourse(course, { params: pageParams });
|
||||
} else {
|
||||
this.navigateCourseSummary(courseId, pageParams);
|
||||
|
||||
}
|
||||
|
||||
modal.dismiss();
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate course summary.
|
||||
*
|
||||
* @param courseId Course ID.
|
||||
* @param pageParams Params to send to the new page.
|
||||
*/
|
||||
protected navigateCourseSummary(courseId: number, pageParams: Params): void {
|
||||
CoreNavigator.navigateToSitePath(
|
||||
`/course/${courseId}/summary`,
|
||||
{ params: pageParams },
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const CoreCoursesCourseLinkHandler = makeSingleton(CoreCoursesCourseLinkHandlerService);
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
// (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 { makeSingleton } from '@singletons';
|
||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
import { CoreCourses, CoreEnrolledCourseData } from '@features/courses/services/courses';
|
||||
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreCoursesLinksHandlerBase } from '@features/courses/services/handlers/base-link-handler';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
|
||||
/**
|
||||
* Handler to treat links to course section.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CoreCoursesSectionLinkHandlerService extends CoreCoursesLinksHandlerBase {
|
||||
|
||||
name = 'CoreCoursesSectionLinkHandler';
|
||||
pattern = /\/course\/section\.php.*([?&]id=\d+)/;
|
||||
|
||||
private logger: CoreLogger;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.logger = CoreLogger.getInstance('CoreCoursesSectionLinkHandler');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async getActions(
|
||||
siteIds: string[],
|
||||
url: string,
|
||||
params: Record<string, string>,
|
||||
): Promise<CoreContentLinksAction[]> {
|
||||
try {
|
||||
const siteId = siteIds[0] ?? false;
|
||||
const sectionId = params.id ? Number(params.id) : false;
|
||||
const siteHomeId = await CoreSites.getSiteHomeId(siteId);
|
||||
const course = await this.getSectionCourse(sectionId, siteId);
|
||||
|
||||
if (!sectionId || !course || course.id === siteHomeId) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.getCourseActions(url, course.id, { sectionId });
|
||||
} catch (error) {
|
||||
this.logger.error(`Failed getting actions for url: '${url}'`, error);
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get which course a section belongs to.
|
||||
*
|
||||
* @param sectionId Section id.
|
||||
* @param siteId Site id.
|
||||
* @returns Course.
|
||||
*/
|
||||
private async getSectionCourse(sectionId: number | false, siteId: string | false): Promise<CoreEnrolledCourseData | null> {
|
||||
if (!siteId || !sectionId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Ideally, we would use a webservice to get this information; but such webservice doesn't exists.
|
||||
// Given that getting all the courses from a user could be very network intensive, all the requests
|
||||
// in this method will only use cache.
|
||||
|
||||
const courses = await CoreCourses.getUserCourses(true, siteId, CoreSitesReadingStrategy.ONLY_CACHE);
|
||||
|
||||
for (const course of courses) {
|
||||
const courseSections = await CoreCourse.getSections(
|
||||
course.id,
|
||||
true,
|
||||
true,
|
||||
{
|
||||
...CoreSites.getReadingStrategyPreSets(CoreSitesReadingStrategy.ONLY_CACHE),
|
||||
getCacheUsingCacheKey: true,
|
||||
},
|
||||
);
|
||||
|
||||
const courseSection = courseSections.find(section => section.id === sectionId);
|
||||
|
||||
if (!courseSection) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return course;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const CoreCoursesSectionLinkHandler = makeSingleton(CoreCoursesSectionLinkHandlerService);
|
Loading…
Reference in New Issue