+
+
+
+
+
diff --git a/src/addons/mod/workshop/components/index/addon-mod-workshop-index.html b/src/addons/mod/workshop/components/index/addon-mod-workshop-index.html
index 5227b46db..5dd6b0e66 100644
--- a/src/addons/mod/workshop/components/index/addon-mod-workshop-index.html
+++ b/src/addons/mod/workshop/components/index/addon-mod-workshop-index.html
@@ -27,6 +27,12 @@
+
+
+
+
+
diff --git a/src/core/features/course/classes/main-activity-component.ts b/src/core/features/course/classes/main-activity-component.ts
index 4fdcfe9e9..64c256e90 100644
--- a/src/core/features/course/classes/main-activity-component.ts
+++ b/src/core/features/course/classes/main-activity-component.ts
@@ -122,7 +122,14 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
this.syncIcon = CoreConstants.ICON_LOADING;
try {
- await CoreUtils.ignoreErrors(this.invalidateContent());
+ await CoreUtils.ignoreErrors(Promise.all([
+ this.invalidateContent(),
+ this.showCompletion ? CoreCourse.invalidateModule(this.module.id) : undefined,
+ ]));
+
+ if (this.showCompletion) {
+ this.module = await CoreCourse.getModule(this.module.id, this.courseId);
+ }
await this.loadContent(true, sync, showErrors);
} finally {
diff --git a/src/core/features/course/classes/main-resource-component.ts b/src/core/features/course/classes/main-resource-component.ts
index ad336718e..b53613f17 100644
--- a/src/core/features/course/classes/main-resource-component.ts
+++ b/src/core/features/course/classes/main-resource-component.ts
@@ -70,12 +70,14 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
isDestroyed = false; // Whether the component is destroyed, used when calling fillContextMenu.
contextMenuStatusObserver?: CoreEventObserver; // Observer of package status, used when calling fillContextMenu.
contextFileStatusObserver?: CoreEventObserver; // Observer of file status, used when calling fillContextMenu.
+ showCompletion = false; // Whether to show completion inside the activity.
protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents.
protected isCurrentView = false; // Whether the component is in the current view.
protected siteId?: string; // Current Site ID.
protected statusObserver?: CoreEventObserver; // Observer of package status. Only if setStatusListener is called.
protected currentStatus?: string; // The current status of the module. Only if setStatusListener is called.
+ protected completionObserver?: CoreEventObserver;
protected logger: CoreLogger;
constructor(
@@ -94,6 +96,18 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
this.componentId = this.module.id;
this.externalUrl = this.module.url;
this.courseId = this.courseId || this.module.course!;
+ this.showCompletion = !!CoreSites.getCurrentSite()?.isVersionGreaterEqualThan('3.11');
+
+ if (this.showCompletion) {
+ this.completionObserver = CoreEvents.on(CoreEvents.COMPLETION_MODULE_VIEWED, async (data) => {
+ if (data && data.cmId == this.module.id) {
+ await CoreCourse.invalidateModule(this.module.id);
+
+ this.module = await CoreCourse.getModule(this.module.id, this.courseId);
+ }
+ });
+ }
+
this.blog = await AddonBlog.isPluginEnabled();
}
@@ -140,7 +154,14 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
this.refreshIcon = CoreConstants.ICON_LOADING;
try {
- await CoreUtils.ignoreErrors(this.invalidateContent());
+ await CoreUtils.ignoreErrors(Promise.all([
+ this.invalidateContent(),
+ this.showCompletion ? CoreCourse.invalidateModule(this.module.id) : undefined,
+ ]));
+
+ if (this.showCompletion) {
+ this.module = await CoreCourse.getModule(this.module.id, this.courseId);
+ }
await this.loadContent(true);
} finally {
@@ -376,6 +397,16 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
return result;
}
+ /**
+ * The completion of the modules has changed.
+ *
+ * @return Promise resolved when done.
+ */
+ async onCompletionChange(): Promise {
+ // Nothing to do.
+ return;
+ }
+
/**
* Component being destroyed.
*/
@@ -384,6 +415,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
this.contextMenuStatusObserver?.off();
this.contextFileStatusObserver?.off();
this.statusObserver?.off();
+ this.completionObserver?.off();
}
/**
diff --git a/src/core/features/course/classes/module-completion.ts b/src/core/features/course/classes/module-completion.ts
index c78de3695..161da7e94 100644
--- a/src/core/features/course/classes/module-completion.ts
+++ b/src/core/features/course/classes/module-completion.ts
@@ -14,8 +14,6 @@
import { Component, Input, Output, EventEmitter, OnChanges, SimpleChange } from '@angular/core';
-import { CoreDomUtils } from '@services/utils/dom';
-import { CoreCourse } from '@features/course/services/course';
import { CoreCourseModuleCompletionData } from '@features/course/services/course-helper';
/**
@@ -32,7 +30,7 @@ export class CoreCourseModuleCompletionBaseComponent implements OnChanges {
@Output() completionChanged = new EventEmitter(); // Notify when completion changes.
/**
- * Detect changes on input properties.
+ * @inheritdoc
*/
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
if (changes.completion && this.completion) {
@@ -47,47 +45,4 @@ export class CoreCourseModuleCompletionBaseComponent implements OnChanges {
return;
}
- /**
- * Completion clicked.
- *
- * @param e The click event.
- */
- async completionClicked(e: Event): Promise {
- if (!this.completion) {
- return;
- }
-
- if (typeof this.completion.cmid == 'undefined' || this.completion.tracking !== 1) {
- return;
- }
-
- e.preventDefault();
- e.stopPropagation();
-
- const modal = await CoreDomUtils.showModalLoading();
- this.completion.state = this.completion.state === 1 ? 0 : 1;
-
- try {
- const response = await CoreCourse.markCompletedManually(
- this.completion.cmid,
- this.completion.state === 1,
- this.completion.courseId!,
- this.completion.courseName,
- );
-
- if (this.completion.valueused === false) {
- this.calculateData();
- if (response.offline) {
- this.completion.offline = true;
- }
- }
- this.completionChanged.emit(this.completion);
- } catch (error) {
- this.completion.state = this.completion.state === 1 ? 0 : 1;
- CoreDomUtils.showErrorModalDefault(error, 'core.errorchangecompletion', true);
- } finally {
- modal.dismiss();
- }
- }
-
}
diff --git a/src/core/features/course/components/components.module.ts b/src/core/features/course/components/components.module.ts
index 29e90f3cc..3680f6f36 100644
--- a/src/core/features/course/components/components.module.ts
+++ b/src/core/features/course/components/components.module.ts
@@ -24,6 +24,8 @@ import { CoreCourseSectionSelectorComponent } from './section-selector/section-s
import { CoreCourseTagAreaComponent } from './tag-area/tag-area';
import { CoreCourseUnsupportedModuleComponent } from './unsupported-module/unsupported-module';
import { CoreCourseModuleCompletionLegacyComponent } from './module-completion-legacy/module-completion-legacy';
+import { CoreCourseModuleInfoComponent } from './module-info/module-info';
+import { CoreCourseModuleManualCompletionComponent } from './module-manual-completion/module-manual-completion';
@NgModule({
declarations: [
@@ -32,6 +34,8 @@ import { CoreCourseModuleCompletionLegacyComponent } from './module-completion-l
CoreCourseModuleCompletionComponent,
CoreCourseModuleCompletionLegacyComponent,
CoreCourseModuleDescriptionComponent,
+ CoreCourseModuleInfoComponent,
+ CoreCourseModuleManualCompletionComponent,
CoreCourseSectionSelectorComponent,
CoreCourseTagAreaComponent,
CoreCourseUnsupportedModuleComponent,
@@ -46,6 +50,8 @@ import { CoreCourseModuleCompletionLegacyComponent } from './module-completion-l
CoreCourseModuleCompletionComponent,
CoreCourseModuleCompletionLegacyComponent,
CoreCourseModuleDescriptionComponent,
+ CoreCourseModuleInfoComponent,
+ CoreCourseModuleManualCompletionComponent,
CoreCourseSectionSelectorComponent,
CoreCourseTagAreaComponent,
CoreCourseUnsupportedModuleComponent,
diff --git a/src/core/features/course/components/module-completion-legacy/module-completion-legacy.ts b/src/core/features/course/components/module-completion-legacy/module-completion-legacy.ts
index a44dced24..8eca20fe0 100644
--- a/src/core/features/course/components/module-completion-legacy/module-completion-legacy.ts
+++ b/src/core/features/course/components/module-completion-legacy/module-completion-legacy.ts
@@ -19,6 +19,7 @@ import { CoreCourseProvider } 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';
+import { CoreCourseHelper } from '@features/course/services/course-helper';
/**
* Component to handle activity completion in sites previous to 3.11.
@@ -115,4 +116,21 @@ export class CoreCourseModuleCompletionLegacyComponent extends CoreCourseModuleC
this.completionDescription = Translate.instant(langKey, translateParams);
}
+ /**
+ * Completion clicked.
+ *
+ * @param event The click event.
+ */
+ async completionClicked(event: Event): Promise {
+ if (!this.completion) {
+ return;
+ }
+
+ await CoreCourseHelper.changeManualCompletion(this.completion, event);
+
+ this.calculateData();
+
+ this.completionChanged.emit(this.completion);
+ }
+
}
diff --git a/src/core/features/course/components/module-completion/core-course-module-completion.html b/src/core/features/course/components/module-completion/core-course-module-completion.html
index 4951f341d..ffce38a8b 100644
--- a/src/core/features/course/components/module-completion/core-course-module-completion.html
+++ b/src/core/features/course/components/module-completion/core-course-module-completion.html
@@ -27,27 +27,6 @@
-
-
-
-
-
-
- {{ 'core.course.completion_manual:done' | translate }}
-
-
-
-
- {{ 'core.course.completion_manual:markdone' | translate }}
-
-
-
-
-
-
- {{ 'core.course.completion_manual:markdone' | translate }}
-
-
-
+
+
diff --git a/src/core/features/course/components/module-completion/module-completion.scss b/src/core/features/course/components/module-completion/module-completion.scss
index eeded5aaa..946eac3bd 100644
--- a/src/core/features/course/components/module-completion/module-completion.scss
+++ b/src/core/features/course/components/module-completion/module-completion.scss
@@ -9,10 +9,4 @@
}
}
}
-
- .core-module-manual-completion {
- ion-button {
- text-transform: none;
- }
- }
}
diff --git a/src/core/features/course/components/module-completion/module-completion.ts b/src/core/features/course/components/module-completion/module-completion.ts
index 4fa8ffdcb..a147c7b03 100644
--- a/src/core/features/course/components/module-completion/module-completion.ts
+++ b/src/core/features/course/components/module-completion/module-completion.ts
@@ -35,7 +35,7 @@ import { Translate } from '@singletons';
export class CoreCourseModuleCompletionComponent extends CoreCourseModuleCompletionBaseComponent {
@Input() showCompletionConditions = false; // Whether to show activity completion conditions.
- @Input() showManualCompletion = false; // Whether to show manual completion when completion conditions are disabled.
+ @Input() showManualCompletion = false; // Whether to show manual completion.
details?: CompletionRule[];
accessibleDescription: string | null = null;
@@ -48,21 +48,6 @@ export class CoreCourseModuleCompletionComponent extends CoreCourseModuleComplet
return;
}
- // Set an accessible description for manual completions with overridden completion state.
- if (!this.completion.isautomatic && this.completion.overrideby) {
- const setByData = {
- $a: {
- activityname: this.moduleName,
- setby: this.completion.overrideby,
- },
- };
- const setByLangKey = this.completion.state ? 'completion_setby:manual:done' : 'completion_setby:manual:markdone';
- this.accessibleDescription = Translate.instant('core.course.' + setByLangKey, setByData);
- } else {
- const langKey = this.completion.state ? 'completion_manual:aria:done' : 'completion_manual:aria:markdone';
- this.accessibleDescription = Translate.instant('core.course.' + langKey, { $a: this.moduleName });
- }
-
// Format rules.
this.details = this.completion.details.map((rule: CompletionRule) => {
rule.statuscomplete = rule.rulevalue.status == CoreCourseProvider.COMPLETION_COMPLETE ||
diff --git a/src/core/features/course/components/module-info/core-course-module-info.html b/src/core/features/course/components/module-info/core-course-module-info.html
new file mode 100644
index 000000000..d69b3148a
--- /dev/null
+++ b/src/core/features/course/components/module-info/core-course-module-info.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+ {{ date.label }} {{ date.timestamp * 1000 | coreFormatDate:'strftimedatetime' }}
+
+
+
+
+
+
+
+
+
diff --git a/src/core/features/course/components/module-info/module-info.ts b/src/core/features/course/components/module-info/module-info.ts
new file mode 100644
index 000000000..c4748fe4c
--- /dev/null
+++ b/src/core/features/course/components/module-info/module-info.ts
@@ -0,0 +1,31 @@
+// (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 { Component, EventEmitter, Input, Output } from '@angular/core';
+import { CoreCourseModule, CoreCourseModuleCompletionData } from '@features/course/services/course-helper';
+
+/**
+ * Display info about a module: dates and completion.
+ */
+@Component({
+ selector: 'core-course-module-info',
+ templateUrl: 'core-course-module-info.html',
+})
+export class CoreCourseModuleInfoComponent {
+
+ @Input() module!: CoreCourseModule; // The module to render.
+ @Input() showManualCompletion = false; // Whether to show manual completion.
+ @Output() completionChanged = new EventEmitter(); // Notify when completion changes.
+
+}
diff --git a/src/core/features/course/components/module-manual-completion/core-course-module-manual-completion.html b/src/core/features/course/components/module-manual-completion/core-course-module-manual-completion.html
new file mode 100644
index 000000000..0f0ce4be8
--- /dev/null
+++ b/src/core/features/course/components/module-manual-completion/core-course-module-manual-completion.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+ {{ 'core.course.completion_manual:done' | translate }}
+
+
+
+
+ {{ 'core.course.completion_manual:markdone' | translate }}
+
+
+
+
+
+
+ {{ 'core.course.completion_manual:markdone' | translate }}
+
+
+
diff --git a/src/core/features/course/components/module-manual-completion/module-manual-completion.scss b/src/core/features/course/components/module-manual-completion/module-manual-completion.scss
new file mode 100644
index 000000000..0aa279fc8
--- /dev/null
+++ b/src/core/features/course/components/module-manual-completion/module-manual-completion.scss
@@ -0,0 +1,5 @@
+:host {
+ ion-button {
+ text-transform: none;
+ }
+}
diff --git a/src/core/features/course/components/module-manual-completion/module-manual-completion.ts b/src/core/features/course/components/module-manual-completion/module-manual-completion.ts
new file mode 100644
index 000000000..3cab6465e
--- /dev/null
+++ b/src/core/features/course/components/module-manual-completion/module-manual-completion.ts
@@ -0,0 +1,109 @@
+// (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 { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChange } from '@angular/core';
+
+import { CoreCourseHelper, CoreCourseModuleCompletionData } from '@features/course/services/course-helper';
+import { Translate } from '@singletons';
+import { CoreEventObserver, CoreEvents } from '@singletons/events';
+
+/**
+ * Component to display a button for manual completion.
+ */
+@Component({
+ selector: 'core-course-module-manual-completion',
+ templateUrl: 'core-course-module-manual-completion.html',
+ styleUrls: ['module-manual-completion.scss'],
+})
+export class CoreCourseModuleManualCompletionComponent implements OnInit, OnChanges, OnDestroy {
+
+ @Input() completion?: CoreCourseModuleCompletionData; // The completion status.
+ @Input() moduleName?: string; // The name of the module this completion affects.
+ @Output() completionChanged = new EventEmitter(); // Notify when completion changes.
+
+ accessibleDescription: string | null = null;
+
+ protected manualChangedObserver?: CoreEventObserver;
+
+ /**
+ * @inheritdoc
+ */
+ ngOnInit(): void {
+ this.manualChangedObserver = CoreEvents.on(CoreEvents.MANUAL_COMPLETION_CHANGED, (data) => {
+ if (this.completion && this.completion.cmid == data.completion.cmid) {
+ this.completion = data.completion;
+ this.calculateData();
+ }
+ });
+ }
+
+ /**
+ * @inheritdoc
+ */
+ ngOnChanges(changes: { [name: string]: SimpleChange }): void {
+ if (changes.completion && this.completion) {
+ this.calculateData();
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected calculateData(): void {
+ if (!this.completion?.isautomatic) {
+ return;
+ }
+
+ // Set an accessible description for manual completions with overridden completion state.
+ if (this.completion.overrideby) {
+ const setByData = {
+ $a: {
+ activityname: this.moduleName,
+ setby: this.completion.overrideby,
+ },
+ };
+ const setByLangKey = this.completion.state ? 'completion_setby:manual:done' : 'completion_setby:manual:markdone';
+ this.accessibleDescription = Translate.instant('core.course.' + setByLangKey, setByData);
+ } else {
+ const langKey = this.completion.state ? 'completion_manual:aria:done' : 'completion_manual:aria:markdone';
+ this.accessibleDescription = Translate.instant('core.course.' + langKey, { $a: this.moduleName });
+ }
+ }
+
+ /**
+ * Completion clicked.
+ *
+ * @param event The click event.
+ */
+ async completionClicked(event: Event): Promise {
+ if (!this.completion) {
+ return;
+ }
+
+ await CoreCourseHelper.changeManualCompletion(this.completion, event);
+
+ this.calculateData();
+
+ CoreEvents.trigger(CoreEvents.MANUAL_COMPLETION_CHANGED, { completion: this.completion });
+ this.completionChanged.emit(this.completion);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ ngOnDestroy(): void {
+ this.manualChangedObserver?.off();
+ }
+
+}
diff --git a/src/core/features/course/services/course-helper.ts b/src/core/features/course/services/course-helper.ts
index 4b647b267..b8e1ee6b4 100644
--- a/src/core/features/course/services/course-helper.ts
+++ b/src/core/features/course/services/course-helper.ts
@@ -67,6 +67,7 @@ import { CoreNetworkError } from '@classes/errors/network-error';
import { CoreSiteHome } from '@features/sitehome/services/sitehome';
import { CoreNavigator } from '@services/navigator';
import { CoreSiteHomeHomeHandlerService } from '@features/sitehome/services/handlers/sitehome-home';
+import { CoreStatusWithWarningsWSResponse } from '@services/ws';
/**
* Prefetch info of a module.
@@ -1890,6 +1891,52 @@ export class CoreCourseHelperProvider {
await Promise.all(promises);
}
+ /**
+ * Completion clicked.
+ *
+ * @param completion The completion.
+ * @param event The click event.
+ * @return Promise resolved with the result.
+ */
+ async changeManualCompletion(
+ completion: CoreCourseModuleCompletionData,
+ event?: Event,
+ ): Promise {
+ if (!completion) {
+ return;
+ }
+
+ if (typeof completion.cmid == 'undefined' || completion.tracking !== 1) {
+ return;
+ }
+
+ event?.preventDefault();
+ event?.stopPropagation();
+
+ const modal = await CoreDomUtils.showModalLoading();
+ completion.state = completion.state === 1 ? 0 : 1;
+
+ try {
+ const response = await CoreCourse.markCompletedManually(
+ completion.cmid,
+ completion.state === 1,
+ completion.courseId!,
+ completion.courseName,
+ );
+
+ if (response.offline) {
+ completion.offline = true;
+ }
+
+ return response;
+ } catch (error) {
+ completion.state = completion.state === 1 ? 0 : 1;
+ CoreDomUtils.showErrorModalDefault(error, 'core.errorchangecompletion', true);
+ } finally {
+ modal.dismiss();
+ }
+ }
+
}
export const CoreCourseHelper = makeSingleton(CoreCourseHelperProvider);
diff --git a/src/core/features/course/services/course.ts b/src/core/features/course/services/course.ts
index 2c67cb4f5..45fd0aa6b 100644
--- a/src/core/features/course/services/course.ts
+++ b/src/core/features/course/services/course.ts
@@ -150,9 +150,12 @@ export class CoreCourseProvider {
* @param completion Completion status of the module.
*/
checkModuleCompletion(courseId: number, completion?: CoreCourseModuleCompletionData): void {
- if (completion && completion.tracking === 2 && completion.state === 0) {
+ if (completion && completion.tracking === CoreCourseProvider.COMPLETION_TRACKING_AUTOMATIC && completion.state === 0) {
this.invalidateSections(courseId).finally(() => {
- CoreEvents.trigger(CoreEvents.COMPLETION_MODULE_VIEWED, { courseId: courseId });
+ CoreEvents.trigger(CoreEvents.COMPLETION_MODULE_VIEWED, {
+ courseId: courseId,
+ cmId: completion.cmid,
+ });
});
}
}
@@ -969,6 +972,9 @@ export class CoreCourseProvider {
// Ignore errors, shouldn't happen.
}
+ // Invalidate module now, completion has changed.
+ await this.invalidateModule(cmId, siteId);
+
return result;
} catch (error) {
if (CoreUtils.isWebServiceError(error) || !courseId) {
diff --git a/src/core/singletons/events.ts b/src/core/singletons/events.ts
index ee72d67e9..0c622f77b 100644
--- a/src/core/singletons/events.ts
+++ b/src/core/singletons/events.ts
@@ -18,6 +18,7 @@ import { CoreLogger } from '@singletons/logger';
import { CoreSite, CoreSiteInfoResponse, CoreSitePublicConfigResponse } from '@classes/site';
import { CoreFilepoolComponentFileEventData } from '@services/filepool';
import { CoreNavigationOptions } from '@services/navigator';
+import { CoreCourseModuleCompletionData } from '@features/course/services/course-helper';
/**
* Observer instance to stop listening to an event.
@@ -45,6 +46,7 @@ export interface CoreEventsData {
[CoreEvents.NOTIFICATION_SOUND_CHANGED]: CoreEventNotificationSoundChangedData;
[CoreEvents.SELECT_COURSE_TAB]: CoreEventSelectCourseTabData;
[CoreEvents.COMPLETION_MODULE_VIEWED]: CoreEventCompletionModuleViewedData;
+ [CoreEvents.MANUAL_COMPLETION_CHANGED]: CoreEventManualCompletionChangedData;
[CoreEvents.SECTION_STATUS_CHANGED]: CoreEventSectionStatusChangedData;
[CoreEvents.ACTIVITY_DATA_SENT]: CoreEventActivityDataSentData;
[CoreEvents.IAB_LOAD_START]: InAppBrowserEvent;
@@ -53,7 +55,7 @@ export interface CoreEventsData {
[CoreEvents.COMPONENT_FILE_ACTION]: CoreFilepoolComponentFileEventData;
[CoreEvents.FILE_SHARED]: CoreEventFileSharedData;
[CoreEvents.APP_LAUNCHED_URL]: CoreEventAppLaunchedData;
-};
+}
/*
* Service to send and listen to events.
@@ -72,6 +74,7 @@ export class CoreEvents {
static readonly SITE_UPDATED = 'site_updated';
static readonly SITE_DELETED = 'site_deleted';
static readonly COMPLETION_MODULE_VIEWED = 'completion_module_viewed';
+ static readonly MANUAL_COMPLETION_CHANGED = 'manual_completion_changed';
static readonly USER_DELETED = 'user_deleted';
static readonly PACKAGE_STATUS_CHANGED = 'package_status_changed';
static readonly COURSE_STATUS_CHANGED = 'course_status_changed';
@@ -330,7 +333,15 @@ export type CoreEventSelectCourseTabData = {
* Data passed to COMPLETION_MODULE_VIEWED event.
*/
export type CoreEventCompletionModuleViewedData = {
- courseId?: number;
+ courseId: number;
+ cmId?: number;
+};
+
+/**
+ * Data passed to MANUAL_COMPLETION_CHANGED event.
+ */
+export type CoreEventManualCompletionChangedData = {
+ completion: CoreCourseModuleCompletionData;
};
/**