MOBILE-3914 blocks: Add blocks to single activity courses
parent
c5c662989b
commit
3cfa76f7f7
|
@ -1,3 +1,3 @@
|
||||||
<ion-button (click)="openBlocks()" [attr.aria-label]="'core.block.opendrawerblocks' | translate">
|
<ion-button (click)="openBlocks()" [attr.aria-label]="'core.block.opendrawerblocks' | translate">
|
||||||
<ion-icon name="fas-cubes" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-chevron-left" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
||||||
<core-empty-box *ngIf="blocks.length == 0" icon="fas-cubes" [message]="'core.block.noblocks' | translate">
|
<core-empty-box *ngIf="blocks.length == 0" icon="fas-th-large" [message]="'core.block.noblocks' | translate">
|
||||||
</core-empty-box>
|
</core-empty-box>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
|
@ -1 +1,4 @@
|
||||||
<core-dynamic-component [component]="componentClass" [data]="data"></core-dynamic-component>
|
<core-dynamic-component [component]="componentClass" [data]="data"></core-dynamic-component>
|
||||||
|
|
||||||
|
<core-block-side-blocks-button *ngIf="course && hasBlocks" [courseId]="course.id" [downloadEnabled]="downloadEnabled">
|
||||||
|
</core-block-side-blocks-button>
|
||||||
|
|
|
@ -20,6 +20,8 @@ import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-comp
|
||||||
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
import { IonRefresher } from '@ionic/angular';
|
||||||
import { CoreCourseModuleCompletionData, CoreCourseSectionWithStatus } from '@features/course/services/course-helper';
|
import { CoreCourseModuleCompletionData, CoreCourseSectionWithStatus } from '@features/course/services/course-helper';
|
||||||
|
import { CoreBlockHelper } from '@features/block/services/block-helper';
|
||||||
|
import { CoreCourse } from '@features/course/services/course';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component to display single activity format. It will determine the right component to use and instantiate it.
|
* Component to display single activity format. It will determine the right component to use and instantiate it.
|
||||||
|
@ -44,12 +46,13 @@ export class CoreCourseFormatSingleActivityComponent implements OnChanges {
|
||||||
|
|
||||||
componentClass?: Type<unknown>; // The class of the component to render.
|
componentClass?: Type<unknown>; // The class of the component to render.
|
||||||
data: Record<string | number, unknown> = {}; // Data to pass to the component.
|
data: Record<string | number, unknown> = {}; // Data to pass to the component.
|
||||||
|
hasBlocks = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect changes on input properties.
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async ngOnChanges(changes: { [name: string]: SimpleChange }): Promise<void> {
|
async ngOnChanges(changes: { [name: string]: SimpleChange }): Promise<void> {
|
||||||
if (!changes.course || !changes.sections) {
|
if (!changes.course && !changes.sections) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +60,8 @@ export class CoreCourseFormatSingleActivityComponent implements OnChanges {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.hasBlocks = await CoreBlockHelper.hasCourseBlocks(this.course.id);
|
||||||
|
|
||||||
// In single activity the module should only have 1 section and 1 module. Get the module.
|
// In single activity the module should only have 1 section and 1 module. Get the module.
|
||||||
const module = this.sections?.[0].modules?.[0];
|
const module = this.sections?.[0].modules?.[0];
|
||||||
|
|
||||||
|
@ -85,6 +90,15 @@ export class CoreCourseFormatSingleActivityComponent implements OnChanges {
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.dynamicComponent?.callComponentFunction('doRefresh', [refresher, done]);
|
await this.dynamicComponent?.callComponentFunction('doRefresh', [refresher, done]);
|
||||||
|
|
||||||
|
if (this.course) {
|
||||||
|
const courseId = this.course.id;
|
||||||
|
await CoreCourse.invalidateCourseBlocks(courseId).then(async () => {
|
||||||
|
this.hasBlocks = await CoreBlockHelper.hasCourseBlocks(courseId);
|
||||||
|
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,43 +31,28 @@ export class CoreCourseFormatSingleActivityHandlerService implements CoreCourseF
|
||||||
format = 'singleactivity';
|
format = 'singleactivity';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the handler is enabled on a site level.
|
* @inheritdoc
|
||||||
*
|
|
||||||
* @return True or promise resolved with true if enabled.
|
|
||||||
*/
|
*/
|
||||||
async isEnabled(): Promise<boolean> {
|
async isEnabled(): Promise<boolean> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether it allows seeing all sections at the same time. Defaults to true.
|
* @inheritdoc
|
||||||
*
|
|
||||||
* @param course The course to check.
|
|
||||||
* @return Whether it can view all sections.
|
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
canViewAllSections(): boolean {
|
||||||
canViewAllSections(course: CoreCourseAnyCourseData): boolean {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the option blocks should be displayed. Defaults to true.
|
* @inheritdoc
|
||||||
*
|
|
||||||
* @param course The course to check.
|
|
||||||
* @return Whether it can display blocks.
|
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
displayBlocks(): boolean {
|
||||||
displayBlocks(course: CoreCourseAnyCourseData): boolean {
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the title to use in course page. If not defined, course displayname or fullname.
|
* @inheritdoc
|
||||||
* This function will be called without sections first, and then call it again when the sections are retrieved.
|
|
||||||
*
|
|
||||||
* @param course The course.
|
|
||||||
* @param sections List of sections.
|
|
||||||
* @return Title.
|
|
||||||
*/
|
*/
|
||||||
getCourseTitle(course: CoreCourseAnyCourseData, sections?: CoreCourseWSSection[]): string {
|
getCourseTitle(course: CoreCourseAnyCourseData, sections?: CoreCourseWSSection[]): string {
|
||||||
if (sections?.[0]?.modules?.[0]) {
|
if (sections?.[0]?.modules?.[0]) {
|
||||||
|
@ -84,34 +69,21 @@ export class CoreCourseFormatSingleActivityHandlerService implements CoreCourseF
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the option to enable section/module download should be displayed. Defaults to true.
|
* @inheritdoc
|
||||||
*
|
|
||||||
* @param course The course to check.
|
|
||||||
* @return Whether the option to enable section/module download should be displayed
|
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
displayEnableDownload(): boolean {
|
||||||
displayEnableDownload(course: CoreCourseAnyCourseData): boolean {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the default section selector should be displayed. Defaults to true.
|
* @inheritdoc
|
||||||
*
|
|
||||||
* @param course The course to check.
|
|
||||||
* @return Whether the default section selector should be displayed.
|
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
displaySectionSelector(): boolean {
|
||||||
displaySectionSelector(course: CoreCourseAnyCourseData): boolean {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the course refresher should be displayed. If it returns false, a refresher must be included in the course format,
|
* @inheritdoc
|
||||||
* and the doRefresh method of CoreCourseSectionPage must be called on refresh. Defaults to true.
|
|
||||||
*
|
|
||||||
* @param course The course to check.
|
|
||||||
* @param sections List of course sections.
|
|
||||||
* @return Whether the refresher should be displayed.
|
|
||||||
*/
|
*/
|
||||||
displayRefresher(course: CoreCourseAnyCourseData, sections: CoreCourseWSSection[]): boolean {
|
displayRefresher(course: CoreCourseAnyCourseData, sections: CoreCourseWSSection[]): boolean {
|
||||||
if (sections?.[0]?.modules?.[0]) {
|
if (sections?.[0]?.modules?.[0]) {
|
||||||
|
@ -122,28 +94,16 @@ export class CoreCourseFormatSingleActivityHandlerService implements CoreCourseF
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the Component to use to display the course format instead of using the default one.
|
* @inheritdoc
|
||||||
* Use it if you want to display a format completely different from the default one.
|
|
||||||
* If you want to customize the default format there are several methods to customize parts of it.
|
|
||||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
|
||||||
*
|
|
||||||
* @param course The course to render.
|
|
||||||
* @return The component (or promise resolved with component) to use, undefined if not found.
|
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
async getCourseFormatComponent(): Promise<Type<unknown>> {
|
||||||
async getCourseFormatComponent(course: CoreCourseAnyCourseData): Promise<Type<unknown>> {
|
|
||||||
return CoreCourseFormatSingleActivityComponent;
|
return CoreCourseFormatSingleActivityComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the view should be refreshed when completion changes. If your course format doesn't display
|
* @inheritdoc
|
||||||
* activity completion then you should return false.
|
|
||||||
*
|
|
||||||
* @param course The course.
|
|
||||||
* @return Whether course view should be refreshed when an activity completion changes.
|
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
async shouldRefreshWhenCompletionChanges(): Promise<boolean> {
|
||||||
async shouldRefreshWhenCompletionChanges(course: CoreCourseAnyCourseData): Promise<boolean> {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { CoreSharedModule } from '@/core/shared.module';
|
||||||
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
||||||
import { CoreCourseFormatSingleActivityComponent } from './components/singleactivity';
|
import { CoreCourseFormatSingleActivityComponent } from './components/singleactivity';
|
||||||
import { CoreCourseFormatSingleActivityHandler } from './services/handlers/singleactivity-format';
|
import { CoreCourseFormatSingleActivityHandler } from './services/handlers/singleactivity-format';
|
||||||
|
import { CoreBlockComponentsModule } from '@features/block/components/components.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -25,6 +26,7 @@ import { CoreCourseFormatSingleActivityHandler } from './services/handlers/singl
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CoreSharedModule,
|
CoreSharedModule,
|
||||||
|
CoreBlockComponentsModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue