MOBILE-3833 course: Use completion enums
parent
efece1d4ac
commit
13fbaf0b0f
|
@ -100,7 +100,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
|||
this.showCompletion = !!CoreSites.getRequiredCurrentSite().isVersionGreaterEqualThan('3.11');
|
||||
|
||||
if (this.showCompletion) {
|
||||
CoreCourseHelper.calculateModuleCompletionData(this.module, this.courseId);
|
||||
CoreCourseHelper.calculateModuleCompletionData(this.module);
|
||||
CoreCourseHelper.loadModuleOfflineCompletion(this.courseId, this.module);
|
||||
|
||||
this.completionObserver = CoreEvents.on(CoreEvents.COMPLETION_MODULE_VIEWED, async (data) => {
|
||||
|
@ -428,7 +428,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
|||
protected async fetchModule(): Promise<void> {
|
||||
const module = await CoreCourse.getModule(this.module.id, this.courseId);
|
||||
|
||||
CoreCourseHelper.calculateModuleCompletionData(module, this.courseId);
|
||||
CoreCourseHelper.calculateModuleCompletionData(module);
|
||||
|
||||
await CoreCourseHelper.loadModuleOfflineCompletion(this.courseId, module);
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-comp
|
|||
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
||||
import {
|
||||
CoreCourse,
|
||||
CoreCourseModuleCompletionStatus,
|
||||
CoreCourseProvider,
|
||||
} from '@features/course/services/course';
|
||||
import {
|
||||
|
@ -643,7 +644,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
|
||||
const moduleProgressPercent = 100 / (completionModules || 1);
|
||||
// Use min/max here to avoid floating point rounding errors over/under-flowing the progress bar.
|
||||
if (completionData.state === CoreCourseProvider.COMPLETION_COMPLETE) {
|
||||
if (completionData.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE) {
|
||||
this.course.progress = Math.min(100, this.course.progress + moduleProgressPercent);
|
||||
} else {
|
||||
this.course.progress = Math.max(0, this.course.progress - moduleProgressPercent);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
import { CoreUser } from '@features/user/services/user';
|
||||
import { CoreCourseProvider } from '@features/course/services/course';
|
||||
import { CoreCourseModuleCompletionStatus, CoreCourseModuleCompletionTracking } from '@features/course/services/course';
|
||||
import { CoreFilterHelper } from '@features/filter/services/filter-helper';
|
||||
import { Translate } from '@singletons';
|
||||
import { CoreCourseModuleCompletionBaseComponent } from '@features/course/classes/module-completion';
|
||||
|
@ -52,28 +52,28 @@ export class CoreCourseModuleCompletionLegacyComponent extends CoreCourseModuleC
|
|||
let langKey: string | undefined;
|
||||
let image: string | undefined;
|
||||
|
||||
if (this.completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_MANUAL &&
|
||||
this.completion.state === CoreCourseProvider.COMPLETION_INCOMPLETE) {
|
||||
if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL &&
|
||||
this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE) {
|
||||
image = 'completion-manual-n';
|
||||
langKey = 'core.completion-alt-manual-n';
|
||||
} else if (this.completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_MANUAL &&
|
||||
this.completion.state === CoreCourseProvider.COMPLETION_COMPLETE) {
|
||||
} else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL &&
|
||||
this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE) {
|
||||
image = 'completion-manual-y';
|
||||
langKey = 'core.completion-alt-manual-y';
|
||||
} else if (this.completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_AUTOMATIC &&
|
||||
this.completion.state === CoreCourseProvider.COMPLETION_INCOMPLETE) {
|
||||
} else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC &&
|
||||
this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE) {
|
||||
image = 'completion-auto-n';
|
||||
langKey = 'core.completion-alt-auto-n';
|
||||
} else if (this.completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_AUTOMATIC &&
|
||||
this.completion.state === CoreCourseProvider.COMPLETION_COMPLETE) {
|
||||
} else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC &&
|
||||
this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE) {
|
||||
image = 'completion-auto-y';
|
||||
langKey = 'core.completion-alt-auto-y';
|
||||
} else if (this.completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_AUTOMATIC &&
|
||||
this.completion.state === CoreCourseProvider.COMPLETION_COMPLETE_PASS) {
|
||||
} else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC &&
|
||||
this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_PASS) {
|
||||
image = 'completion-auto-pass';
|
||||
langKey = 'core.completion-alt-auto-pass';
|
||||
} else if (this.completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_AUTOMATIC &&
|
||||
this.completion.state === CoreCourseProvider.COMPLETION_COMPLETE_FAIL) {
|
||||
} else if (this.completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC &&
|
||||
this.completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_FAIL) {
|
||||
image = 'completion-auto-fail';
|
||||
langKey = 'core.completion-alt-auto-fail';
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import { Component, Input } from '@angular/core';
|
||||
|
||||
import { CoreCourseModuleCompletionBaseComponent } from '@features/course/classes/module-completion';
|
||||
import { CoreCourseModuleWSRuleDetails, CoreCourseProvider } from '@features/course/services/course';
|
||||
import { CoreCourseModuleCompletionStatus, CoreCourseModuleWSRuleDetails } from '@features/course/services/course';
|
||||
import { CoreUser } from '@features/user/services/user';
|
||||
import { Translate } from '@singletons';
|
||||
|
||||
|
@ -51,10 +51,10 @@ export class CoreCourseModuleCompletionComponent extends CoreCourseModuleComplet
|
|||
|
||||
// Format rules.
|
||||
this.details = await Promise.all(this.completion.details.map(async (rule: CompletionRule) => {
|
||||
rule.statuscomplete = rule.rulevalue.status == CoreCourseProvider.COMPLETION_COMPLETE ||
|
||||
rule.rulevalue.status == CoreCourseProvider.COMPLETION_COMPLETE_PASS;
|
||||
rule.statuscompletefail = rule.rulevalue.status == CoreCourseProvider.COMPLETION_COMPLETE_FAIL;
|
||||
rule.statusincomplete = rule.rulevalue.status == CoreCourseProvider.COMPLETION_INCOMPLETE;
|
||||
rule.statuscomplete = rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE ||
|
||||
rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_PASS;
|
||||
rule.statuscompletefail = rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_FAIL;
|
||||
rule.statusincomplete = rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE;
|
||||
rule.accessibleDescription = null;
|
||||
|
||||
if (this.completion!.overrideby) {
|
||||
|
|
|
@ -15,7 +15,11 @@
|
|||
import { Component, Input, OnInit } from '@angular/core';
|
||||
|
||||
import { CoreCourseSection } from '@features/course/services/course-helper';
|
||||
import { CoreCourseProvider } from '@features/course/services/course';
|
||||
import {
|
||||
CoreCourseModuleCompletionStatus,
|
||||
CoreCourseModuleCompletionTracking,
|
||||
CoreCourseProvider,
|
||||
} from '@features/course/services/course';
|
||||
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { ModalController } from '@singletons';
|
||||
|
@ -56,14 +60,14 @@ export class CoreCourseSectionSelectorComponent implements OnInit {
|
|||
let complete = 0;
|
||||
let total = 0;
|
||||
section.modules.forEach((module) => {
|
||||
if (!module.uservisible || module.completiondata === undefined || module.completiondata.tracking === undefined ||
|
||||
module.completiondata.tracking <= CoreCourseProvider.COMPLETION_TRACKING_NONE) {
|
||||
if (!module.uservisible || module.completiondata === undefined ||
|
||||
module.completiondata.tracking == CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
total++;
|
||||
if (module.completiondata.state == CoreCourseProvider.COMPLETION_COMPLETE ||
|
||||
module.completiondata.state == CoreCourseProvider.COMPLETION_COMPLETE_PASS) {
|
||||
if (module.completiondata.state == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE ||
|
||||
module.completiondata.state == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_PASS) {
|
||||
complete++;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -73,7 +73,7 @@ export class CoreCourseModulePreviewPage implements OnInit {
|
|||
this.module = await CoreCourse.getModule(this.module.id, this.courseId);
|
||||
}
|
||||
|
||||
CoreCourseHelper.calculateModuleCompletionData(this.module, this.courseId);
|
||||
CoreCourseHelper.calculateModuleCompletionData(this.module);
|
||||
|
||||
await CoreCourseHelper.loadModuleOfflineCompletion(this.courseId, this.module);
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ import {
|
|||
CoreCourseWSModule,
|
||||
CoreCourseProvider,
|
||||
CoreCourseWSSection,
|
||||
CoreCourseModuleCompletionTracking,
|
||||
CoreCourseModuleCompletionStatus,
|
||||
} from './course';
|
||||
import { CoreConstants } from '@/core/constants';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
|
@ -200,8 +202,8 @@ export class CoreCourseHelperProvider {
|
|||
);
|
||||
|
||||
if (module.completiondata) {
|
||||
this.calculateModuleCompletionData(module, courseId, courseName);
|
||||
} else if (completionStatus && typeof completionStatus[module.id] != 'undefined') {
|
||||
this.calculateModuleCompletionData(module, undefined, courseName);
|
||||
} else if (completionStatus && completionStatus[module.id] !== undefined) {
|
||||
// Should not happen on > 3.6. Check if activity has completions and if it's marked.
|
||||
const activityStatus = completionStatus[module.id];
|
||||
|
||||
|
@ -229,18 +231,18 @@ export class CoreCourseHelperProvider {
|
|||
* Calculate completion data of a module.
|
||||
*
|
||||
* @param module Module.
|
||||
* @param courseId Course ID of the module.
|
||||
* @param courseId Not used since 4.0
|
||||
* @param courseName Course name.
|
||||
*/
|
||||
calculateModuleCompletionData(module: CoreCourseModule, courseId: number, courseName?: string): void {
|
||||
calculateModuleCompletionData(module: CoreCourseModule, courseId?: number, courseName?: string): void {
|
||||
if (!module.completiondata || !module.completion) {
|
||||
return;
|
||||
}
|
||||
|
||||
module.completiondata.courseId = courseId;
|
||||
module.completiondata.courseName = courseName;
|
||||
module.completiondata.courseId = module.course;
|
||||
module.completiondata.tracking = module.completion;
|
||||
module.completiondata.cmid = module.id;
|
||||
module.completiondata.courseName = courseName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2069,7 +2071,8 @@ export class CoreCourseHelperProvider {
|
|||
return;
|
||||
}
|
||||
|
||||
if (typeof completion.cmid == 'undefined' || completion.tracking !== 1) {
|
||||
if (completion.cmid === undefined ||
|
||||
completion.tracking !== CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2077,14 +2080,15 @@ export class CoreCourseHelperProvider {
|
|||
event?.stopPropagation();
|
||||
|
||||
const modal = await CoreDomUtils.showModalLoading();
|
||||
completion.state = completion.state === 1 ? 0 : 1;
|
||||
completion.state = completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE
|
||||
? CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE
|
||||
: CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE;
|
||||
|
||||
try {
|
||||
const response = await CoreCourse.markCompletedManually(
|
||||
completion.cmid,
|
||||
completion.state === 1,
|
||||
completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE,
|
||||
completion.courseId!,
|
||||
completion.courseName,
|
||||
);
|
||||
|
||||
if (response.offline) {
|
||||
|
@ -2093,7 +2097,11 @@ export class CoreCourseHelperProvider {
|
|||
|
||||
return response;
|
||||
} catch (error) {
|
||||
completion.state = completion.state === 1 ? 0 : 1;
|
||||
// Restore previous state.
|
||||
completion.state = completion.state === CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE
|
||||
? CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE
|
||||
: CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE;
|
||||
|
||||
CoreDomUtils.showErrorModalDefault(error, 'core.errorchangecompletion', true);
|
||||
} finally {
|
||||
modal.dismiss();
|
||||
|
@ -2139,7 +2147,7 @@ export type CoreCourseModule = Omit<CoreCourseWSModule, 'completiondata'> & {
|
|||
export type CoreCourseModuleCompletionData = CoreCourseModuleWSCompletionData & {
|
||||
courseId?: number;
|
||||
courseName?: string;
|
||||
tracking?: number;
|
||||
tracking?: CoreCourseModuleCompletionTracking;
|
||||
cmid?: number;
|
||||
offline?: boolean;
|
||||
};
|
||||
|
|
|
@ -61,6 +61,25 @@ declare module '@singletons/events' {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Completion status valid values.
|
||||
*/
|
||||
export enum CoreCourseModuleCompletionStatus {
|
||||
COMPLETION_INCOMPLETE = 0,
|
||||
COMPLETION_COMPLETE = 1,
|
||||
COMPLETION_COMPLETE_PASS = 2,
|
||||
COMPLETION_COMPLETE_FAIL = 3,
|
||||
}
|
||||
|
||||
/**
|
||||
* Completion tracking valid values.
|
||||
*/
|
||||
export enum CoreCourseModuleCompletionTracking {
|
||||
COMPLETION_TRACKING_NONE = 0,
|
||||
COMPLETION_TRACKING_MANUAL = 1,
|
||||
COMPLETION_TRACKING_AUTOMATIC = 2,
|
||||
}
|
||||
|
||||
/**
|
||||
* Service that provides some features regarding a course.
|
||||
*/
|
||||
|
@ -73,13 +92,34 @@ export class CoreCourseProvider {
|
|||
static readonly ACCESS_DEFAULT = 'courses_access_default';
|
||||
static readonly ALL_COURSES_CLEARED = -1;
|
||||
|
||||
/**
|
||||
* @deprecated since 4.0, use CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_NONE instead.
|
||||
*/
|
||||
static readonly COMPLETION_TRACKING_NONE = 0;
|
||||
/**
|
||||
* @deprecated since 4.0, use CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL instead.
|
||||
*/
|
||||
static readonly COMPLETION_TRACKING_MANUAL = 1;
|
||||
/**
|
||||
* @deprecated since 4.0, use CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC instead.
|
||||
*/
|
||||
static readonly COMPLETION_TRACKING_AUTOMATIC = 2;
|
||||
|
||||
/**
|
||||
* @deprecated since 4.0, use CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE instead.
|
||||
*/
|
||||
static readonly COMPLETION_INCOMPLETE = 0;
|
||||
/**
|
||||
* @deprecated since 4.0, use CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE instead.
|
||||
*/
|
||||
static readonly COMPLETION_COMPLETE = 1;
|
||||
/**
|
||||
* @deprecated since 4.0, use CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_PASS instead.
|
||||
*/
|
||||
static readonly COMPLETION_COMPLETE_PASS = 2;
|
||||
/**
|
||||
* @deprecated since 4.0, use CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_FAIL instead.
|
||||
*/
|
||||
static readonly COMPLETION_COMPLETE_FAIL = 3;
|
||||
|
||||
static readonly COMPONENT = 'CoreCourse';
|
||||
|
@ -151,7 +191,8 @@ export class CoreCourseProvider {
|
|||
* @param completion Completion status of the module.
|
||||
*/
|
||||
checkModuleCompletion(courseId: number, completion?: CoreCourseModuleCompletionData): void {
|
||||
if (completion && completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_AUTOMATIC && completion.state === 0) {
|
||||
if (completion && completion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC &&
|
||||
completion.state === CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE) {
|
||||
this.invalidateSections(courseId).finally(() => {
|
||||
CoreEvents.trigger(CoreEvents.COMPLETION_MODULE_VIEWED, {
|
||||
courseId: courseId,
|
||||
|
@ -256,7 +297,7 @@ export class CoreCourseProvider {
|
|||
const onlineCompletion = completionStatus[offlineCompletion.cmid];
|
||||
|
||||
// If the activity uses manual completion, override the value with the offline one.
|
||||
if (onlineCompletion.tracking === 1) {
|
||||
if (onlineCompletion.tracking === CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL) {
|
||||
onlineCompletion.state = offlineCompletion.completed;
|
||||
onlineCompletion.offline = true;
|
||||
}
|
||||
|
@ -986,7 +1027,7 @@ export class CoreCourseProvider {
|
|||
CoreCourseOffline.markCompletedManually(cmId, completed, courseId, courseName, siteId);
|
||||
|
||||
// The offline function requires a courseId and it could be missing because it's a calculated field.
|
||||
if (!CoreApp.isOnline() && courseId) {
|
||||
if (!CoreApp.isOnline()) {
|
||||
// App is offline, store the action.
|
||||
return storeOffline();
|
||||
}
|
||||
|
@ -996,18 +1037,14 @@ export class CoreCourseProvider {
|
|||
const result = await this.markCompletedManuallyOnline(cmId, completed, siteId);
|
||||
|
||||
// Data sent to server, if there is some offline data delete it now.
|
||||
try {
|
||||
await CoreCourseOffline.deleteManualCompletion(cmId, siteId);
|
||||
} catch {
|
||||
// Ignore errors, shouldn't happen.
|
||||
}
|
||||
await CoreUtils.ignoreErrors(CoreCourseOffline.deleteManualCompletion(cmId, siteId));
|
||||
|
||||
// Invalidate module now, completion has changed.
|
||||
await this.invalidateModule(cmId, siteId);
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (CoreUtils.isWebServiceError(error) || !courseId) {
|
||||
if (CoreUtils.isWebServiceError(error)) {
|
||||
// The WebService has thrown an error, this means that responses cannot be submitted.
|
||||
throw error;
|
||||
} else {
|
||||
|
@ -1346,7 +1383,7 @@ export type CoreCourseCompletionActivityStatus = {
|
|||
instance: number; // Instance ID.
|
||||
state: number; // Completion state value: 0 means incomplete, 1 complete, 2 complete pass, 3 complete fail.
|
||||
timecompleted: number; // Timestamp for completed activity.
|
||||
tracking: number; // Type of tracking: 0 means none, 1 manual, 2 automatic.
|
||||
tracking: CoreCourseModuleCompletionTracking; // Type of tracking: 0 means none, 1 manual, 2 automatic.
|
||||
overrideby?: number | null; // The user id who has overriden the status, or null.
|
||||
valueused?: boolean; // Whether the completion status affects the availability of another activity.
|
||||
hascompletion?: boolean; // @since 3.11. Whether this activity module has completion enabled.
|
||||
|
@ -1497,7 +1534,7 @@ export type CoreCourseWSModule = {
|
|||
afterlink?: string; // After link info to be displayed.
|
||||
customdata?: string; // Custom data (JSON encoded).
|
||||
noviewlink?: boolean; // Whether the module has no view page.
|
||||
completion?: number; // Type of completion tracking: 0 means none, 1 manual, 2 automatic.
|
||||
completion?: CoreCourseModuleCompletionTracking; // Type of completion tracking: 0 means none, 1 manual, 2 automatic.
|
||||
completiondata?: CoreCourseModuleWSCompletionData; // Module completion data.
|
||||
contents?: CoreCourseModuleContentFile[];
|
||||
dates?: {
|
||||
|
@ -1517,7 +1554,7 @@ export type CoreCourseWSModule = {
|
|||
* Module completion data.
|
||||
*/
|
||||
export type CoreCourseModuleWSCompletionData = {
|
||||
state: number; // Completion state value: 0 means incomplete, 1 complete, 2 complete pass, 3 complete fail.
|
||||
state: CoreCourseModuleCompletionStatus; // Completion state value.
|
||||
timecompleted: number; // Timestamp for completion status.
|
||||
overrideby: number | null; // The user id who has overriden the status.
|
||||
valueused?: boolean; // Whether the completion status affects the availability of another activity.
|
||||
|
|
Loading…
Reference in New Issue