commit
428e753ca6
File diff suppressed because it is too large
Load Diff
|
@ -101,7 +101,7 @@
|
||||||
"cordova-plugin-file-transfer": "1.7.1",
|
"cordova-plugin-file-transfer": "1.7.1",
|
||||||
"cordova-plugin-geolocation": "git+https://github.com/apache/cordova-plugin-geolocation.git#89cf51d222e8f225bdfb661965b3007d669c40ff",
|
"cordova-plugin-geolocation": "git+https://github.com/apache/cordova-plugin-geolocation.git#89cf51d222e8f225bdfb661965b3007d669c40ff",
|
||||||
"cordova-plugin-globalization": "1.11.0",
|
"cordova-plugin-globalization": "1.11.0",
|
||||||
"cordova-plugin-inappbrowser": "3.2.0",
|
"cordova-plugin-inappbrowser": "git+https://github.com/apache/cordova-plugin-inappbrowser.git#d2b512ed048ce9345e61901b29ba7dd4271a73bf",
|
||||||
"cordova-plugin-ionic-keyboard": "2.1.3",
|
"cordova-plugin-ionic-keyboard": "2.1.3",
|
||||||
"cordova-plugin-ionic-webview": "4.1.3",
|
"cordova-plugin-ionic-webview": "4.1.3",
|
||||||
"cordova-plugin-local-notification": "git+https://github.com/moodlemobile/cordova-plugin-local-notification.git#moodle",
|
"cordova-plugin-local-notification": "git+https://github.com/moodlemobile/cordova-plugin-local-notification.git#moodle",
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { Component, Optional, Injector } from '@angular/core';
|
||||||
import { Content } from 'ionic-angular';
|
import { Content } from 'ionic-angular';
|
||||||
import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component';
|
import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component';
|
||||||
import { AddonModLtiProvider, AddonModLtiLti } from '../../providers/lti';
|
import { AddonModLtiProvider, AddonModLtiLti } from '../../providers/lti';
|
||||||
|
import { AddonModLtiHelper } from '../../providers/helper';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays an LTI entry page.
|
* Component that displays an LTI entry page.
|
||||||
|
@ -92,18 +93,6 @@ export class AddonModLtiIndexComponent extends CoreCourseModuleMainActivityCompo
|
||||||
* Launch the LTI.
|
* Launch the LTI.
|
||||||
*/
|
*/
|
||||||
launch(): void {
|
launch(): void {
|
||||||
this.ltiProvider.getLtiLaunchData(this.lti.id).then((launchData) => {
|
AddonModLtiHelper.instance.getDataAndLaunch(this.courseId, this.module, this.lti);
|
||||||
// "View" LTI.
|
|
||||||
this.ltiProvider.logView(this.lti.id, this.lti.name).then(() => {
|
|
||||||
this.checkCompletion();
|
|
||||||
}).catch((error) => {
|
|
||||||
// Ignore errors.
|
|
||||||
});
|
|
||||||
|
|
||||||
// Launch LTI.
|
|
||||||
return this.ltiProvider.launch(launchData.endpoint, launchData.parameters);
|
|
||||||
}).catch((message) => {
|
|
||||||
this.domUtils.showErrorModalDefault(message, 'core.error', true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { NgModule } from '@angular/core';
|
||||||
import { AddonModLtiComponentsModule } from './components/components.module';
|
import { AddonModLtiComponentsModule } from './components/components.module';
|
||||||
import { AddonModLtiModuleHandler } from './providers/module-handler';
|
import { AddonModLtiModuleHandler } from './providers/module-handler';
|
||||||
import { AddonModLtiProvider } from './providers/lti';
|
import { AddonModLtiProvider } from './providers/lti';
|
||||||
|
import { AddonModLtiHelperProvider } from './providers/helper';
|
||||||
import { AddonModLtiLinkHandler } from './providers/link-handler';
|
import { AddonModLtiLinkHandler } from './providers/link-handler';
|
||||||
import { AddonModLtiListLinkHandler } from './providers/list-link-handler';
|
import { AddonModLtiListLinkHandler } from './providers/list-link-handler';
|
||||||
import { AddonModLtiPrefetchHandler } from './providers/prefetch-handler';
|
import { AddonModLtiPrefetchHandler } from './providers/prefetch-handler';
|
||||||
|
@ -25,7 +26,8 @@ import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-
|
||||||
|
|
||||||
// List of providers (without handlers).
|
// List of providers (without handlers).
|
||||||
export const ADDON_MOD_LTI_PROVIDERS: any[] = [
|
export const ADDON_MOD_LTI_PROVIDERS: any[] = [
|
||||||
AddonModLtiProvider
|
AddonModLtiProvider,
|
||||||
|
AddonModLtiHelperProvider,
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -36,10 +38,11 @@ export const ADDON_MOD_LTI_PROVIDERS: any[] = [
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
AddonModLtiProvider,
|
AddonModLtiProvider,
|
||||||
|
AddonModLtiHelperProvider,
|
||||||
AddonModLtiModuleHandler,
|
AddonModLtiModuleHandler,
|
||||||
AddonModLtiLinkHandler,
|
AddonModLtiLinkHandler,
|
||||||
AddonModLtiListLinkHandler,
|
AddonModLtiListLinkHandler,
|
||||||
AddonModLtiPrefetchHandler
|
AddonModLtiPrefetchHandler,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AddonModLtiModule {
|
export class AddonModLtiModule {
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
// (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 { Platform } from 'ionic-angular';
|
||||||
|
import { CoreEvents, CoreEventsProvider } from '@providers/events';
|
||||||
|
import { CoreSites } from '@providers/sites';
|
||||||
|
import { CoreDomUtils } from '@providers/utils/dom';
|
||||||
|
import { CoreCourse } from '@core/course/providers/course';
|
||||||
|
import { AddonModLti, AddonModLtiLti } from './lti';
|
||||||
|
|
||||||
|
import { makeSingleton } from '@singletons/core.singletons';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service that provides some helper functions for LTI.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class AddonModLtiHelperProvider {
|
||||||
|
|
||||||
|
protected pendingCheckCompletion: {[moduleId: string]: {courseId: number, module: any}} = {};
|
||||||
|
|
||||||
|
constructor(platform: Platform) {
|
||||||
|
|
||||||
|
platform.resume.subscribe(() => {
|
||||||
|
// User went back to the app, check pending completions.
|
||||||
|
for (const moduleId in this.pendingCheckCompletion) {
|
||||||
|
const data = this.pendingCheckCompletion[moduleId];
|
||||||
|
|
||||||
|
CoreCourse.instance.checkModuleCompletion(data.courseId, data.module.completiondata);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear pending completion on logout.
|
||||||
|
CoreEvents.instance.on(CoreEventsProvider.LOGOUT, () => {
|
||||||
|
this.pendingCheckCompletion = {};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get needed data and launch the LTI.
|
||||||
|
*
|
||||||
|
* @param courseId Course ID.
|
||||||
|
* @param module Module.
|
||||||
|
* @param lti LTI instance. If not provided it will be obtained.
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
async getDataAndLaunch(courseId: number, module: any, lti?: AddonModLtiLti, siteId?: string): Promise<void> {
|
||||||
|
siteId = siteId || CoreSites.instance.getCurrentSiteId();
|
||||||
|
|
||||||
|
const modal = CoreDomUtils.instance.showModalLoading();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const openInBrowser = await AddonModLti.instance.isOpenInAppBrowserDisabled(siteId);
|
||||||
|
|
||||||
|
if (openInBrowser) {
|
||||||
|
const site = await CoreSites.instance.getSite(siteId);
|
||||||
|
|
||||||
|
// The view event is triggered by the browser, mark the module as pending to check completion.
|
||||||
|
this.pendingCheckCompletion[module.id] = {
|
||||||
|
courseId,
|
||||||
|
module,
|
||||||
|
};
|
||||||
|
|
||||||
|
await site.openInBrowserWithAutoLogin(module.url);
|
||||||
|
} else {
|
||||||
|
// Open in app.
|
||||||
|
if (!lti) {
|
||||||
|
lti = await AddonModLti.instance.getLti(courseId, module.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const launchData = await AddonModLti.instance.getLtiLaunchData(lti.id);
|
||||||
|
|
||||||
|
// "View" LTI without blocking the UI.
|
||||||
|
this.logViewAndCheckCompletion(courseId, module, lti.id, lti.name, siteId);
|
||||||
|
|
||||||
|
// Launch LTI.
|
||||||
|
return AddonModLti.instance.launch(launchData.endpoint, launchData.parameters);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
CoreDomUtils.instance.showErrorModalDefault(error, 'addon.mod_lti.errorgetlti', true);
|
||||||
|
} finally {
|
||||||
|
modal.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report the LTI as being viewed and check completion.
|
||||||
|
*
|
||||||
|
* @param courseId Course ID.
|
||||||
|
* @param module Module.
|
||||||
|
* @param ltiId LTI id.
|
||||||
|
* @param name Name of the lti.
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
async logViewAndCheckCompletion(courseId: number, module: any, ltiId: number, name?: string, siteId?: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
await AddonModLti.instance.logView(ltiId, name);
|
||||||
|
|
||||||
|
CoreCourse.instance.checkModuleCompletion(courseId, module.completiondata);
|
||||||
|
} catch (error) {
|
||||||
|
// Ignore errors.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AddonModLtiHelper extends makeSingleton(AddonModLtiHelperProvider) {}
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable, NgZone } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { CoreAppProvider } from '@providers/app';
|
import { CoreAppProvider } from '@providers/app';
|
||||||
import { CoreFileProvider } from '@providers/file';
|
import { CoreFileProvider } from '@providers/file';
|
||||||
|
@ -24,6 +24,8 @@ import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
|
||||||
import { CoreSite } from '@classes/site';
|
import { CoreSite } from '@classes/site';
|
||||||
import { CoreWSExternalWarning, CoreWSExternalFile } from '@providers/ws';
|
import { CoreWSExternalWarning, CoreWSExternalFile } from '@providers/ws';
|
||||||
|
|
||||||
|
import { makeSingleton } from '@singletons/core.singletons';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service that provides some features for LTI.
|
* Service that provides some features for LTI.
|
||||||
*/
|
*/
|
||||||
|
@ -41,8 +43,7 @@ export class AddonModLtiProvider {
|
||||||
private utils: CoreUtilsProvider,
|
private utils: CoreUtilsProvider,
|
||||||
private translate: TranslateService,
|
private translate: TranslateService,
|
||||||
private appProvider: CoreAppProvider,
|
private appProvider: CoreAppProvider,
|
||||||
private logHelper: CoreCourseLogHelperProvider,
|
private logHelper: CoreCourseLogHelperProvider) {}
|
||||||
protected zone: NgZone) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete launcher.
|
* Delete launcher.
|
||||||
|
@ -65,10 +66,23 @@ export class AddonModLtiProvider {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate an empty page with the JS code.
|
// Generate a form with the params.
|
||||||
const text = '<script type="text/javascript"> \n' +
|
let text = '<form action="' + url + '" name="ltiLaunchForm" ' +
|
||||||
|
'method="post" encType="application/x-www-form-urlencoded">\n';
|
||||||
|
params.forEach((p) => {
|
||||||
|
if (p.name == 'ext_submit') {
|
||||||
|
text += ' <input type="submit"';
|
||||||
|
} else {
|
||||||
|
text += ' <input type="hidden" name="' + this.textUtils.escapeHTML(p.name) + '"';
|
||||||
|
}
|
||||||
|
text += ' value="' + this.textUtils.escapeHTML(p.value) + '"/>\n';
|
||||||
|
});
|
||||||
|
text += '</form>\n';
|
||||||
|
|
||||||
|
// Add an in-line script to automatically submit the form.
|
||||||
|
text += '<script type="text/javascript"> \n' +
|
||||||
' window.onload = function() { \n' +
|
' window.onload = function() { \n' +
|
||||||
this.getLaunchJSCode(url, params) +
|
' document.ltiLaunchForm.submit(); \n' +
|
||||||
' }; \n' +
|
' }; \n' +
|
||||||
'</script> \n';
|
'</script> \n';
|
||||||
|
|
||||||
|
@ -81,42 +95,6 @@ export class AddonModLtiProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the Javascript code to launch the LTI tool.
|
|
||||||
*
|
|
||||||
* @param url Launch URL.
|
|
||||||
* @param params Launch params.
|
|
||||||
* @return Javascript code.
|
|
||||||
*/
|
|
||||||
getLaunchJSCode(url: string, params: AddonModLtiParam[]): string {
|
|
||||||
// Create the form.
|
|
||||||
let jsCode = 'var form = document.createElement("form");\n' +
|
|
||||||
'form.method = "post";\n' +
|
|
||||||
'form.setAttribute("encType", "application/x-www-form-urlencoded");\n' +
|
|
||||||
`form.setAttribute("action", "${url}");\n`;
|
|
||||||
|
|
||||||
// Create the inputs based on the params.
|
|
||||||
params.forEach((p) => {
|
|
||||||
jsCode += 'var input = document.createElement("input");\n';
|
|
||||||
|
|
||||||
if (p.name == 'ext_submit') {
|
|
||||||
jsCode += 'input.type = "submit";\n';
|
|
||||||
} else {
|
|
||||||
jsCode += 'input.type = "hidden";\n' +
|
|
||||||
'input.name = "' + this.textUtils.escapeHTML(p.name) + '";\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
jsCode += 'input.value = "' + this.textUtils.escapeHTML(p.value) + '";\n' +
|
|
||||||
'form.appendChild(input);\n';
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add the form to the document and submit it.
|
|
||||||
jsCode += 'document.body.appendChild(form);\n' +
|
|
||||||
'form.submit();\n';
|
|
||||||
|
|
||||||
return jsCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a LTI.
|
* Get a LTI.
|
||||||
*
|
*
|
||||||
|
@ -217,6 +195,30 @@ export class AddonModLtiProvider {
|
||||||
return this.sitesProvider.getCurrentSite().invalidateWsCacheForKey(this.getLtiLaunchDataCacheKey(id));
|
return this.sitesProvider.getCurrentSite().invalidateWsCacheForKey(this.getLtiLaunchDataCacheKey(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if open in InAppBrowser is disabled.
|
||||||
|
*
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
|
* @return Promise resolved with boolean: whether it's disabled.
|
||||||
|
*/
|
||||||
|
async isOpenInAppBrowserDisabled(siteId?: string): Promise<boolean> {
|
||||||
|
const site = await this.sitesProvider.getSite(siteId);
|
||||||
|
|
||||||
|
return this.isOpenInAppBrowserDisabledInSite(site);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if open in InAppBrowser is disabled.
|
||||||
|
*
|
||||||
|
* @param site Site. If not defined, current site.
|
||||||
|
* @return Whether it's disabled.
|
||||||
|
*/
|
||||||
|
isOpenInAppBrowserDisabledInSite(site?: CoreSite): boolean {
|
||||||
|
site = site || this.sitesProvider.getCurrentSite();
|
||||||
|
|
||||||
|
return site.isFeatureDisabled('CoreCourseModuleDelegate_AddonModLti:openInAppBrowser');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch LTI.
|
* Launch LTI.
|
||||||
*
|
*
|
||||||
|
@ -229,40 +231,13 @@ export class AddonModLtiProvider {
|
||||||
throw this.translate.instant('addon.mod_lti.errorinvalidlaunchurl');
|
throw this.translate.instant('addon.mod_lti.errorinvalidlaunchurl');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate launcher and open it.
|
||||||
|
const launcherUrl = await this.generateLauncher(url, params);
|
||||||
|
|
||||||
if (this.appProvider.isMobile()) {
|
if (this.appProvider.isMobile()) {
|
||||||
// Open it in InAppBrowser. Use JS code because IAB has a bug in iOS when opening local files.
|
this.utils.openInApp(launcherUrl);
|
||||||
const jsCode = this.getLaunchJSCode(url, params);
|
|
||||||
|
|
||||||
const iabInstance = this.utils.openInApp('about:blank');
|
|
||||||
|
|
||||||
// Execute the JS code when the page is loaded.
|
|
||||||
let codeExecuted = false;
|
|
||||||
const executeCode = (): void => {
|
|
||||||
if (codeExecuted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
codeExecuted = true;
|
|
||||||
loadStopSubscription && loadStopSubscription.unsubscribe();
|
|
||||||
|
|
||||||
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
|
||||||
this.zone.run(() => {
|
|
||||||
iabInstance.executeScript({code: jsCode});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const loadStopSubscription = iabInstance.on('loadstop').subscribe((event) => {
|
|
||||||
executeCode();
|
|
||||||
});
|
|
||||||
|
|
||||||
// If loadstop hasn't triggered after 1 second, execute the code anyway.
|
|
||||||
setTimeout(() => {
|
|
||||||
executeCode();
|
|
||||||
}, 1000);
|
|
||||||
} else {
|
} else {
|
||||||
// Generate launched and open it in system browser, we found some cases where inapp caused JS issues.
|
// In desktop open in browser, we found some cases where inapp caused JS issues.
|
||||||
const launcherUrl = await this.generateLauncher(url, params);
|
|
||||||
|
|
||||||
this.utils.openInBrowser(launcherUrl);
|
this.utils.openInBrowser(launcherUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,6 +259,8 @@ export class AddonModLtiProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class AddonModLti extends makeSingleton(AddonModLtiProvider) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LTI returned by mod_lti_get_ltis_by_courses.
|
* LTI returned by mod_lti_get_ltis_by_courses.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,11 +18,11 @@ import { DomSanitizer } from '@angular/platform-browser';
|
||||||
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@core/course/providers/module-delegate';
|
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@core/course/providers/module-delegate';
|
||||||
import { CoreAppProvider } from '@providers/app';
|
import { CoreAppProvider } from '@providers/app';
|
||||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
|
||||||
import { CoreFilepoolProvider } from '@providers/filepool';
|
import { CoreFilepoolProvider } from '@providers/filepool';
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { AddonModLtiIndexComponent } from '../components/index/index';
|
import { AddonModLtiIndexComponent } from '../components/index/index';
|
||||||
import { AddonModLtiProvider } from './lti';
|
import { AddonModLtiProvider } from './lti';
|
||||||
|
import { AddonModLtiHelper } from './helper';
|
||||||
import { CoreConstants } from '@core/constants';
|
import { CoreConstants } from '@core/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,7 +46,6 @@ export class AddonModLtiModuleHandler implements CoreCourseModuleHandler {
|
||||||
|
|
||||||
constructor(private appProvider: CoreAppProvider,
|
constructor(private appProvider: CoreAppProvider,
|
||||||
private courseProvider: CoreCourseProvider,
|
private courseProvider: CoreCourseProvider,
|
||||||
private domUtils: CoreDomUtilsProvider,
|
|
||||||
private filepoolProvider: CoreFilepoolProvider,
|
private filepoolProvider: CoreFilepoolProvider,
|
||||||
private sitesProvider: CoreSitesProvider,
|
private sitesProvider: CoreSitesProvider,
|
||||||
private ltiProvider: AddonModLtiProvider,
|
private ltiProvider: AddonModLtiProvider,
|
||||||
|
@ -85,26 +84,8 @@ export class AddonModLtiModuleHandler implements CoreCourseModuleHandler {
|
||||||
icon: 'link',
|
icon: 'link',
|
||||||
label: 'addon.mod_lti.launchactivity',
|
label: 'addon.mod_lti.launchactivity',
|
||||||
action: (event: Event, navCtrl: NavController, module: any, courseId: number): void => {
|
action: (event: Event, navCtrl: NavController, module: any, courseId: number): void => {
|
||||||
const modal = this.domUtils.showModalLoading();
|
// Launch the LTI.
|
||||||
|
AddonModLtiHelper.instance.getDataAndLaunch(courseId, module);
|
||||||
// Get LTI and launch data.
|
|
||||||
this.ltiProvider.getLti(courseId, module.id).then((ltiData) => {
|
|
||||||
return this.ltiProvider.getLtiLaunchData(ltiData.id).then((launchData) => {
|
|
||||||
// "View" LTI.
|
|
||||||
this.ltiProvider.logView(ltiData.id, ltiData.name).then(() => {
|
|
||||||
this.courseProvider.checkModuleCompletion(courseId, module.completiondata);
|
|
||||||
}).catch(() => {
|
|
||||||
// Ignore errors.
|
|
||||||
});
|
|
||||||
|
|
||||||
// Launch LTI.
|
|
||||||
return this.ltiProvider.launch(launchData.endpoint, launchData.parameters);
|
|
||||||
});
|
|
||||||
}).catch((message) => {
|
|
||||||
this.domUtils.showErrorModalDefault(message, 'addon.mod_lti.errorgetlti', true);
|
|
||||||
}).finally(() => {
|
|
||||||
modal.dismiss();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
|
@ -85,6 +85,13 @@ export class CoreUtilsProvider {
|
||||||
protected modalCtrl: ModalController,
|
protected modalCtrl: ModalController,
|
||||||
protected qrScanner: QRScanner) {
|
protected qrScanner: QRScanner) {
|
||||||
this.logger = logger.getInstance('CoreUtilsProvider');
|
this.logger = logger.getInstance('CoreUtilsProvider');
|
||||||
|
|
||||||
|
const win = <any> window;
|
||||||
|
|
||||||
|
if (win.cordova && win.cordova.InAppBrowser) {
|
||||||
|
// Override the default window.open with the InAppBrowser one.
|
||||||
|
win.open = win.cordova.InAppBrowser.open;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue