MOBILE-2840 scorm: Launch automatically
parent
c62237e1db
commit
e8f7219883
|
@ -24,7 +24,7 @@
|
|||
|
||||
<div *ngIf="scorm && loaded && !scorm.warningMessage">
|
||||
<!-- Attempts status. -->
|
||||
<ion-card *ngIf="scorm.displayattemptstatus || (scorm.offlineAttempts && scorm.offlineAttempts.length)">
|
||||
<ion-card *ngIf="(scorm.displayattemptstatus || (scorm.offlineAttempts && scorm.offlineAttempts.length)) && !skip">
|
||||
<ion-card-header text-wrap>
|
||||
<h2>{{ 'addon.mod_scorm.attempts' | translate }}</h2>
|
||||
</ion-card-header>
|
||||
|
@ -75,7 +75,7 @@
|
|||
</div>
|
||||
|
||||
<!-- TOC. -->
|
||||
<ion-card *ngIf="scorm && organizations && ((scorm.displaycoursestructure && organizations.length) || organizations.length > 1)" class="addon-mod_scorm-toc">
|
||||
<ion-card *ngIf="scorm && organizations && ((scorm.displaycoursestructure && organizations.length) || organizations.length > 1) && !skip" class="addon-mod_scorm-toc">
|
||||
<ion-card-header text-wrap>
|
||||
<h2>{{ 'addon.mod_scorm.contents' | translate }}</h2>
|
||||
</ion-card-header>
|
||||
|
@ -128,7 +128,7 @@
|
|||
<ion-card *ngIf="!errorMessage && scorm && (!scorm.lastattemptlock || scorm.attemptsLeft > 0)">
|
||||
<ion-list>
|
||||
<!-- Open mode (Preview or Normal) -->
|
||||
<div *ngIf="!scorm.hidebrowse" radio-group [(ngModel)]="scormOptions.mode" name="mode">
|
||||
<div *ngIf="!scorm.hidebrowse && !skip" radio-group [(ngModel)]="scormOptions.mode" name="mode">
|
||||
<ion-item>
|
||||
<p class="item-heading">{{ 'addon.mod_scorm.mode' | translate }}</p>
|
||||
</ion-item>
|
||||
|
@ -143,14 +143,14 @@
|
|||
</div>
|
||||
|
||||
<!-- Create new attempt -->
|
||||
<ion-item text-wrap *ngIf="!scorm.forcenewattempt && scorm.numAttempts > 0 && !scorm.incomplete && scorm.attemptsLeft > 0">
|
||||
<ion-item text-wrap *ngIf="!scorm.forcenewattempt && scorm.numAttempts > 0 && !scorm.incomplete && scorm.attemptsLeft > 0 && !skip">
|
||||
<ion-label>{{ 'addon.mod_scorm.newattempt' | translate }}</ion-label>
|
||||
<ion-checkbox item-end name="newAttempt" [(ngModel)]="scormOptions.newAttempt">
|
||||
</ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<!-- Button to open the SCORM. -->
|
||||
<ng-container *ngIf="!downloading">
|
||||
<ng-container *ngIf="!downloading && !skip">
|
||||
<ion-item text-wrap *ngIf="statusMessage">
|
||||
<p >{{ statusMessage | translate }}</p>
|
||||
</ion-item>
|
||||
|
|
|
@ -54,6 +54,8 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
|
|||
organizations: any[]; // List of organizations.
|
||||
loadingToc: boolean; // Whether the TOC is being loaded.
|
||||
toc: any[]; // Table of contents (structure).
|
||||
accessInfo: any; // Access information.
|
||||
skip: boolean; // Launch immediately.
|
||||
|
||||
protected fetchContentDefaultError = 'addon.mod_scorm.errorgetscorm'; // Default error to show when loading contents.
|
||||
protected syncEventName = AddonModScormSyncProvider.AUTO_SYNCED;
|
||||
|
@ -83,6 +85,10 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
|
|||
return;
|
||||
}
|
||||
|
||||
if (this.skip) {
|
||||
this.open();
|
||||
}
|
||||
|
||||
this.scormProvider.logView(this.scorm.id, this.scorm.name).then(() => {
|
||||
this.checkCompletion();
|
||||
}).catch((error) => {
|
||||
|
@ -181,54 +187,72 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
|
|||
this.syncTime = syncTime;
|
||||
});
|
||||
|
||||
// Get the number of attempts.
|
||||
return this.scormProvider.getAttemptCount(this.scorm.id);
|
||||
}).then((attemptsData) => {
|
||||
this.attempts = attemptsData;
|
||||
this.hasOffline = !!this.attempts.offline.length;
|
||||
|
||||
// Determine the attempt that will be continued or reviewed.
|
||||
return this.scormHelper.determineAttemptToContinue(this.scorm, this.attempts);
|
||||
}).then((attempt) => {
|
||||
this.lastAttempt = attempt.number;
|
||||
this.lastIsOffline = attempt.offline;
|
||||
|
||||
if (this.lastAttempt != this.attempts.lastAttempt.number) {
|
||||
this.attemptToContinue = this.lastAttempt;
|
||||
} else {
|
||||
this.attemptToContinue = undefined;
|
||||
}
|
||||
|
||||
// Check if the last attempt is incomplete.
|
||||
return this.scormProvider.isAttemptIncomplete(this.scorm.id, this.lastAttempt, this.lastIsOffline);
|
||||
}).then((incomplete) => {
|
||||
const promises = [];
|
||||
|
||||
this.scorm.incomplete = incomplete;
|
||||
this.scorm.numAttempts = this.attempts.total;
|
||||
this.scorm.gradeMethodReadable = this.scormProvider.getScormGradeMethod(this.scorm);
|
||||
this.scorm.attemptsLeft = this.scormProvider.countAttemptsLeft(this.scorm, this.attempts.lastAttempt.number);
|
||||
// Get access information.
|
||||
promises.push(this.scormProvider.getAccessInformation(this.scorm.id).then((accessInfo) => {
|
||||
this.accessInfo = accessInfo;
|
||||
}));
|
||||
|
||||
if (this.scorm.forcenewattempt == AddonModScormProvider.SCORM_FORCEATTEMPT_ALWAYS ||
|
||||
(this.scorm.forcenewattempt && !this.scorm.incomplete)) {
|
||||
this.scormOptions.newAttempt = true;
|
||||
}
|
||||
// Get the number of attempts.
|
||||
promises.push(this.scormProvider.getAttemptCount(this.scorm.id).then((attemptsData) => {
|
||||
this.attempts = attemptsData;
|
||||
this.hasOffline = !!this.attempts.offline.length;
|
||||
|
||||
promises.push(this.getReportedGrades());
|
||||
// Determine the attempt that will be continued or reviewed.
|
||||
return this.scormHelper.determineAttemptToContinue(this.scorm, this.attempts);
|
||||
}).then((attempt) => {
|
||||
this.lastAttempt = attempt.number;
|
||||
this.lastIsOffline = attempt.offline;
|
||||
|
||||
promises.push(this.fetchStructure());
|
||||
if (this.lastAttempt != this.attempts.lastAttempt.number) {
|
||||
this.attemptToContinue = this.lastAttempt;
|
||||
} else {
|
||||
this.attemptToContinue = undefined;
|
||||
}
|
||||
|
||||
if (!this.scorm.packagesize && this.errorMessage === '') {
|
||||
// SCORM is supported but we don't have package size. Try to calculate it.
|
||||
promises.push(this.scormProvider.calculateScormSize(this.scorm).then((size) => {
|
||||
this.scorm.packagesize = size;
|
||||
}));
|
||||
}
|
||||
// Check if the last attempt is incomplete.
|
||||
return this.scormProvider.isAttemptIncomplete(this.scorm.id, this.lastAttempt, this.lastIsOffline);
|
||||
}).then((incomplete) => {
|
||||
const promises = [];
|
||||
|
||||
// Handle status.
|
||||
this.setStatusListener();
|
||||
this.scorm.incomplete = incomplete;
|
||||
this.scorm.numAttempts = this.attempts.total;
|
||||
this.scorm.gradeMethodReadable = this.scormProvider.getScormGradeMethod(this.scorm);
|
||||
this.scorm.attemptsLeft = this.scormProvider.countAttemptsLeft(this.scorm, this.attempts.lastAttempt.number);
|
||||
|
||||
return Promise.all(promises);
|
||||
if (this.scorm.forcenewattempt == AddonModScormProvider.SCORM_FORCEATTEMPT_ALWAYS ||
|
||||
(this.scorm.forcenewattempt && !this.scorm.incomplete)) {
|
||||
this.scormOptions.newAttempt = true;
|
||||
}
|
||||
|
||||
promises.push(this.getReportedGrades());
|
||||
|
||||
promises.push(this.fetchStructure());
|
||||
|
||||
if (!this.scorm.packagesize && this.errorMessage === '') {
|
||||
// SCORM is supported but we don't have package size. Try to calculate it.
|
||||
promises.push(this.scormProvider.calculateScormSize(this.scorm).then((size) => {
|
||||
this.scorm.packagesize = size;
|
||||
}));
|
||||
}
|
||||
|
||||
// Handle status.
|
||||
promises.push(this.setStatusListener());
|
||||
|
||||
return Promise.all(promises);
|
||||
}));
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
// Check whether to launch the SCORM immediately.
|
||||
if (typeof this.skip == 'undefined' && !this.hasOffline && !this.errorMessage &&
|
||||
(!this.scorm.lastattemptlock || this.scorm.attemptsLeft > 0) &&
|
||||
this.accessInfo.canskipview && !this.accessInfo.canviewreport &&
|
||||
this.scorm.skipview >= AddonModScormProvider.SKIPVIEW_FIRST &&
|
||||
(this.scorm.skipview == AddonModScormProvider.SKIPVIEW_ALWAYS || this.lastAttempt == 0)) {
|
||||
this.skip = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}).then(() => {
|
||||
// All data obtained, now fill the context menu.
|
||||
|
@ -368,6 +392,9 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
|
|||
ionViewDidLeave(): void {
|
||||
super.ionViewDidLeave();
|
||||
|
||||
// Display the full page when returning to the page.
|
||||
this.skip = false;
|
||||
|
||||
if (this.navCtrl.getActive().component.name == 'AddonModScormPlayerPage') {
|
||||
this.hasPlayed = true;
|
||||
|
||||
|
@ -460,11 +487,17 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
|
|||
});
|
||||
}
|
||||
|
||||
// Open a SCORM. It will download the SCORM package if it's not downloaded or it has changed.
|
||||
// The scoId param indicates the SCO that needs to be loaded when the SCORM is opened. If not defined, load first SCO.
|
||||
open(e: Event, scoId: number): void {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
/**
|
||||
* Open a SCORM. It will download the SCORM package if it's not downloaded or it has changed.
|
||||
*
|
||||
* @param {Event} [event] Event.
|
||||
* @param {string} [scoId] SCO that needs to be loaded when the SCORM is opened. If not defined, load first SCO.
|
||||
*/
|
||||
open(event?: Event, scoId?: number): void {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
if (this.downloading) {
|
||||
// Scope is being downloaded, abort.
|
||||
|
|
|
@ -123,6 +123,9 @@ export class AddonModScormPrefetchHandler extends CoreCourseActivityPrefetchHand
|
|||
// Ignore errors.
|
||||
}));
|
||||
|
||||
// Prefetch access information.
|
||||
promises.push(this.scormProvider.getAccessInformation(scorm.id));
|
||||
|
||||
return Promise.all(promises);
|
||||
}).then(() => {
|
||||
// Success, return the hash.
|
||||
|
|
|
@ -83,6 +83,10 @@ export class AddonModScormProvider {
|
|||
static SCORM_FORCEATTEMPT_ONCOMPLETE = 1;
|
||||
static SCORM_FORCEATTEMPT_ALWAYS = 2;
|
||||
|
||||
static SKIPVIEW_NEVER = 0;
|
||||
static SKIPVIEW_FIRST = 1;
|
||||
static SKIPVIEW_ALWAYS = 2;
|
||||
|
||||
// Events.
|
||||
static LAUNCH_NEXT_SCO_EVENT = 'addon_mod_scorm_launch_next_sco';
|
||||
static LAUNCH_PREV_SCO_EVENT = 'addon_mod_scorm_launch_prev_sco';
|
||||
|
@ -442,6 +446,44 @@ export class AddonModScormProvider {
|
|||
return formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get access information for a given SCORM.
|
||||
*
|
||||
* @param {number} scormId SCORM ID.
|
||||
* @param {boolean} [forceCache] True to always get the value from cache. false otherwise.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @return {Promise<any>} Object with access information.
|
||||
* @since 3.7
|
||||
*/
|
||||
getAccessInformation(scormId: number, forceCache?: boolean, siteId?: string): Promise<any> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
if (!site.wsAvailable('mod_scorm_get_scorm_access_information')) {
|
||||
// Access information not available for 3.6 or older sites.
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
const params = {
|
||||
scormid: scormId
|
||||
};
|
||||
const preSets = {
|
||||
cacheKey: this.getAccessInformationCacheKey(scormId),
|
||||
omitExpires: forceCache
|
||||
};
|
||||
|
||||
return site.read('mod_scorm_get_scorm_access_information', params, preSets);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache key for access information WS calls.
|
||||
*
|
||||
* @param {number} scormId SCORM ID.
|
||||
* @return {string} Cache key.
|
||||
*/
|
||||
protected getAccessInformationCacheKey(scormId: number): string {
|
||||
return this.ROOT_CACHE_KEY + 'accessInfo:' + scormId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of attempts done by a user in the given SCORM.
|
||||
*
|
||||
|
@ -1176,6 +1218,19 @@ export class AddonModScormProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates access information.
|
||||
*
|
||||
* @param {number} forumId SCORM ID.
|
||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||
* @return {Promise<any>} Promise resolved when the data is invalidated.
|
||||
*/
|
||||
invalidateAccessInformation(scormId: number, siteId?: string): Promise<any> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
return site.invalidateWsCacheForKey(this.getAccessInformationCacheKey(scormId));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates all the data related to a certain SCORM.
|
||||
*
|
||||
|
@ -1190,6 +1245,7 @@ export class AddonModScormProvider {
|
|||
promises.push(this.invalidateAttemptCount(scormId, siteId, userId));
|
||||
promises.push(this.invalidateScos(scormId, siteId));
|
||||
promises.push(this.invalidateScormUserData(scormId, siteId));
|
||||
promises.push(this.invalidateAccessInformation(scormId, siteId));
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
|
|
@ -254,8 +254,10 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
|
|||
|
||||
/**
|
||||
* Watch for changes on the status.
|
||||
*
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
protected setStatusListener(): void {
|
||||
protected setStatusListener(): Promise<any> {
|
||||
if (typeof this.statusObserver == 'undefined') {
|
||||
// Listen for changes on this module status.
|
||||
this.statusObserver = this.eventsProvider.on(CoreEventsProvider.PACKAGE_STATUS_CHANGED, (data) => {
|
||||
|
@ -269,11 +271,13 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
|
|||
}, this.siteId);
|
||||
|
||||
// Also, get the current status.
|
||||
this.modulePrefetchDelegate.getModuleStatus(this.module, this.courseId).then((status) => {
|
||||
return this.modulePrefetchDelegate.getModuleStatus(this.module, this.courseId).then((status) => {
|
||||
this.currentStatus = status;
|
||||
this.showStatus(status);
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue