MOBILE-2309 contentlinks: Implement some handlers and handle links
parent
b3d0457540
commit
3cb62c748c
|
@ -58,6 +58,7 @@ import { CoreFileUploaderModule } from '../core/fileuploader/fileuploader.module
|
|||
import { CoreSharedFilesModule } from '../core/sharedfiles/sharedfiles.module';
|
||||
import { CoreCourseModule } from '../core/course/course.module';
|
||||
import { CoreSiteHomeModule } from '../core/sitehome/sitehome.module';
|
||||
import { CoreContentLinksModule } from '../core/contentlinks/contentlinks.module';
|
||||
|
||||
// Addon modules.
|
||||
import { AddonCalendarModule } from '../addon/calendar/calendar.module';
|
||||
|
@ -94,6 +95,7 @@ export function createTranslateLoader(http: HttpClient) {
|
|||
CoreSharedFilesModule,
|
||||
CoreCourseModule,
|
||||
CoreSiteHomeModule,
|
||||
CoreContentLinksModule,
|
||||
AddonCalendarModule
|
||||
],
|
||||
bootstrap: [IonicApp],
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreContentLinksAction } from '../providers/delegate';
|
||||
import { CoreContentLinksHandlerBase } from './base-handler';
|
||||
import { CoreSitesProvider } from '../../../providers/sites';
|
||||
|
@ -64,7 +65,7 @@ export class CoreContentLinksModuleGradeHandler extends CoreContentLinksHandlerB
|
|||
|
||||
courseId = courseId || params.courseid || params.cid;
|
||||
return [{
|
||||
action: (siteId) : void => {
|
||||
action: (siteId, navCtrl?) : void => {
|
||||
// Check if userid is the site's current user.
|
||||
const modal = this.domUtils.showModalLoading();
|
||||
this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
@ -73,7 +74,7 @@ export class CoreContentLinksModuleGradeHandler extends CoreContentLinksHandlerB
|
|||
this.courseHelper.navigateToModule(parseInt(params.id, 10), siteId, courseId);
|
||||
} else if (this.canReview) {
|
||||
// Use the goToReview function.
|
||||
this.goToReview(url, params, courseId, siteId);
|
||||
this.goToReview(url, params, courseId, siteId, navCtrl);
|
||||
} else {
|
||||
// Not current user and cannot review it in the app, open it in browser.
|
||||
site.openInBrowserWithAutoLogin(url);
|
||||
|
@ -91,10 +92,11 @@ export class CoreContentLinksModuleGradeHandler extends CoreContentLinksHandlerB
|
|||
* @param {string} url The URL to treat.
|
||||
* @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.
|
||||
* @param {string} siteId List of sites the URL belongs to.
|
||||
* @param {string} siteId Site to use.
|
||||
* @param {NavController} [navCtrl] Nav Controller to use to navigate.
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
protected goToReview(url: string, params: any, courseId: number, siteId: string) : Promise<any> {
|
||||
protected goToReview(url: string, params: any, courseId: number, siteId: string, navCtrl?: NavController) : Promise<any> {
|
||||
// This function should be overridden.
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ export class CoreContentLinksModuleIndexHandler extends CoreContentLinksHandlerB
|
|||
|
||||
courseId = courseId || params.courseid || params.cid;
|
||||
return [{
|
||||
action: (siteId) => {
|
||||
action: (siteId, navCtrl?) => {
|
||||
this.courseHelper.navigateToModule(parseInt(params.id, 10), siteId, courseId);
|
||||
}
|
||||
}];
|
||||
|
|
|
@ -80,7 +80,7 @@ export class CoreContentLinksChooseSitePage implements OnInit {
|
|||
* @param {string} siteId Site ID.
|
||||
*/
|
||||
siteClicked(siteId: string) : void {
|
||||
this.action.action(siteId);
|
||||
this.action.action(siteId, this.navCtrl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreLoggerProvider } from '../../../providers/logger';
|
||||
import { CoreSitesProvider } from '../../../providers/sites';
|
||||
import { CoreUrlUtilsProvider } from '../../../providers/utils/url';
|
||||
|
@ -115,8 +116,9 @@ export interface CoreContentLinksAction {
|
|||
* Action to perform when the link is clicked.
|
||||
*
|
||||
* @param {string} siteId The site ID.
|
||||
* @param {NavController} [navCtrl] Nav Controller to use to navigate.
|
||||
*/
|
||||
action(siteId: string) : void;
|
||||
action(siteId: string, navCtrl?: NavController) : void;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -202,9 +202,10 @@ export class CoreContentLinksHelperProvider {
|
|||
* @param {string} url URL to handle.
|
||||
* @param {string} [username] Username related with the URL. E.g. in 'http://myuser@m.com', url would be 'http://m.com' and
|
||||
* the username 'myuser'. Don't use it if you don't want to filter by username.
|
||||
* @param {NavController} [navCtrl] Nav Controller to use to navigate.
|
||||
* @return {Promise<boolean>} Promise resolved with a boolean: true if URL was treated, false otherwise.
|
||||
*/
|
||||
handleLink(url: string, username?: string) : Promise<boolean> {
|
||||
handleLink(url: string, username?: string, navCtrl?: NavController) : Promise<boolean> {
|
||||
// Check if the link should be treated by some component/addon.
|
||||
return this.contentLinksDelegate.getActionsFor(url, undefined, username).then((actions) => {
|
||||
const action = this.getFirstValidAction(actions);
|
||||
|
@ -212,18 +213,18 @@ export class CoreContentLinksHelperProvider {
|
|||
if (!this.sitesProvider.isLoggedIn()) {
|
||||
// No current site. Perform the action if only 1 site found, choose the site otherwise.
|
||||
if (action.sites.length == 1) {
|
||||
action.action(action.sites[0]);
|
||||
action.action(action.sites[0], navCtrl);
|
||||
} else {
|
||||
this.goToChooseSite(url);
|
||||
}
|
||||
} else if (action.sites.length == 1 && action.sites[0] == this.sitesProvider.getCurrentSiteId()) {
|
||||
// Current site.
|
||||
action.action(action.sites[0]);
|
||||
action.action(action.sites[0], navCtrl);
|
||||
} else {
|
||||
// Not current site or more than one site. Ask for confirmation.
|
||||
this.domUtils.showConfirm(this.translate.instant('core.contentlinks.confirmurlothersite')).then(() => {
|
||||
if (action.sites.length == 1) {
|
||||
action.action(action.sites[0]);
|
||||
action.action(action.sites[0], navCtrl);
|
||||
} else {
|
||||
this.goToChooseSite(url);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,8 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
@Input() course: any; // The course to render.
|
||||
@Input() sections: any[]; // List of course sections.
|
||||
@Input() downloadEnabled?: boolean; // Whether the download of sections and modules is enabled.
|
||||
@Input() initialSectionId: number; // The section to load first.
|
||||
@Input() initialSectionId?: number; // The section to load first (by ID).
|
||||
@Input() initialSectionNumber?: number; // The section to load first (by number).
|
||||
@Output() completionChanged?: EventEmitter<void>; // Will emit an event when any module completion changes.
|
||||
|
||||
// Get the containers where to inject dynamic components. We use a setter because they might be inside a *ngIf.
|
||||
|
@ -144,11 +145,11 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
if (changes.sections && this.sections) {
|
||||
if (!this.selectedSection) {
|
||||
// There is no selected section yet, calculate which one to load.
|
||||
if (this.initialSectionId) {
|
||||
if (this.initialSectionId || this.initialSectionNumber) {
|
||||
// We have an input indicating the section ID to load. Search the section.
|
||||
for (let i = 0; i < this.sections.length; i++) {
|
||||
let section = this.sections[i];
|
||||
if (section.id == this.initialSectionId) {
|
||||
if (section.id == this.initialSectionId || section.section == this.initialSectionNumber) {
|
||||
this.loaded = true;
|
||||
this.sectionChanged(section);
|
||||
break;
|
||||
|
@ -229,6 +230,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
this.componentInstances[type].course = this.course;
|
||||
this.componentInstances[type].sections = this.sections;
|
||||
this.componentInstances[type].initialSectionId = this.initialSectionId;
|
||||
this.componentInstances[type].initialSectionNumber = this.initialSectionNumber;
|
||||
this.componentInstances[type].downloadEnabled = this.downloadEnabled;
|
||||
|
||||
this.cdr.detectChanges(); // The instances are used in ngIf, tell Angular that something has changed.
|
||||
|
|
|
@ -21,6 +21,6 @@
|
|||
<a aria-selected="true">{{ 'core.course.contents' | translate }}</a>
|
||||
<a *ngFor="let handler of courseHandlers">{{ handler.data.title || translate }}</a>
|
||||
</div>
|
||||
<core-course-format [course]="course" [sections]="sections" [initialSectionId]="sectionId" [downloadEnabled]="downloadEnabled" (completionChanged)="onCompletionChange()"></core-course-format>
|
||||
<core-course-format [course]="course" [sections]="sections" [initialSectionId]="sectionId" [initialSectionNumber]="sectionNumber" [downloadEnabled]="downloadEnabled" (completionChanged)="onCompletionChange()"></core-course-format>
|
||||
</core-loading>
|
||||
</ion-content>
|
||||
|
|
|
@ -40,6 +40,7 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
course: any;
|
||||
sections: any[];
|
||||
sectionId: number;
|
||||
sectionNumber: number;
|
||||
courseHandlers: CoreCoursesHandlerToDisplay[];
|
||||
dataLoaded: boolean;
|
||||
downloadEnabled: boolean;
|
||||
|
@ -59,6 +60,7 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
sitesProvider: CoreSitesProvider, private navCtrl: NavController) {
|
||||
this.course = navParams.get('course');
|
||||
this.sectionId = navParams.get('sectionId');
|
||||
this.sectionNumber = navParams.get('sectionNumber');
|
||||
|
||||
// Get the title to display. We dont't have sections yet.
|
||||
this.title = courseFormatDelegate.getCourseTitle(this.course);
|
||||
|
|
|
@ -13,11 +13,13 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, Input, Output, OnChanges, EventEmitter, SimpleChange } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreSitesProvider } from '../../../../providers/sites';
|
||||
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
|
||||
import { CoreTextUtilsProvider } from '../../../../providers/utils/text';
|
||||
import { CoreUtilsProvider } from '../../../../providers/utils/utils';
|
||||
import { CoreCourseProvider } from '../../../course/providers/course';
|
||||
import { CoreContentLinksHelperProvider } from '../../../contentlinks/providers/helper';
|
||||
import * as moment from 'moment';
|
||||
|
||||
/**
|
||||
|
@ -41,9 +43,9 @@ export class CoreCoursesOverviewEventsComponent implements OnChanges {
|
|||
next30Days: any[] = [];
|
||||
future: any[] = [];
|
||||
|
||||
constructor(private utils: CoreUtilsProvider, private textUtils: CoreTextUtilsProvider,
|
||||
constructor(private navCtrl: NavController, private utils: CoreUtilsProvider, private textUtils: CoreTextUtilsProvider,
|
||||
private domUtils: CoreDomUtilsProvider, private sitesProvider: CoreSitesProvider,
|
||||
private courseProvider: CoreCourseProvider) {
|
||||
private courseProvider: CoreCourseProvider, private contentLinksHelper: CoreContentLinksHelperProvider) {
|
||||
this.loadMore = new EventEmitter();
|
||||
}
|
||||
|
||||
|
@ -100,9 +102,6 @@ export class CoreCoursesOverviewEventsComponent implements OnChanges {
|
|||
loadMoreEvents() {
|
||||
this.loadingMore = true;
|
||||
this.loadMore.emit();
|
||||
// this.loadMore().finally(function() {
|
||||
// scope.loadingMore = false;
|
||||
// });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,19 +118,14 @@ export class CoreCoursesOverviewEventsComponent implements OnChanges {
|
|||
url = this.textUtils.decodeHTMLEntities(url);
|
||||
|
||||
let modal = this.domUtils.showModalLoading();
|
||||
this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(url).finally(() => {
|
||||
this.contentLinksHelper.handleLink(url, undefined, this.navCtrl).then((treated) => {
|
||||
if (!treated) {
|
||||
return this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(url);
|
||||
}
|
||||
}).finally(() => {
|
||||
modal.dismiss();
|
||||
});
|
||||
|
||||
// @todo
|
||||
// $mmContentLinksHelper.handleLink(url).then((treated) => {
|
||||
// if (!treated) {
|
||||
// return this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(url);
|
||||
// }
|
||||
// }).finally(() => {
|
||||
// modal.dismiss();
|
||||
// });
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,11 @@ import { CoreCoursesProvider } from './providers/courses';
|
|||
import { CoreCoursesMainMenuHandler } from './providers/mainmenu-handler';
|
||||
import { CoreCoursesMyOverviewProvider } from './providers/my-overview';
|
||||
import { CoreCoursesDelegate } from './providers/delegate';
|
||||
import { CoreCoursesCourseLinkHandler } from './providers/course-link-handler';
|
||||
import { CoreCoursesIndexLinkHandler } from './providers/courses-index-link-handler';
|
||||
import { CoreCoursesMyOverviewLinkHandler } from './providers/my-overview-link-handler';
|
||||
import { CoreMainMenuDelegate } from '../mainmenu/providers/delegate';
|
||||
import { CoreContentLinksDelegate } from '../contentlinks/providers/delegate';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
|
@ -27,12 +31,21 @@ import { CoreMainMenuDelegate } from '../mainmenu/providers/delegate';
|
|||
CoreCoursesProvider,
|
||||
CoreCoursesMainMenuHandler,
|
||||
CoreCoursesMyOverviewProvider,
|
||||
CoreCoursesDelegate
|
||||
CoreCoursesDelegate,
|
||||
CoreCoursesCourseLinkHandler,
|
||||
CoreCoursesIndexLinkHandler,
|
||||
CoreCoursesMyOverviewLinkHandler
|
||||
],
|
||||
exports: []
|
||||
})
|
||||
export class CoreCoursesModule {
|
||||
constructor(mainMenuDelegate: CoreMainMenuDelegate, mainMenuHandler: CoreCoursesMainMenuHandler) {
|
||||
constructor(mainMenuDelegate: CoreMainMenuDelegate, contentLinksDelegate: CoreContentLinksDelegate,
|
||||
mainMenuHandler: CoreCoursesMainMenuHandler, courseLinkHandler: CoreCoursesCourseLinkHandler,
|
||||
indexLinkHandler: CoreCoursesIndexLinkHandler, myOverviewLinkHandler: CoreCoursesMyOverviewLinkHandler) {
|
||||
mainMenuDelegate.registerHandler(mainMenuHandler);
|
||||
|
||||
contentLinksDelegate.registerHandler(courseLinkHandler);
|
||||
contentLinksDelegate.registerHandler(indexLinkHandler);
|
||||
contentLinksDelegate.registerHandler(myOverviewLinkHandler);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,267 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreSitesProvider } from '../../../providers/sites';
|
||||
import { CoreDomUtilsProvider } from '../../../providers/utils/dom';
|
||||
import { CoreContentLinksHandlerBase } from '../../contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '../../contentlinks/providers/delegate';
|
||||
import { CoreLoginHelperProvider } from '../../login/providers/helper';
|
||||
import { CoreCourseProvider } from '../../course/providers/course';
|
||||
import { CoreCoursesProvider } from './courses';
|
||||
|
||||
/**
|
||||
* Handler to treat links to course view or enrol (except site home).
|
||||
*/
|
||||
@Injectable()
|
||||
export class CoreCoursesCourseLinkHandler extends CoreContentLinksHandlerBase {
|
||||
name = 'CoreCoursesCourseLinkHandler';
|
||||
pattern = /((\/enrol\/index\.php)|(\/course\/enrol\.php)|(\/course\/view\.php)).*([\?\&]id=\d+)/;
|
||||
|
||||
protected waitStart = 0;
|
||||
|
||||
constructor(private sitesProvider: CoreSitesProvider, private coursesProvider: CoreCoursesProvider,
|
||||
private loginHelper: CoreLoginHelperProvider, private domUtils: CoreDomUtilsProvider,
|
||||
private translate: TranslateService, private courseProvider: CoreCourseProvider) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of actions for a link (url).
|
||||
*
|
||||
* @param {string[]} siteIds List of sites the URL belongs to.
|
||||
* @param {string} url The URL to treat.
|
||||
* @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.
|
||||
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
|
||||
*/
|
||||
getActions(siteIds: string[], url: string, params: any, courseId?: number) :
|
||||
CoreContentLinksAction[]|Promise<CoreContentLinksAction[]> {
|
||||
courseId = parseInt(params.id, 10);
|
||||
|
||||
let sectionId = params.sectionid ? parseInt(params.sectionid, 10) : null,
|
||||
sectionNumber = typeof params.section != 'undefined' ? parseInt(params.section, 10) : NaN,
|
||||
pageParams: any = {
|
||||
course: {id: courseId},
|
||||
sectionId: sectionId || null
|
||||
};
|
||||
|
||||
if (!isNaN(sectionNumber)) {
|
||||
pageParams.sectionNumber = sectionNumber;
|
||||
}
|
||||
|
||||
return [{
|
||||
action: (siteId, navCtrl?) => {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
if (siteId == this.sitesProvider.getCurrentSiteId()) {
|
||||
this.actionEnrol(courseId, url, pageParams).catch(() => {
|
||||
// Ignore errors.
|
||||
});
|
||||
} else {
|
||||
// Use redirect to make the course the new history root (to avoid "loops" in history).
|
||||
this.loginHelper.redirect('CoreCourseSectionPage', pageParams, siteId);
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the handler is enabled for a certain site (site + user) and a URL.
|
||||
* If not defined, defaults to true.
|
||||
*
|
||||
* @param {string} siteId The site ID.
|
||||
* @param {string} url The URL to treat.
|
||||
* @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.
|
||||
* @return {boolean|Promise<boolean>} Whether the handler is enabled for the URL and site.
|
||||
*/
|
||||
isEnabled(siteId: string, url: string, params: any, courseId?: number) : boolean|Promise<boolean> {
|
||||
courseId = parseInt(params.id, 10);
|
||||
|
||||
if (!courseId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the course id of Site Home.
|
||||
return this.sitesProvider.getSiteHomeId(siteId).then((siteHomeId) => {
|
||||
return courseId != siteHomeId;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to perform when an enrol link is clicked.
|
||||
*
|
||||
* @param {number} courseId Course ID.
|
||||
* @param {string} url Treated URL.
|
||||
* @param {any} pageParams Params to send to the new page.
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
protected actionEnrol(courseId: number, url: string, pageParams: any) : Promise<any> {
|
||||
let modal = this.domUtils.showModalLoading(),
|
||||
isEnrolUrl = !!url.match(/(\/enrol\/index\.php)|(\/course\/enrol\.php)/);
|
||||
|
||||
// Check if user is enrolled in the course.
|
||||
return this.coursesProvider.getUserCourse(courseId).catch(() => {
|
||||
// User is not enrolled in the course. Check if can self enrol.
|
||||
return this.canSelfEnrol(courseId).then(() => {
|
||||
modal.dismiss();
|
||||
|
||||
// The user can self enrol. If it's not a enrolment URL we'll ask for confirmation.
|
||||
let promise = isEnrolUrl ? Promise.resolve() :
|
||||
this.domUtils.showConfirm(this.translate.instant('core.courses.confirmselfenrol'));
|
||||
|
||||
return promise.then(() => {
|
||||
// Enrol URL or user confirmed.
|
||||
return this.selfEnrol(courseId).catch((error) => {
|
||||
if (error) {
|
||||
this.domUtils.showErrorModal(error);
|
||||
}
|
||||
return Promise.reject(null);
|
||||
});
|
||||
}, () => {
|
||||
// User cancelled. Check if the user can view the course contents (guest access or similar).
|
||||
return this.courseProvider.getSections(courseId, false, true);
|
||||
});
|
||||
}, (error) => {
|
||||
// Can't self enrol. Check if the user can view the course contents (guest access or similar).
|
||||
return this.courseProvider.getSections(courseId, false, true).catch(() => {
|
||||
// Error. Show error message and allow the user to open the link in browser.
|
||||
modal.dismiss();
|
||||
|
||||
if (error) {
|
||||
error = error.message || error.error || error.content || error.body || error;
|
||||
}
|
||||
if (!error) {
|
||||
error = this.translate.instant('core.courses.notenroled');
|
||||
}
|
||||
|
||||
let body = this.translate.instant('core.twoparagraphs',
|
||||
{p1: error, p2: this.translate.instant('core.confirmopeninbrowser')});
|
||||
this.domUtils.showConfirm(body).then(() => {
|
||||
this.sitesProvider.getCurrentSite().openInBrowserWithAutoLogin(url);
|
||||
}).catch(() => {
|
||||
// User cancelled.
|
||||
});
|
||||
return Promise.reject(null);
|
||||
});
|
||||
});
|
||||
}).then(() => {
|
||||
modal.dismiss();
|
||||
|
||||
// Use redirect to make the course the new history root (to avoid "loops" in history).
|
||||
this.loginHelper.redirect('CoreCourseSectionPage', pageParams, this.sitesProvider.getCurrentSiteId());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user can be "automatically" self enrolled in a course.
|
||||
*
|
||||
* @param {number} courseId Course ID.
|
||||
* @return {Promise<any>} Promise resolved if user can be enrolled in a course, rejected otherwise.
|
||||
*/
|
||||
protected canSelfEnrol(courseId: number) : Promise<any> {
|
||||
// Check that the course has self enrolment enabled.
|
||||
return this.coursesProvider.getCourseEnrolmentMethods(courseId).then((methods) => {
|
||||
let isSelfEnrolEnabled = false,
|
||||
instances = 0;
|
||||
|
||||
methods.forEach((method) => {
|
||||
if (method.type == 'self' && method.status) {
|
||||
isSelfEnrolEnabled = true;
|
||||
instances++;
|
||||
}
|
||||
});
|
||||
|
||||
if (!isSelfEnrolEnabled || instances != 1) {
|
||||
// Self enrol not enabled or more than one instance.
|
||||
return Promise.reject(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to self enrol a user in a course.
|
||||
*
|
||||
* @param {number} courseId Course ID.
|
||||
* @param {string} [password] Password.
|
||||
* @return {Promise<any>} Promise resolved when the user is enrolled, rejected otherwise.
|
||||
*/
|
||||
protected selfEnrol(courseId: number, password?: string) : Promise<any> {
|
||||
const modal = this.domUtils.showModalLoading();
|
||||
return this.coursesProvider.selfEnrol(courseId, password).then(() => {
|
||||
// Success self enrolling the user, invalidate the courses list.
|
||||
return this.coursesProvider.invalidateUserCourses().catch(() => {
|
||||
// Ignore errors.
|
||||
}).then(() => {
|
||||
// Sometimes the list of enrolled courses takes a while to be updated. Wait for it.
|
||||
return this.waitForEnrolled(courseId, true).finally(() => {
|
||||
modal.dismiss();
|
||||
});
|
||||
});
|
||||
|
||||
}).catch((error) => {
|
||||
modal.dismiss();
|
||||
if (error && error.code === CoreCoursesProvider.ENROL_INVALID_KEY) {
|
||||
// Invalid password. Allow the user to input password.
|
||||
let title = this.translate.instant('core.courses.selfenrolment'),
|
||||
body = ' ', // Empty message.
|
||||
placeholder = this.translate.instant('core.courses.password');
|
||||
|
||||
if (typeof password != 'undefined') {
|
||||
// The user attempted a password. Show an error message.
|
||||
this.domUtils.showErrorModal(error.message);
|
||||
}
|
||||
|
||||
return this.domUtils.showPrompt(body, title, placeholder).then((password) => {
|
||||
return this.selfEnrol(courseId, password);
|
||||
});
|
||||
} else {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the user to be enrolled in a course.
|
||||
*
|
||||
* @param {number} courseId The course ID.
|
||||
* @param {boolean} first If it's the first call (true) or it's a recursive call (false).
|
||||
* @return {Promise<any>} Promise resolved when enrolled or timeout.
|
||||
*/
|
||||
protected waitForEnrolled(courseId: number, first?: boolean) : Promise<any> {
|
||||
if (first) {
|
||||
this.waitStart = Date.now();
|
||||
}
|
||||
|
||||
// Check if user is enrolled in the course.
|
||||
return this.coursesProvider.invalidateUserCourses().catch(() => {
|
||||
// Ignore errors.
|
||||
}).then(() => {
|
||||
return this.coursesProvider.getUserCourse(courseId);
|
||||
}).catch(() => {
|
||||
// Not enrolled, wait a bit and try again.
|
||||
if (Date.now() - this.waitStart > 60000) {
|
||||
// Max time reached, stop.
|
||||
return;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
this.waitForEnrolled(courseId).then(resolve);
|
||||
}, 5000);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreContentLinksHandlerBase } from '../../contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '../../contentlinks/providers/delegate';
|
||||
import { CoreLoginHelperProvider } from '../../login/providers/helper';
|
||||
import { CoreCoursesProvider } from './courses';
|
||||
|
||||
/**
|
||||
* Handler to treat links to course index (list of courses).
|
||||
*/
|
||||
@Injectable()
|
||||
export class CoreCoursesIndexLinkHandler extends CoreContentLinksHandlerBase {
|
||||
name = 'CoreCoursesIndexLinkHandler';
|
||||
featureName = '$mmSideMenuDelegate_mmCourses';
|
||||
pattern = /\/course\/?(index\.php.*)?$/;
|
||||
|
||||
constructor(private coursesProvider: CoreCoursesProvider, private loginHelper: CoreLoginHelperProvider) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of actions for a link (url).
|
||||
*
|
||||
* @param {string[]} siteIds List of sites the URL belongs to.
|
||||
* @param {string} url The URL to treat.
|
||||
* @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.
|
||||
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
|
||||
*/
|
||||
getActions(siteIds: string[], url: string, params: any, courseId?: number) :
|
||||
CoreContentLinksAction[]|Promise<CoreContentLinksAction[]> {
|
||||
return [{
|
||||
action: (siteId, navCtrl?) => {
|
||||
var page = 'CoreCoursesMyCoursesPage', // By default, go to My Courses.
|
||||
pageParams: any = {};
|
||||
|
||||
if (this.coursesProvider.isGetCoursesByFieldAvailable()) {
|
||||
if (params.categoryid) {
|
||||
page = 'CoreCoursesCategoriesPage';
|
||||
pageParams.categoryId = parseInt(params.categoryid, 10);
|
||||
} else {
|
||||
page = 'CoreCoursesAvailableCoursesPage';
|
||||
}
|
||||
}
|
||||
|
||||
// Always use redirect to make it the new history root (to avoid "loops" in history).
|
||||
this.loginHelper.redirect(page, pageParams, siteId);
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreContentLinksHandlerBase } from '../../contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '../../contentlinks/providers/delegate';
|
||||
import { CoreLoginHelperProvider } from '../../login/providers/helper';
|
||||
import { CoreCoursesProvider } from './courses';
|
||||
|
||||
/**
|
||||
* Handler to treat links to my overview.
|
||||
*/
|
||||
@Injectable()
|
||||
export class CoreCoursesMyOverviewLinkHandler extends CoreContentLinksHandlerBase {
|
||||
name = 'CoreCoursesMyOverviewLinkHandler';
|
||||
featureName = '$mmSideMenuDelegate_mmCourses';
|
||||
pattern = /\/my\/?$/;
|
||||
|
||||
constructor(private coursesProvider: CoreCoursesProvider, private loginHelper: CoreLoginHelperProvider) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of actions for a link (url).
|
||||
*
|
||||
* @param {string[]} siteIds List of sites the URL belongs to.
|
||||
* @param {string} url The URL to treat.
|
||||
* @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.
|
||||
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
|
||||
*/
|
||||
getActions(siteIds: string[], url: string, params: any, courseId?: number) :
|
||||
CoreContentLinksAction[]|Promise<CoreContentLinksAction[]> {
|
||||
return [{
|
||||
action: (siteId, navCtrl?) => {
|
||||
// Always use redirect to make it the new history root (to avoid "loops" in history).
|
||||
this.loginHelper.redirect('CoreCoursesMyOverviewPage', undefined, siteId);
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
|
@ -21,6 +21,8 @@ import { CoreSitesProvider } from '../../../../providers/sites';
|
|||
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
|
||||
import { CoreUtilsProvider } from '../../../../providers/utils/utils';
|
||||
import { CoreLoginHelperProvider } from '../../providers/helper';
|
||||
import { CoreContentLinksDelegate } from '../../../contentlinks/providers/delegate';
|
||||
import { CoreContentLinksHelperProvider } from '../../../contentlinks/providers/helper';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
/**
|
||||
|
@ -52,7 +54,8 @@ export class CoreLoginCredentialsPage {
|
|||
constructor(private navCtrl: NavController, navParams: NavParams, fb: FormBuilder, private appProvider: CoreAppProvider,
|
||||
private sitesProvider: CoreSitesProvider, private loginHelper: CoreLoginHelperProvider,
|
||||
private domUtils: CoreDomUtilsProvider, private translate: TranslateService, private utils: CoreUtilsProvider,
|
||||
private eventsProvider: CoreEventsProvider) {
|
||||
private eventsProvider: CoreEventsProvider, private contentLinksDelegate: CoreContentLinksDelegate,
|
||||
private contentLinksHelper: CoreContentLinksHelperProvider) {
|
||||
|
||||
this.siteUrl = navParams.get('siteUrl');
|
||||
this.siteConfig = navParams.get('siteConfig');
|
||||
|
@ -203,16 +206,15 @@ export class CoreLoginCredentialsPage {
|
|||
|
||||
if (this.urlToOpen) {
|
||||
// There's a content link to open.
|
||||
// @todo: Implement this once content links delegate is implemented.
|
||||
// return $mmContentLinksDelegate.getActionsFor(urlToOpen, undefined, username).then((actions) => {
|
||||
// action = $mmContentLinksHelper.getFirstValidAction(actions);
|
||||
// if (action && action.sites.length) {
|
||||
// // Action should only have 1 site because we're filtering by username.
|
||||
// action.action(action.sites[0]);
|
||||
// } else {
|
||||
// return $mmLoginHelper.goToSiteInitialPage();
|
||||
// }
|
||||
// });
|
||||
return this.contentLinksDelegate.getActionsFor(this.urlToOpen, undefined, username).then((actions) => {
|
||||
const action = this.contentLinksHelper.getFirstValidAction(actions);
|
||||
if (action && action.sites.length) {
|
||||
// Action should only have 1 site because we're filtering by username.
|
||||
action.action(action.sites[0]);
|
||||
} else {
|
||||
return this.loginHelper.goToSiteInitialPage();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return this.loginHelper.goToSiteInitialPage();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreSitesProvider } from '../../../providers/sites';
|
||||
import { CoreContentLinksHandlerBase } from '../../contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '../../contentlinks/providers/delegate';
|
||||
import { CoreLoginHelperProvider } from '../../login/providers/helper';
|
||||
import { CoreSiteHomeProvider } from './sitehome';
|
||||
|
||||
/**
|
||||
* Handler to treat links to site home index.
|
||||
*/
|
||||
@Injectable()
|
||||
export class CoreSiteHomeIndexLinkHandler extends CoreContentLinksHandlerBase {
|
||||
name = 'CoreSiteHomeIndexLinkHandler';
|
||||
featureName = '$mmSideMenuDelegate_mmaFrontpage';
|
||||
pattern = /\/course\/view\.php.*([\?\&]id=\d+)/;
|
||||
|
||||
constructor(private sitesProvider: CoreSitesProvider, private siteHomeProvider: CoreSiteHomeProvider,
|
||||
private loginHelper: CoreLoginHelperProvider) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of actions for a link (url).
|
||||
*
|
||||
* @param {string[]} siteIds List of sites the URL belongs to.
|
||||
* @param {string} url The URL to treat.
|
||||
* @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.
|
||||
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
|
||||
*/
|
||||
getActions(siteIds: string[], url: string, params: any, courseId?: number) :
|
||||
CoreContentLinksAction[]|Promise<CoreContentLinksAction[]> {
|
||||
return [{
|
||||
action: (siteId, navCtrl?) => {
|
||||
// Always use redirect to make it the new history root (to avoid "loops" in history).
|
||||
this.loginHelper.redirect('CoreSiteHomeIndexPage', undefined, siteId);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the handler is enabled for a certain site (site + user) and a URL.
|
||||
* If not defined, defaults to true.
|
||||
*
|
||||
* @param {string} siteId The site ID.
|
||||
* @param {string} url The URL to treat.
|
||||
* @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.
|
||||
* @return {boolean|Promise<boolean>} Whether the handler is enabled for the URL and site.
|
||||
*/
|
||||
isEnabled(siteId: string, url: string, params: any, courseId?: number) : boolean|Promise<boolean> {
|
||||
courseId = parseInt(params.id, 10);
|
||||
if (!courseId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
if (courseId != site.getSiteHomeId()) {
|
||||
// The course is not site home.
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.siteHomeProvider.isAvailable(siteId).then(() => {
|
||||
return true;
|
||||
}).catch(() => {
|
||||
return false;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -15,7 +15,9 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CoreSiteHomeProvider } from './providers/sitehome';
|
||||
import { CoreSiteHomeMainMenuHandler } from './providers/mainmenu-handler';
|
||||
import { CoreSiteHomeIndexLinkHandler } from './providers/index-link-handler';
|
||||
import { CoreMainMenuDelegate } from '../mainmenu/providers/delegate';
|
||||
import { CoreContentLinksDelegate } from '../contentlinks/providers/delegate';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
|
@ -23,12 +25,15 @@ import { CoreMainMenuDelegate } from '../mainmenu/providers/delegate';
|
|||
],
|
||||
providers: [
|
||||
CoreSiteHomeProvider,
|
||||
CoreSiteHomeMainMenuHandler
|
||||
CoreSiteHomeMainMenuHandler,
|
||||
CoreSiteHomeIndexLinkHandler
|
||||
],
|
||||
exports: []
|
||||
})
|
||||
export class CoreSiteHomeModule {
|
||||
constructor(mainMenuDelegate: CoreMainMenuDelegate, mainMenuHandler: CoreSiteHomeMainMenuHandler) {
|
||||
constructor(mainMenuDelegate: CoreMainMenuDelegate, contentLinksDelegate: CoreContentLinksDelegate,
|
||||
mainMenuHandler: CoreSiteHomeMainMenuHandler, indexLinkHandler: CoreSiteHomeIndexLinkHandler) {
|
||||
mainMenuDelegate.registerHandler(mainMenuHandler);
|
||||
contentLinksDelegate.registerHandler(indexLinkHandler);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Directive, ElementRef, Input, Output, EventEmitter, OnChanges, SimpleChange } from '@angular/core';
|
||||
import { Platform } from 'ionic-angular';
|
||||
import { Platform, NavController } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreAppProvider } from '../providers/app';
|
||||
import { CoreFilepoolProvider } from '../providers/filepool';
|
||||
|
@ -26,6 +26,7 @@ import { CoreUtilsProvider } from '../providers/utils/utils';
|
|||
import { CoreSite } from '../classes/site';
|
||||
import { CoreLinkDirective } from '../directives/link';
|
||||
import { CoreExternalContentDirective } from '../directives/external-content';
|
||||
import { CoreContentLinksHelperProvider } from '../core/contentlinks/providers/helper';
|
||||
|
||||
/**
|
||||
* Directive to format text rendered. It renders the HTML and treats all links and media, using CoreLinkDirective
|
||||
|
@ -60,7 +61,8 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
constructor(element: ElementRef, private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider,
|
||||
private textUtils: CoreTextUtilsProvider, private translate: TranslateService, private platform: Platform,
|
||||
private utils: CoreUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private loggerProvider: CoreLoggerProvider,
|
||||
private filepoolProvider: CoreFilepoolProvider, private appProvider: CoreAppProvider) {
|
||||
private filepoolProvider: CoreFilepoolProvider, private appProvider: CoreAppProvider,
|
||||
private contentLinksHelper: CoreContentLinksHelperProvider, private navCtrl: NavController) {
|
||||
this.element = element.nativeElement;
|
||||
this.element.classList.add('opacity-hide'); // Hide contents until they're treated.
|
||||
this.afterRender = new EventEmitter();
|
||||
|
@ -274,7 +276,8 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
// Important: We need to look for links first because in 'img' we add new links without core-link.
|
||||
anchors.forEach((anchor) => {
|
||||
// Angular 2 doesn't let adding directives dynamically. Create the CoreLinkDirective manually.
|
||||
let linkDir = new CoreLinkDirective(anchor, this.domUtils, this.utils, this.sitesProvider, this.urlUtils);
|
||||
let linkDir = new CoreLinkDirective(anchor, this.domUtils, this.utils, this.sitesProvider, this.urlUtils,
|
||||
this.contentLinksHelper, this.navCtrl);
|
||||
linkDir.capture = true;
|
||||
linkDir.ngOnInit();
|
||||
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreSitesProvider } from '../providers/sites';
|
||||
import { CoreDomUtilsProvider } from '../providers/utils/dom';
|
||||
import { CoreUrlUtilsProvider } from '../providers/utils/url';
|
||||
import { CoreUtilsProvider } from '../providers/utils/utils';
|
||||
import { CoreContentLinksHelperProvider } from '../core/contentlinks/providers/helper';
|
||||
import { CoreConfigConstants } from '../configconstants';
|
||||
|
||||
/**
|
||||
|
@ -36,7 +38,8 @@ export class CoreLinkDirective implements OnInit {
|
|||
protected element: HTMLElement;
|
||||
|
||||
constructor(element: ElementRef, private domUtils: CoreDomUtilsProvider, private utils: CoreUtilsProvider,
|
||||
private sitesProvider: CoreSitesProvider, private urlUtils: CoreUrlUtilsProvider) {
|
||||
private sitesProvider: CoreSitesProvider, private urlUtils: CoreUrlUtilsProvider,
|
||||
private contentLinksHelper: CoreContentLinksHelperProvider, private navCtrl: NavController) {
|
||||
// This directive can be added dynamically. In that case, the first param is the anchor HTMLElement.
|
||||
this.element = element.nativeElement || element;
|
||||
}
|
||||
|
@ -56,12 +59,11 @@ export class CoreLinkDirective implements OnInit {
|
|||
event.stopPropagation();
|
||||
|
||||
if (this.utils.isTrueOrOne(this.capture)) {
|
||||
// @todo: Handle link using content links helper.
|
||||
// $mmContentLinksHelper.handleLink(href).then((treated) => {
|
||||
// if (!treated) {
|
||||
this.contentLinksHelper.handleLink(href, undefined, this.navCtrl).then((treated) => {
|
||||
if (!treated) {
|
||||
this.navigate(href);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.navigate(href);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue