MOBILE-3025 blocks: Show blocks on sidebar
This commit is contained in:
		
							parent
							
								
									83d2f455ef
								
							
						
					
					
						commit
						cec6844968
					
				| @ -23,6 +23,12 @@ ion-app.app-root core-ion-tabs { | ||||
|         background-color: $ion-tabs-badge-color; | ||||
|     } | ||||
| 
 | ||||
|     &[tabsplacement="bottom"] { | ||||
|         .ion-page > ion-content > .scroll-content { | ||||
|             margin-bottom: $navbar-md-height !important; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     &[tabsplacement="side"] { | ||||
|         .tabbar { | ||||
|             @include float(start); | ||||
| @ -53,6 +59,10 @@ ion-app.app-root core-ion-tabs { | ||||
|                 position: relative; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         .scroll-content, .fixed-content { | ||||
|             margin-bottom: 0 !important; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -14,9 +14,8 @@ | ||||
| 
 | ||||
| import { NgModule } from '@angular/core'; | ||||
| import { CoreBlockDelegate } from './providers/delegate'; | ||||
| import { CoreBlockHelperProvider } from './providers/helper'; | ||||
| import { CoreBlockDefaultHandler } from './providers/default-block-handler'; | ||||
| import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate'; | ||||
| import { CoreBlockCourseBlocksCourseOptionHandler } from './providers/course-option-handler'; | ||||
| import { CoreBlockComponentsModule } from './components/components.module'; | ||||
| 
 | ||||
| // List of providers (without handlers).
 | ||||
| @ -31,14 +30,10 @@ export const CORE_BLOCK_PROVIDERS: any[] = [ | ||||
|     ], | ||||
|     providers: [ | ||||
|         CoreBlockDelegate, | ||||
|         CoreBlockDefaultHandler, | ||||
|         CoreBlockCourseBlocksCourseOptionHandler | ||||
|         CoreBlockHelperProvider, | ||||
|         CoreBlockDefaultHandler | ||||
|     ], | ||||
|     exports: [] | ||||
| }) | ||||
| export class CoreBlockModule { | ||||
|     constructor(courseOptionHandler: CoreBlockCourseBlocksCourseOptionHandler, | ||||
|             courseOptionsDelegate: CoreCourseOptionsDelegate) { | ||||
|         courseOptionsDelegate.registerHandler(courseOptionHandler); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,15 +1,14 @@ | ||||
| <ion-content> | ||||
|     <ion-refresher [enabled]="dataLoaded" (ionRefresh)="doRefresh($event)"> | ||||
|         <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content> | ||||
|     </ion-refresher> | ||||
| <div class="core-course-blocks-content"> | ||||
|     <ng-content></ng-content> | ||||
| </div> | ||||
| 
 | ||||
| <ion-content *ngIf="blocks && blocks.length > 0" [class.core-hide-blocks]="hideBlocks" class="core-course-blocks-side"> | ||||
|     <core-loading [hideUntil]="dataLoaded" class="core-loading-center"> | ||||
|         <ion-list *ngIf="hasSupportedBlock"> | ||||
|         <ion-list> | ||||
|             <!-- Course blocks. --> | ||||
|             <ng-container *ngFor="let block of blocks"> | ||||
|                 <core-block [block]="block" contextLevel="course" [instanceId]="courseId"></core-block> | ||||
|                 <core-block [block]="block" contextLevel="course" [instanceId]="courseId" [extraData]="{'downloadEnabled': downloadEnabled}"></core-block> | ||||
|             </ng-container> | ||||
|         </ion-list> | ||||
| 
 | ||||
|         <core-empty-box *ngIf="!hasSupportedBlock" icon="qr-scanner" [message]="'core.course.nocontentavailable' | translate"></core-empty-box> | ||||
|     </core-loading> | ||||
| </ion-content> | ||||
|  | ||||
							
								
								
									
										74
									
								
								src/core/block/components/course-blocks/course-blocks.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/core/block/components/course-blocks/course-blocks.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | ||||
| $core-side-blocks-max-width: 320px; | ||||
| $core-side-blocks-min-width: 30%; | ||||
| 
 | ||||
| .core-course-block-with-blocks > .scroll-content { | ||||
|     overflow-y: visible; | ||||
| } | ||||
| 
 | ||||
| ion-app.app-root core-block-course-blocks { | ||||
| 
 | ||||
|     &.core-no-blocks { | ||||
|         .core-course-blocks-content > ion-content { | ||||
|             height: auto; | ||||
|             contain: content; | ||||
| 
 | ||||
|             > .scroll-content { | ||||
|                 overflow-y: visible; | ||||
|                 position: relative; | ||||
|                 contain: content; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     &.core-has-blocks { | ||||
|         @include media-breakpoint-up(md) { | ||||
|             @include position(0, 0, 0, 0); | ||||
| 
 | ||||
|             position: absolute; | ||||
| 
 | ||||
|             display: flex; | ||||
| 
 | ||||
|             flex-direction: row; | ||||
|             flex-wrap: nowrap; | ||||
| 
 | ||||
|             contain: strict; | ||||
| 
 | ||||
|             .core-course-blocks-content { | ||||
|                 min-width: calc(100% - #{($core-side-blocks-max-width)}); | ||||
|                 max-width: calc(100% - #{($core-side-blocks-min-width)}); | ||||
|                 z-index: 0; | ||||
|                 flex: 1; | ||||
|                 box-shadow: none !important; | ||||
|             } | ||||
| 
 | ||||
|             ion-content.core-course-blocks-side { | ||||
|                 transform: none !important; | ||||
|                 position: sticky; | ||||
|                 @include position(0, 0, 0, auto); | ||||
|                 z-index: 30; | ||||
|                 max-width: $core-side-blocks-max-width; | ||||
|                 min-width: $core-side-blocks-min-width; | ||||
|                 @include border-start(1px, solid, $list-md-border-color); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         @include media-breakpoint-down(sm) { | ||||
|             // Disable scroll on individual columns. | ||||
|             .core-course-blocks-content > ion-content, | ||||
|             ion-content.core-course-blocks-side { | ||||
|                 height: auto; | ||||
|                 contain: content; | ||||
| 
 | ||||
|                 &.core-hide-blocks { | ||||
|                     display: none; | ||||
|                 } | ||||
| 
 | ||||
|                 > .scroll-content { | ||||
|                     overflow-y: visible; | ||||
|                     position: relative; | ||||
|                     contain: content; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -12,11 +12,12 @@ | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { Component, ViewChildren, Input, OnInit, QueryList } from '@angular/core'; | ||||
| import { Component, ViewChildren, Input, OnInit, QueryList, ElementRef, Optional } from '@angular/core'; | ||||
| import { Content } from 'ionic-angular'; | ||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||
| import { CoreBlockComponent } from '../block/block'; | ||||
| import { CoreBlockDelegate } from '../../providers/delegate'; | ||||
| import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreBlockComponent } from '../block/block'; | ||||
| import { CoreBlockHelperProvider } from '../../providers/helper'; | ||||
| 
 | ||||
| /** | ||||
|  * Component that displays the list of course blocks. | ||||
| @ -28,16 +29,22 @@ import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| export class CoreBlockCourseBlocksComponent implements OnInit { | ||||
| 
 | ||||
|     @Input() courseId: number; | ||||
|     @Input() hideBlocks = false; | ||||
|     @Input() downloadEnabled: boolean; | ||||
| 
 | ||||
|     @ViewChildren(CoreBlockComponent) blocksComponents: QueryList<CoreBlockComponent>; | ||||
| 
 | ||||
|     dataLoaded = false; | ||||
|     hasContent: boolean; | ||||
|     hasSupportedBlock: boolean; | ||||
|     blocks = []; | ||||
| 
 | ||||
|     protected element: HTMLElement; | ||||
|     protected parentContent: HTMLElement; | ||||
| 
 | ||||
|     constructor(private domUtils: CoreDomUtilsProvider, private courseProvider: CoreCourseProvider, | ||||
|             private blockDelegate: CoreBlockDelegate) { | ||||
|             protected blockHelper: CoreBlockHelperProvider, element: ElementRef, | ||||
|             @Optional() content: Content) { | ||||
|         this.element = element.nativeElement; | ||||
|         this.parentContent = content.getElementRef().nativeElement; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -50,14 +57,14 @@ export class CoreBlockCourseBlocksComponent implements OnInit { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Refresh the data. | ||||
|      * Invalidate blocks data. | ||||
|      * | ||||
|      * @param {any} refresher Refresher. | ||||
|      * @return {Promise<any>} Promise resolved when done. | ||||
|      */ | ||||
|     doRefresh(refresher: any): void { | ||||
|     invalidateBlocks(): Promise<any> { | ||||
|         const promises = []; | ||||
| 
 | ||||
|         if (this.courseProvider.canGetCourseBlocks()) { | ||||
|         if (this.blockHelper.canGetCourseBlocks()) { | ||||
|             promises.push(this.courseProvider.invalidateCourseBlocks(this.courseId)); | ||||
|         } | ||||
| 
 | ||||
| @ -68,11 +75,7 @@ export class CoreBlockCourseBlocksComponent implements OnInit { | ||||
|             })); | ||||
|         }); | ||||
| 
 | ||||
|         Promise.all(promises).finally(() => { | ||||
|             this.loadContent().finally(() => { | ||||
|                 refresher.complete(); | ||||
|             }); | ||||
|         }); | ||||
|         return Promise.all(promises); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -80,21 +83,24 @@ export class CoreBlockCourseBlocksComponent implements OnInit { | ||||
|      * | ||||
|      * @return {Promise<any>} Promise resolved when done. | ||||
|      */ | ||||
|     protected loadContent(): Promise<any> { | ||||
|         // Get site home blocks.
 | ||||
|         const canGetBlocks = this.courseProvider.canGetCourseBlocks(), | ||||
|             promise = canGetBlocks ? this.courseProvider.getCourseBlocks(this.courseId) : Promise.reject(null); | ||||
| 
 | ||||
|         return promise.then((blocks) => { | ||||
|     loadContent(): Promise<any> { | ||||
|         return this.blockHelper.getCourseBlocks(this.courseId).then((blocks) => { | ||||
|             this.blocks = blocks; | ||||
|             this.hasSupportedBlock = this.blockDelegate.hasSupportedBlock(blocks); | ||||
| 
 | ||||
|         }).catch((error) => { | ||||
|             if (canGetBlocks) { | ||||
|             this.domUtils.showErrorModal(error); | ||||
|             } | ||||
|             this.blocks = []; | ||||
|         }); | ||||
| 
 | ||||
|             this.blocks = []; | ||||
|         }).finally(() => { | ||||
|             if (this.blocks.length > 0) { | ||||
|                 this.element.classList.add('core-has-blocks'); | ||||
|                 this.element.classList.remove('core-no-blocks'); | ||||
| 
 | ||||
|                 this.parentContent.classList.add('core-course-block-with-blocks'); | ||||
|             } else { | ||||
|                 this.element.classList.remove('core-has-blocks'); | ||||
|                 this.element.classList.add('core-no-blocks'); | ||||
|                 this.parentContent.classList.remove('core-course-block-with-blocks'); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,3 +1,3 @@ | ||||
| <ion-item-divider text-wrap detail-push (click)="gotoBlock($event)"> | ||||
|     <h2>{{ title | translate }}</h2> | ||||
|     <h2><core-format-text [text]="title | translate"></core-format-text></h2> | ||||
| </ion-item-divider> | ||||
| @ -1,91 +0,0 @@ | ||||
| // (C) Copyright 2015 Martin Dougiamas
 | ||||
| //
 | ||||
| // 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 { Injectable, Injector } from '@angular/core'; | ||||
| import { CoreCourseOptionsHandler, CoreCourseOptionsHandlerData } from '@core/course/providers/options-delegate'; | ||||
| import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreBlockCourseBlocksComponent } from '../components/course-blocks/course-blocks'; | ||||
| import { CoreBlockDelegate } from './delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Course nav handler. | ||||
|  */ | ||||
| @Injectable() | ||||
| export class CoreBlockCourseBlocksCourseOptionHandler implements CoreCourseOptionsHandler { | ||||
|     name = 'CoreCourseBlocks'; | ||||
|     priority = 700; | ||||
| 
 | ||||
|     constructor(private courseProvider: CoreCourseProvider, private blockDelegate: CoreBlockDelegate) {} | ||||
| 
 | ||||
|     /** | ||||
|      * Should invalidate the data to determine if the handler is enabled for a certain course. | ||||
|      * | ||||
|      * @param {number} courseId The course ID. | ||||
|      * @param {any} [navOptions] Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions. | ||||
|      * @param {any} [admOptions] Course admin options for current user. See CoreCoursesProvider.getUserAdministrationOptions. | ||||
|      * @return {Promise<any>} Promise resolved when done. | ||||
|      */ | ||||
|     invalidateEnabledForCourse(courseId: number, navOptions?: any, admOptions?: any): Promise<any> { | ||||
|         return this.courseProvider.invalidateCourseBlocks(courseId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if the handler is enabled on a site level. | ||||
|      * | ||||
|      * @return {boolean} Whether or not the handler is enabled on a site level. | ||||
|      */ | ||||
|     isEnabled(): boolean | Promise<boolean> { | ||||
|         return this.courseProvider.canGetCourseBlocks() && !this.blockDelegate.areBlocksDisabledInCourses(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Whether or not the handler is enabled for a certain course. | ||||
|      * | ||||
|      * @param {number} courseId The course ID. | ||||
|      * @param {any} accessData Access type and data. Default, guest, ... | ||||
|      * @param {any} [navOptions] Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions. | ||||
|      * @param {any} [admOptions] Course admin options for current user. See CoreCoursesProvider.getUserAdministrationOptions. | ||||
|      * @return {boolean|Promise<boolean>} True or promise resolved with true if enabled. | ||||
|      */ | ||||
|     isEnabledForCourse(courseId: number, accessData: any, navOptions?: any, admOptions?: any): boolean | Promise<boolean> { | ||||
|         return this.courseProvider.getCourseBlocks(courseId).then((blocks) => { | ||||
|             return blocks && blocks.length > 0; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the data needed to render the handler. | ||||
|      * | ||||
|      * @param {Injector} injector Injector. | ||||
|      * @param {number} courseId The course ID. | ||||
|      * @return {CoreCourseOptionsHandlerData|Promise<CoreCourseOptionsHandlerData>} Data or promise resolved with the data. | ||||
|      */ | ||||
|     getDisplayData(injector: Injector, courseId: number): CoreCourseOptionsHandlerData | Promise<CoreCourseOptionsHandlerData> { | ||||
|         return { | ||||
|             title: 'core.block.blocks', | ||||
|             class: 'core-course-blocks-handler', | ||||
|             component: CoreBlockCourseBlocksComponent | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Called when a course is downloaded. It should prefetch all the data to be able to see the addon in offline. | ||||
|      * | ||||
|      * @param {any} course The course. | ||||
|      * @return {Promise<any>} Promise resolved when done. | ||||
|      */ | ||||
|     prefetch(course: any): Promise<any> { | ||||
|         return this.courseProvider.getCourseBlocks(course.id); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										59
									
								
								src/core/block/providers/helper.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/core/block/providers/helper.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| // (C) Copyright 2015 Martin Dougiamas
 | ||||
| //
 | ||||
| // 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 { Injectable } from '@angular/core'; | ||||
| import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreBlockDelegate } from '@core/block/providers/delegate'; | ||||
| 
 | ||||
| /** | ||||
|  * Service that provides helper functions for blocks. | ||||
|  */ | ||||
| @Injectable() | ||||
| export class CoreBlockHelperProvider { | ||||
| 
 | ||||
|     constructor(protected courseProvider: CoreCourseProvider, protected blockDelegate: CoreBlockDelegate) {} | ||||
| 
 | ||||
|     /** | ||||
|      * Return if it get course blocks options is enabled for the current site. | ||||
|      * | ||||
|      * @return {boolean} true if enabled, false otherwise. | ||||
|      */ | ||||
|     canGetCourseBlocks(): boolean { | ||||
|         return this.courseProvider.canGetCourseBlocks() && !this.blockDelegate.areBlocksDisabledInCourses(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the list of blocks for the selected course. | ||||
|      * | ||||
|      * @param  {number}       courseId Course ID. | ||||
|      * @return {Promise<any>}          List of supported blocks. | ||||
|      */ | ||||
|     getCourseBlocks(courseId: number): Promise<any> { | ||||
|         const canGetBlocks = this.canGetCourseBlocks(); | ||||
| 
 | ||||
|         if (!canGetBlocks) { | ||||
|             return Promise.resolve([]); | ||||
|         } | ||||
| 
 | ||||
|         return this.courseProvider.getCourseBlocks(courseId).then((blocks) => { | ||||
|             const hasSupportedBlock = this.blockDelegate.hasSupportedBlock(blocks); | ||||
| 
 | ||||
|             if (!hasSupportedBlock) { | ||||
|                 return []; | ||||
|             } | ||||
| 
 | ||||
|             return blocks; | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| @ -18,6 +18,7 @@ import { IonicModule } from 'ionic-angular'; | ||||
| import { TranslateModule } from '@ngx-translate/core'; | ||||
| import { CoreComponentsModule } from '@components/components.module'; | ||||
| import { CoreDirectivesModule } from '@directives/directives.module'; | ||||
| import { CoreBlockComponentsModule } from '@core/block/components/components.module'; | ||||
| import { CoreCourseFormatComponent } from './format/format'; | ||||
| import { CoreCourseModuleComponent } from './module/module'; | ||||
| import { CoreCourseModuleCompletionComponent } from './module-completion/module-completion'; | ||||
| @ -33,6 +34,7 @@ import { CoreCourseUnsupportedModuleComponent } from './unsupported-module/unsup | ||||
|         CoreCourseUnsupportedModuleComponent | ||||
|     ], | ||||
|     imports: [ | ||||
|         CoreBlockComponentsModule, | ||||
|         CommonModule, | ||||
|         IonicModule, | ||||
|         TranslateModule.forChild(), | ||||
|  | ||||
| @ -5,6 +5,8 @@ | ||||
|     </core-context-menu> | ||||
| </core-navbar-buttons> | ||||
| 
 | ||||
| <core-block-course-blocks [courseId]="course.id" [hideBlocks]="selectedSection && selectedSection.id == allSectionsId && canLoadMore" [downloadEnabled]="downloadEnabled"> | ||||
|     <ion-content> | ||||
|         <!-- Default course format. --> | ||||
|         <core-dynamic-component [component]="courseFormatComponent" [data]="data"> | ||||
|             <core-loading [hideUntil]="loaded"> | ||||
| @ -66,6 +68,8 @@ | ||||
|             </ion-buttons> | ||||
| 
 | ||||
|         </core-dynamic-component> | ||||
|     </ion-content> | ||||
| </core-block-course-blocks> | ||||
| 
 | ||||
| <!-- Template to render a section. --> | ||||
| <ng-template #sectionTemplate let-section="section"> | ||||
|  | ||||
| @ -13,7 +13,7 @@ | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { | ||||
|     Component, Input, OnInit, OnChanges, OnDestroy, SimpleChange, Output, EventEmitter, ViewChildren, QueryList, Injector | ||||
|     Component, Input, OnInit, OnChanges, OnDestroy, SimpleChange, Output, EventEmitter, ViewChildren, QueryList, Injector, ViewChild | ||||
| } from '@angular/core'; | ||||
| import { Content, ModalController } from 'ionic-angular'; | ||||
| import { TranslateService } from '@ngx-translate/core'; | ||||
| @ -24,6 +24,7 @@ import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreCourseHelperProvider } from '@core/course/providers/helper'; | ||||
| import { CoreCourseFormatDelegate } from '@core/course/providers/format-delegate'; | ||||
| import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate'; | ||||
| import { CoreBlockCourseBlocksComponent } from '@core/block/components/course-blocks/course-blocks'; | ||||
| import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-component'; | ||||
| 
 | ||||
| /** | ||||
| @ -52,6 +53,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { | ||||
|     @Output() completionChanged?: EventEmitter<any>; // Will emit an event when any module completion changes.
 | ||||
| 
 | ||||
|     @ViewChildren(CoreDynamicComponent) dynamicComponents: QueryList<CoreDynamicComponent>; | ||||
|     @ViewChild(CoreBlockCourseBlocksComponent) courseBlocksComponent: CoreBlockCourseBlocksComponent; | ||||
| 
 | ||||
|     // All the possible component classes.
 | ||||
|     courseFormatComponent: any; | ||||
| @ -420,6 +422,10 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { | ||||
|             promises.push(Promise.resolve(component.callComponentFunction('doRefresh', [refresher, done, afterCompletionChange]))); | ||||
|         }); | ||||
| 
 | ||||
|         promises.push(this.courseBlocksComponent.invalidateBlocks().finally(() => { | ||||
|             return this.courseBlocksComponent.loadContent(); | ||||
|         })); | ||||
| 
 | ||||
|         return Promise.all(promises); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -20,6 +20,8 @@ import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||
| import { CoreTextUtilsProvider } from '@providers/utils/text'; | ||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CoreTabsComponent } from '@components/tabs/tabs'; | ||||
| import { CoreCoursesProvider } from '@core/courses/providers/courses'; | ||||
| import { CoreCourseProvider } from '../../providers/course'; | ||||
| import { CoreCourseHelperProvider } from '../../providers/helper'; | ||||
| import { CoreCourseFormatDelegate } from '../../providers/format-delegate'; | ||||
| @ -28,8 +30,6 @@ import { CoreCourseOptionsDelegate, CoreCourseOptionsHandlerToDisplay, | ||||
|     CoreCourseOptionsMenuHandlerToDisplay } from '../../providers/options-delegate'; | ||||
| import { CoreCourseSyncProvider } from '../../providers/sync'; | ||||
| import { CoreCourseFormatComponent } from '../../components/format/format'; | ||||
| import { CoreCoursesProvider } from '@core/courses/providers/courses'; | ||||
| import { CoreTabsComponent } from '@components/tabs/tabs'; | ||||
| 
 | ||||
| /** | ||||
|  * Page that displays the list of courses the user is enrolled in. | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| <core-block-course-blocks [courseId]="siteHomeId" [downloadEnabled]="downloadEnabled"> | ||||
|     <ion-content> | ||||
|         <core-loading [hideUntil]="dataLoaded"> | ||||
| 
 | ||||
|                 <ion-list> | ||||
|                     <!-- Site home main contents. --> | ||||
|                     <ng-container *ngIf="section && section.hasContent"> | ||||
| @ -21,12 +22,9 @@ | ||||
|                             <core-sitehome-news *ngIf="item == 'news'"></core-sitehome-news> | ||||
|                         </ng-container> | ||||
|                     </ng-container> | ||||
| 
 | ||||
|         <!-- Site home blocks. --> | ||||
|         <ng-container *ngFor="let block of blocks"> | ||||
|             <core-block [block]="block" contextLevel="course" [instanceId]="siteHomeId" [extraData]="{'downloadEnabled': downloadEnabled}"></core-block> | ||||
|         </ng-container> | ||||
|                 </ion-list> | ||||
| 
 | ||||
|     <core-empty-box *ngIf="!hasContent && !hasSupportedBlock" icon="qr-scanner" [message]="'core.course.nocontentavailable' | translate"></core-empty-box> | ||||
|             <core-empty-box *ngIf="!hasContent" icon="qr-scanner" [message]="'core.course.nocontentavailable' | translate"></core-empty-box> | ||||
|         </core-loading> | ||||
|     </ion-content> | ||||
| </core-block-course-blocks> | ||||
|  | ||||
| @ -12,14 +12,13 @@ | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { Component, OnInit, ViewChildren, QueryList, Input } from '@angular/core'; | ||||
| import { Component, OnInit, Input, ViewChild } from '@angular/core'; | ||||
| import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||
| import { CoreCourseProvider } from '@core/course/providers/course'; | ||||
| import { CoreCourseHelperProvider } from '@core/course/providers/helper'; | ||||
| import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate'; | ||||
| import { CoreBlockDelegate } from '@core/block/providers/delegate'; | ||||
| import { CoreBlockComponent } from '@core/block/components/block/block'; | ||||
| import { CoreBlockCourseBlocksComponent } from '@core/block/components/course-blocks/course-blocks'; | ||||
| import { CoreSite } from '@classes/site'; | ||||
| 
 | ||||
| /** | ||||
| @ -30,21 +29,19 @@ import { CoreSite } from '@classes/site'; | ||||
|     templateUrl: 'core-sitehome-index.html', | ||||
| }) | ||||
| export class CoreSiteHomeIndexComponent implements OnInit { | ||||
|     @ViewChildren(CoreBlockComponent) blocksComponents: QueryList<CoreBlockComponent>; | ||||
|     @Input() downloadEnabled: boolean; | ||||
|     @ViewChild(CoreBlockCourseBlocksComponent) courseBlocksComponent: CoreBlockCourseBlocksComponent; | ||||
| 
 | ||||
|     dataLoaded = false; | ||||
|     section: any; | ||||
|     hasContent: boolean; | ||||
|     hasSupportedBlock: boolean; | ||||
|     items: any[] = []; | ||||
|     siteHomeId: number; | ||||
|     currentSite: CoreSite; | ||||
|     blocks = []; | ||||
| 
 | ||||
|     constructor(private domUtils: CoreDomUtilsProvider, sitesProvider: CoreSitesProvider, | ||||
|             private courseProvider: CoreCourseProvider, private courseHelper: CoreCourseHelperProvider, | ||||
|             private prefetchDelegate: CoreCourseModulePrefetchDelegate, private blockDelegate: CoreBlockDelegate) { | ||||
|             private prefetchDelegate: CoreCourseModulePrefetchDelegate) { | ||||
|         this.currentSite = sitesProvider.getCurrentSite(); | ||||
|         this.siteHomeId = this.currentSite.getSiteHomeId(); | ||||
|     } | ||||
| @ -79,19 +76,15 @@ export class CoreSiteHomeIndexComponent implements OnInit { | ||||
|             promises.push(this.prefetchDelegate.invalidateModules(this.section.modules, this.siteHomeId)); | ||||
|         } | ||||
| 
 | ||||
|         if (this.courseProvider.canGetCourseBlocks()) { | ||||
|             promises.push(this.courseProvider.invalidateCourseBlocks(this.siteHomeId)); | ||||
|         } | ||||
| 
 | ||||
|         // Invalidate the blocks.
 | ||||
|         this.blocksComponents.forEach((blockComponent) => { | ||||
|             promises.push(blockComponent.invalidate().catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|             })); | ||||
|         }); | ||||
|         promises.push(this.courseBlocksComponent.invalidateBlocks()); | ||||
| 
 | ||||
|         Promise.all(promises).finally(() => { | ||||
|             this.loadContent().finally(() => { | ||||
|             const p2 = []; | ||||
| 
 | ||||
|             p2.push(this.loadContent()); | ||||
|             p2.push(this.courseBlocksComponent.loadContent()); | ||||
| 
 | ||||
|             return Promise.all(p2).finally(() => { | ||||
|                 refresher.complete(); | ||||
|             }); | ||||
|         }); | ||||
| @ -149,32 +142,6 @@ export class CoreSiteHomeIndexComponent implements OnInit { | ||||
|                     this.currentSite && this.currentSite.getInfo().sitename).catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|             }); | ||||
| 
 | ||||
|             // Get site home blocks.
 | ||||
|             const canGetBlocks = this.courseProvider.canGetCourseBlocks(), | ||||
|                 promise = canGetBlocks ? this.courseProvider.getCourseBlocks(this.siteHomeId) : Promise.reject(null); | ||||
| 
 | ||||
|             return promise.then((blocks) => { | ||||
|                 this.blocks = blocks; | ||||
|                 this.hasSupportedBlock = this.blockDelegate.hasSupportedBlock(blocks); | ||||
| 
 | ||||
|             }).catch((error) => { | ||||
|                 if (canGetBlocks) { | ||||
|                     this.domUtils.showErrorModal(error); | ||||
|                 } | ||||
|                 this.blocks = []; | ||||
| 
 | ||||
|                 // Cannot get the blocks, just show site main menu if needed.
 | ||||
|                 const section = sections.find((section) => section.section == 0); | ||||
|                 if (section && this.courseHelper.sectionHasContent(section)) { | ||||
|                     this.blocks.push({ | ||||
|                         name: 'site_main_menu' | ||||
|                     }); | ||||
|                     this.hasSupportedBlock = true; | ||||
|                 } else { | ||||
|                     this.hasSupportedBlock = false; | ||||
|                 } | ||||
|             }); | ||||
|         }).catch((error) => { | ||||
|             this.domUtils.showErrorModalDefault(error, 'core.course.couldnotloadsectioncontent', true); | ||||
|         }); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user