Merge pull request #2999 from crazyserver/MOBILE-3914

Mobile 3914
main
Dani Palou 2021-11-17 11:12:59 +01:00 committed by GitHub
commit fb909f63a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 46 additions and 62 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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;
});
}
} }
/** /**

View File

@ -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;
} }

View File

@ -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: [
{ {

View File

@ -183,8 +183,13 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
return; return;
} }
const numItems = CoreMainMenu.getNumItems(); // Calculate the main handlers not to display them in this view.
this.moreBadge = this.allHandlers.some((handler, index) => (handler.onlyInMore || index >= numItems) && !!handler.badge); const mainHandlers = this.allHandlers
.filter((handler) => !handler.onlyInMore)
.slice(0, CoreMainMenu.getNumItems());
// Use only the handlers that don't appear in the main view.
this.moreBadge = this.allHandlers.some((handler) => mainHandlers.indexOf(handler) == -1 && !!handler.badge);
} }
/** /**