Skip to content

Commit 43f4fde

Browse files
committed
MOBILE-4770 overview: Support site plugins items in overview
1 parent 550badd commit 43f4fde

File tree

7 files changed

+159
-35
lines changed

7 files changed

+159
-35
lines changed

src/core/features/course/classes/module-base-handler.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { CoreNavigationOptions, CoreNavigator } from '@services/navigator';
1616
import { CoreCourseModuleHelper } from '../services/course-module-helper';
1717
import { CoreCourseModuleData } from '../services/course-helper';
1818
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData, CoreCourseOverviewItemContent } from '../services/module-delegate';
19-
import { CoreCourseOverviewItem } from '../services/course-overview';
19+
import { CoreCourseOverviewActivity, CoreCourseOverviewItem } from '../services/course-overview';
2020

2121
/**
2222
* Base module handler to be registered.
@@ -94,7 +94,11 @@ export class CoreModuleHandlerBase implements Partial<CoreCourseModuleHandler> {
9494
/**
9595
* @inheritdoc
9696
*/
97-
async getOverviewItemContent(item: CoreCourseOverviewItem): Promise<CoreCourseOverviewItemContent | undefined> {
97+
async getOverviewItemContent(
98+
item: CoreCourseOverviewItem,
99+
activity: CoreCourseOverviewActivity, // eslint-disable-line @typescript-eslint/no-unused-vars
100+
courseId: number, // eslint-disable-line @typescript-eslint/no-unused-vars
101+
): Promise<CoreCourseOverviewItemContent | undefined> {
98102
// Handle items common to all modules or items using common renderables.
99103
if (item.key === 'name') {
100104
const { CoreCourseOverviewItemNameComponent } =

src/core/features/course/pages/overview/overview.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ export default class CoreCourseOverviewPage implements OnInit {
262262
}
263263

264264
// Get the data to render the item.
265-
const content = await CoreCourseModuleDelegate.getOverviewItemContent(modName, item);
265+
const content = await CoreCourseModuleDelegate.getOverviewItemContent(modName, item, activity, this.courseId);
266266

267267
if (content === undefined) {
268268
// The app doesn't know how to render the item, mark the mod type as not supported and render an empty item.

src/core/features/course/services/module-delegate.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { CoreNavigationOptions } from '@services/navigator';
2727
import { DownloadStatus } from '@/core/constants';
2828
import { CORE_COURSE_MODULE_FEATURE_PREFIX } from '../constants';
2929
import { ModFeature } from '@addons/mod/constants';
30-
import { CoreCourseOverviewItem } from './course-overview';
30+
import { CoreCourseOverviewActivity, CoreCourseOverviewItem } from './course-overview';
3131

3232
/**
3333
* Interface that all course module handlers must implement.
@@ -129,9 +129,15 @@ export interface CoreCourseModuleHandler extends CoreDelegateHandler {
129129
* Get the data to render a course overview item.
130130
*
131131
* @param item Item to get the content for.
132+
* @param activity Activity data the item belongs to.
133+
* @param courseId Course ID the item belongs to.
132134
* @returns Data to render the item content. If undefined it means the app doesn't know how to render the item.
133135
*/
134-
getOverviewItemContent?(item: CoreCourseOverviewItem): Promise<CoreCourseOverviewItemContent | undefined>;
136+
getOverviewItemContent?(
137+
item: CoreCourseOverviewItem,
138+
activity: CoreCourseOverviewActivity,
139+
courseId: number,
140+
): Promise<CoreCourseOverviewItemContent | undefined>;
135141
}
136142

137143
/**
@@ -422,14 +428,22 @@ export class CoreCourseModuleDelegateService extends CoreDelegate<CoreCourseModu
422428
*
423429
* @param modname The name of the module type.
424430
* @param item Overview item data.
431+
* @param activity Activity data the item belongs to.
432+
* @param courseId Course ID the item belongs to.
425433
* @returns Data to render the item.
426434
*/
427435
async getOverviewItemContent(
428436
modname: string,
429437
item: CoreCourseOverviewItem,
438+
activity: CoreCourseOverviewActivity,
439+
courseId: number,
430440
): Promise<CoreCourseOverviewItemContent | undefined> {
431441
// Support overview even if the handler is disabled.
432-
return await this.executeFunction<CoreCourseOverviewItemContent>(modname, 'getOverviewItemContent', [item]);
442+
return await this.executeFunction<CoreCourseOverviewItemContent>(
443+
modname,
444+
'getOverviewItemContent',
445+
[item, activity, courseId],
446+
);
433447
}
434448

435449
/**

src/core/features/siteplugins/classes/handlers/module-handler.ts

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ import { Type } from '@angular/core';
1616

1717
import { CoreCourseModuleHelper } from '@features/course/services/course-module-helper';
1818
import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper';
19-
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate';
19+
import {
20+
CoreCourseModuleHandler,
21+
CoreCourseModuleHandlerData,
22+
CoreCourseOverviewItemContent,
23+
} from '@features/course/services/module-delegate';
2024
import {
2125
CoreSitePlugins,
2226
CoreSitePluginsContent,
@@ -25,30 +29,31 @@ import {
2529
} from '@features/siteplugins/services/siteplugins';
2630
import { CoreNavigationOptions, CoreNavigator } from '@services/navigator';
2731
import { CoreLogger } from '@singletons/logger';
28-
import { CoreSitePluginsBaseHandler } from './base-handler';
2932
import { CoreEvents } from '@singletons/events';
3033
import { CorePromiseUtils } from '@singletons/promise-utils';
3134
import { CORE_SITE_PLUGINS_UPDATE_COURSE_CONTENT } from '@features/siteplugins/constants';
3235
import { ModFeature } from '@addons/mod/constants';
36+
import { CoreCourseOverviewActivity, CoreCourseOverviewItem } from '@features/course/services/course-overview';
37+
import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler';
3338

3439
/**
3540
* Handler to support a module using a site plugin.
3641
*/
37-
export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler implements CoreCourseModuleHandler {
42+
export class CoreSitePluginsModuleHandler extends CoreModuleHandlerBase implements CoreCourseModuleHandler {
3843

3944
supportedFeatures?: Record<ModFeature, unknown>;
4045
supportsFeature?: (feature: ModFeature) => unknown;
4146

4247
protected logger: CoreLogger;
4348

4449
constructor(
45-
name: string,
50+
public name: string,
4651
public modName: string,
4752
protected plugin: CoreSitePluginsPlugin,
4853
protected handlerSchema: CoreSitePluginsCourseModuleHandlerData,
4954
protected initResult: CoreSitePluginsContent | null,
5055
) {
51-
super(name);
56+
super();
5257

5358
this.logger = CoreLogger.getInstance('CoreSitePluginsModuleHandler');
5459
this.supportedFeatures = handlerSchema.supportedfeatures;
@@ -244,4 +249,50 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp
244249
CoreNavigator.navigateToSitePath(`siteplugins/module/${courseId}/${module.id}`, options);
245250
}
246251

252+
/**
253+
* @inheritdoc
254+
*/
255+
async getOverviewItemContent(
256+
item: CoreCourseOverviewItem,
257+
activity: CoreCourseOverviewActivity,
258+
courseId: number,
259+
): Promise<CoreCourseOverviewItemContent | undefined> {
260+
const content = await this.getOverviewItemContentFromInitTemplates(item, activity, courseId);
261+
262+
return content ?? super.getOverviewItemContent(item, activity, courseId);
263+
}
264+
265+
/**
266+
* If there is a template in the init result to render the item, use it to render the content.
267+
*
268+
* @param item Item to render.
269+
* @param activity Activity data the item belongs to.
270+
* @param courseId Course ID the item belongs to.
271+
* @returns Content to render, undefined if no template found.
272+
*/
273+
protected async getOverviewItemContentFromInitTemplates(
274+
item: CoreCourseOverviewItem,
275+
activity: CoreCourseOverviewActivity,
276+
courseId: number,
277+
): Promise<CoreCourseOverviewItemContent | undefined> {
278+
const template = this.initResult?.templates?.find(template => template.id === item.key);
279+
if (!template) {
280+
return;
281+
}
282+
283+
const { CoreSitePluginsOverviewItemComponent } =
284+
await import('@features/siteplugins/components/overview-item/overview-item');
285+
286+
return {
287+
component: CoreSitePluginsOverviewItemComponent,
288+
componentData: {
289+
item,
290+
activity,
291+
courseId,
292+
html: template.html,
293+
otherData: this.initResult?.otherdata,
294+
},
295+
};
296+
}
297+
247298
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<core-compile-html [text]="html()" [jsData]="jsData()" />
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// (C) Copyright 2015 Moodle Pty Ltd.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import { CoreSharedModule } from '@/core/shared.module';
16+
import { Component, computed, input } from '@angular/core';
17+
import { CoreCompileHtmlComponent } from '@features/compile/components/compile-html/compile-html';
18+
import { CoreCourseOverviewActivity, CoreCourseOverviewItem } from '@features/course/services/course-overview';
19+
20+
/**
21+
* Component to render a site plugin overview item.
22+
*/
23+
@Component({
24+
selector: 'core-site-plugins-overview-item',
25+
templateUrl: 'core-siteplugins-overview-item.html',
26+
imports: [
27+
CoreSharedModule,
28+
CoreCompileHtmlComponent,
29+
],
30+
})
31+
export class CoreSitePluginsOverviewItemComponent {
32+
33+
readonly courseId = input.required<number>();
34+
readonly activity = input.required<CoreCourseOverviewActivity>();
35+
readonly item = input.required<CoreCourseOverviewItem<unknown>>();
36+
readonly html = input.required<string>();
37+
readonly otherData = input<Record<string,unknown>>();
38+
39+
// Pass jsData even if there's no JS code because the JS variables can be used in the HTML.
40+
readonly jsData = computed(() => ({
41+
courseId: this.courseId(),
42+
activity: this.activity(),
43+
item: this.item(),
44+
// Make a copy of otherdata to make it unique for each item and activity.
45+
INIT_OTHERDATA: { ...(this.otherData() ?? {}) }, // eslint-disable-line @typescript-eslint/naming-convention
46+
}));
47+
48+
}

src/core/features/siteplugins/services/siteplugins-init.ts

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ import { CoreEnrolAction, CoreEnrolDelegate } from '@features/enrol/services/enr
8989
import { CoreSitePluginsEnrolHandler } from '../classes/handlers/enrol-handler';
9090
import { CORE_SITE_PLUGINS_COMPONENT } from '../constants';
9191
import { CORE_COURSES_MY_COURSES_CHANGED_EVENT } from '@features/courses/constants';
92+
import { CoreSitePluginsBaseHandler } from '../classes/handlers/base-handler';
9293

9394
/**
9495
* Helper service to provide functionalities regarding site plugins. It basically has the features to load and register site
@@ -598,18 +599,7 @@ export class CoreSitePluginsInitService {
598599
handlerSchema.methodJSResult = result.jsResult;
599600
handlerSchema.methodOtherdata = result.otherdata;
600601

601-
if (result.jsResult) {
602-
// Override default handler functions with the result of the method JS.
603-
const jsResult = <Record<string, unknown>> result.jsResult;
604-
const handlerProperties = CoreObject.getAllPropertyNames(handler);
605-
606-
for (const property of handlerProperties) {
607-
if (property !== 'constructor' && typeof handler[property] === 'function' &&
608-
typeof jsResult[property] === 'function') {
609-
handler[property] = (<Function> jsResult[property]).bind(handler);
610-
}
611-
}
612-
}
602+
this.overrideHandlerFunctions(handler, result);
613603

614604
delegate.registerHandler(handler);
615605

@@ -821,18 +811,7 @@ export class CoreSitePluginsInitService {
821811
return;
822812
}
823813

824-
if (result.jsResult) {
825-
// Override default handler functions with the result of the method JS.
826-
const jsResult = <Record<string, unknown>> result.jsResult;
827-
const handlerProperties = CoreObject.getAllPropertyNames(handler);
828-
829-
for (const property of handlerProperties) {
830-
if (property !== 'constructor' && typeof handler[property] === 'function' &&
831-
typeof jsResult[property] === 'function') {
832-
handler[property] = (<Function> jsResult[property]).bind(handler);
833-
}
834-
}
835-
}
814+
this.overrideHandlerFunctions(handler, result);
836815
}
837816

838817
CoreEnrolDelegate.registerHandler(handler);
@@ -1240,6 +1219,33 @@ export class CoreSitePluginsInitService {
12401219
return uniqueName;
12411220
}
12421221

1222+
/**
1223+
* Override some functions in a handler with the result of the JS returned by a get_content call.
1224+
*
1225+
* @param handler Handler to override.
1226+
* @param result Result of the get_content call.
1227+
*/
1228+
protected overrideHandlerFunctions(handler: CoreSitePluginsBaseHandler, result: CoreSitePluginsContent | null): void {
1229+
if (!result || !result.jsResult) {
1230+
// No JS result, nothing to do.
1231+
return;
1232+
}
1233+
1234+
// Override default handler functions with the result of the method JS.
1235+
const jsResult = <Record<string, unknown>> result.jsResult;
1236+
const handlerProperties = CoreObject.getAllPropertyNames(handler);
1237+
1238+
for (const property of handlerProperties) {
1239+
if (
1240+
property !== 'constructor' &&
1241+
typeof handler[property] === 'function' &&
1242+
typeof jsResult[property] === 'function'
1243+
) {
1244+
handler[property] = (<Function> jsResult[property]).bind(handler);
1245+
}
1246+
}
1247+
}
1248+
12431249
}
12441250

12451251
export const CoreSitePluginsInit = makeSingleton(CoreSitePluginsInitService);

0 commit comments

Comments
 (0)