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; |         background-color: $ion-tabs-badge-color; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     &[tabsplacement="bottom"] { | ||||||
|  |         .ion-page > ion-content > .scroll-content { | ||||||
|  |             margin-bottom: $navbar-md-height !important; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     &[tabsplacement="side"] { |     &[tabsplacement="side"] { | ||||||
|         .tabbar { |         .tabbar { | ||||||
|             @include float(start); |             @include float(start); | ||||||
| @ -53,6 +59,10 @@ ion-app.app-root core-ion-tabs { | |||||||
|                 position: relative; |                 position: relative; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         .scroll-content, .fixed-content { | ||||||
|  |             margin-bottom: 0 !important; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -14,9 +14,8 @@ | |||||||
| 
 | 
 | ||||||
| import { NgModule } from '@angular/core'; | import { NgModule } from '@angular/core'; | ||||||
| import { CoreBlockDelegate } from './providers/delegate'; | import { CoreBlockDelegate } from './providers/delegate'; | ||||||
|  | import { CoreBlockHelperProvider } from './providers/helper'; | ||||||
| import { CoreBlockDefaultHandler } from './providers/default-block-handler'; | 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'; | import { CoreBlockComponentsModule } from './components/components.module'; | ||||||
| 
 | 
 | ||||||
| // List of providers (without handlers).
 | // List of providers (without handlers).
 | ||||||
| @ -31,14 +30,10 @@ export const CORE_BLOCK_PROVIDERS: any[] = [ | |||||||
|     ], |     ], | ||||||
|     providers: [ |     providers: [ | ||||||
|         CoreBlockDelegate, |         CoreBlockDelegate, | ||||||
|         CoreBlockDefaultHandler, |         CoreBlockHelperProvider, | ||||||
|         CoreBlockCourseBlocksCourseOptionHandler |         CoreBlockDefaultHandler | ||||||
|     ], |     ], | ||||||
|     exports: [] |     exports: [] | ||||||
| }) | }) | ||||||
| export class CoreBlockModule { | export class CoreBlockModule { | ||||||
|     constructor(courseOptionHandler: CoreBlockCourseBlocksCourseOptionHandler, |  | ||||||
|             courseOptionsDelegate: CoreCourseOptionsDelegate) { |  | ||||||
|         courseOptionsDelegate.registerHandler(courseOptionHandler); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,15 +1,14 @@ | |||||||
| <ion-content> | <div class="core-course-blocks-content"> | ||||||
|     <ion-refresher [enabled]="dataLoaded" (ionRefresh)="doRefresh($event)"> |     <ng-content></ng-content> | ||||||
|         <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content> | </div> | ||||||
|     </ion-refresher> | 
 | ||||||
|  | <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"> |     <core-loading [hideUntil]="dataLoaded" class="core-loading-center"> | ||||||
|         <ion-list *ngIf="hasSupportedBlock"> |         <ion-list> | ||||||
|             <!-- Course blocks. --> |             <!-- Course blocks. --> | ||||||
|             <ng-container *ngFor="let block of 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> |             </ng-container> | ||||||
|         </ion-list> |         </ion-list> | ||||||
| 
 |  | ||||||
|         <core-empty-box *ngIf="!hasSupportedBlock" icon="qr-scanner" [message]="'core.course.nocontentavailable' | translate"></core-empty-box> |  | ||||||
|     </core-loading> |     </core-loading> | ||||||
| </ion-content> | </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
 | // See the License for the specific language governing permissions and
 | ||||||
| // limitations under the License.
 | // 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 { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||||
| import { CoreBlockComponent } from '../block/block'; |  | ||||||
| import { CoreBlockDelegate } from '../../providers/delegate'; |  | ||||||
| import { CoreCourseProvider } from '@core/course/providers/course'; | 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. |  * Component that displays the list of course blocks. | ||||||
| @ -28,16 +29,22 @@ import { CoreCourseProvider } from '@core/course/providers/course'; | |||||||
| export class CoreBlockCourseBlocksComponent implements OnInit { | export class CoreBlockCourseBlocksComponent implements OnInit { | ||||||
| 
 | 
 | ||||||
|     @Input() courseId: number; |     @Input() courseId: number; | ||||||
|  |     @Input() hideBlocks = false; | ||||||
|  |     @Input() downloadEnabled: boolean; | ||||||
| 
 | 
 | ||||||
|     @ViewChildren(CoreBlockComponent) blocksComponents: QueryList<CoreBlockComponent>; |     @ViewChildren(CoreBlockComponent) blocksComponents: QueryList<CoreBlockComponent>; | ||||||
| 
 | 
 | ||||||
|     dataLoaded = false; |     dataLoaded = false; | ||||||
|     hasContent: boolean; |  | ||||||
|     hasSupportedBlock: boolean; |  | ||||||
|     blocks = []; |     blocks = []; | ||||||
| 
 | 
 | ||||||
|  |     protected element: HTMLElement; | ||||||
|  |     protected parentContent: HTMLElement; | ||||||
|  | 
 | ||||||
|     constructor(private domUtils: CoreDomUtilsProvider, private courseProvider: CoreCourseProvider, |     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 = []; |         const promises = []; | ||||||
| 
 | 
 | ||||||
|         if (this.courseProvider.canGetCourseBlocks()) { |         if (this.blockHelper.canGetCourseBlocks()) { | ||||||
|             promises.push(this.courseProvider.invalidateCourseBlocks(this.courseId)); |             promises.push(this.courseProvider.invalidateCourseBlocks(this.courseId)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -68,11 +75,7 @@ export class CoreBlockCourseBlocksComponent implements OnInit { | |||||||
|             })); |             })); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         Promise.all(promises).finally(() => { |         return Promise.all(promises); | ||||||
|             this.loadContent().finally(() => { |  | ||||||
|                 refresher.complete(); |  | ||||||
|             }); |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -80,21 +83,24 @@ export class CoreBlockCourseBlocksComponent implements OnInit { | |||||||
|      * |      * | ||||||
|      * @return {Promise<any>} Promise resolved when done. |      * @return {Promise<any>} Promise resolved when done. | ||||||
|      */ |      */ | ||||||
|     protected loadContent(): Promise<any> { |     loadContent(): Promise<any> { | ||||||
|         // Get site home blocks.
 |         return this.blockHelper.getCourseBlocks(this.courseId).then((blocks) => { | ||||||
|         const canGetBlocks = this.courseProvider.canGetCourseBlocks(), |  | ||||||
|             promise = canGetBlocks ? this.courseProvider.getCourseBlocks(this.courseId) : Promise.reject(null); |  | ||||||
| 
 |  | ||||||
|         return promise.then((blocks) => { |  | ||||||
|             this.blocks = blocks; |             this.blocks = blocks; | ||||||
|             this.hasSupportedBlock = this.blockDelegate.hasSupportedBlock(blocks); |  | ||||||
| 
 |  | ||||||
|         }).catch((error) => { |         }).catch((error) => { | ||||||
|             if (canGetBlocks) { |  | ||||||
|             this.domUtils.showErrorModal(error); |             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)"> | <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> | </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 { TranslateModule } from '@ngx-translate/core'; | ||||||
| import { CoreComponentsModule } from '@components/components.module'; | import { CoreComponentsModule } from '@components/components.module'; | ||||||
| import { CoreDirectivesModule } from '@directives/directives.module'; | import { CoreDirectivesModule } from '@directives/directives.module'; | ||||||
|  | import { CoreBlockComponentsModule } from '@core/block/components/components.module'; | ||||||
| import { CoreCourseFormatComponent } from './format/format'; | import { CoreCourseFormatComponent } from './format/format'; | ||||||
| import { CoreCourseModuleComponent } from './module/module'; | import { CoreCourseModuleComponent } from './module/module'; | ||||||
| import { CoreCourseModuleCompletionComponent } from './module-completion/module-completion'; | import { CoreCourseModuleCompletionComponent } from './module-completion/module-completion'; | ||||||
| @ -33,6 +34,7 @@ import { CoreCourseUnsupportedModuleComponent } from './unsupported-module/unsup | |||||||
|         CoreCourseUnsupportedModuleComponent |         CoreCourseUnsupportedModuleComponent | ||||||
|     ], |     ], | ||||||
|     imports: [ |     imports: [ | ||||||
|  |         CoreBlockComponentsModule, | ||||||
|         CommonModule, |         CommonModule, | ||||||
|         IonicModule, |         IonicModule, | ||||||
|         TranslateModule.forChild(), |         TranslateModule.forChild(), | ||||||
|  | |||||||
| @ -5,6 +5,8 @@ | |||||||
|     </core-context-menu> |     </core-context-menu> | ||||||
| </core-navbar-buttons> | </core-navbar-buttons> | ||||||
| 
 | 
 | ||||||
|  | <core-block-course-blocks [courseId]="course.id" [hideBlocks]="selectedSection && selectedSection.id == allSectionsId && canLoadMore" [downloadEnabled]="downloadEnabled"> | ||||||
|  |     <ion-content> | ||||||
|         <!-- Default course format. --> |         <!-- Default course format. --> | ||||||
|         <core-dynamic-component [component]="courseFormatComponent" [data]="data"> |         <core-dynamic-component [component]="courseFormatComponent" [data]="data"> | ||||||
|             <core-loading [hideUntil]="loaded"> |             <core-loading [hideUntil]="loaded"> | ||||||
| @ -66,6 +68,8 @@ | |||||||
|             </ion-buttons> |             </ion-buttons> | ||||||
| 
 | 
 | ||||||
|         </core-dynamic-component> |         </core-dynamic-component> | ||||||
|  |     </ion-content> | ||||||
|  | </core-block-course-blocks> | ||||||
| 
 | 
 | ||||||
| <!-- Template to render a section. --> | <!-- Template to render a section. --> | ||||||
| <ng-template #sectionTemplate let-section="section"> | <ng-template #sectionTemplate let-section="section"> | ||||||
|  | |||||||
| @ -13,7 +13,7 @@ | |||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { | 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'; | } from '@angular/core'; | ||||||
| import { Content, ModalController } from 'ionic-angular'; | import { Content, ModalController } from 'ionic-angular'; | ||||||
| import { TranslateService } from '@ngx-translate/core'; | 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 { CoreCourseHelperProvider } from '@core/course/providers/helper'; | ||||||
| import { CoreCourseFormatDelegate } from '@core/course/providers/format-delegate'; | import { CoreCourseFormatDelegate } from '@core/course/providers/format-delegate'; | ||||||
| import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-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'; | 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.
 |     @Output() completionChanged?: EventEmitter<any>; // Will emit an event when any module completion changes.
 | ||||||
| 
 | 
 | ||||||
|     @ViewChildren(CoreDynamicComponent) dynamicComponents: QueryList<CoreDynamicComponent>; |     @ViewChildren(CoreDynamicComponent) dynamicComponents: QueryList<CoreDynamicComponent>; | ||||||
|  |     @ViewChild(CoreBlockCourseBlocksComponent) courseBlocksComponent: CoreBlockCourseBlocksComponent; | ||||||
| 
 | 
 | ||||||
|     // All the possible component classes.
 |     // All the possible component classes.
 | ||||||
|     courseFormatComponent: any; |     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(Promise.resolve(component.callComponentFunction('doRefresh', [refresher, done, afterCompletionChange]))); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  |         promises.push(this.courseBlocksComponent.invalidateBlocks().finally(() => { | ||||||
|  |             return this.courseBlocksComponent.loadContent(); | ||||||
|  |         })); | ||||||
|  | 
 | ||||||
|         return Promise.all(promises); |         return Promise.all(promises); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -20,6 +20,8 @@ import { CoreSitesProvider } from '@providers/sites'; | |||||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||||
| import { CoreTextUtilsProvider } from '@providers/utils/text'; | import { CoreTextUtilsProvider } from '@providers/utils/text'; | ||||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | 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 { CoreCourseProvider } from '../../providers/course'; | ||||||
| import { CoreCourseHelperProvider } from '../../providers/helper'; | import { CoreCourseHelperProvider } from '../../providers/helper'; | ||||||
| import { CoreCourseFormatDelegate } from '../../providers/format-delegate'; | import { CoreCourseFormatDelegate } from '../../providers/format-delegate'; | ||||||
| @ -28,8 +30,6 @@ import { CoreCourseOptionsDelegate, CoreCourseOptionsHandlerToDisplay, | |||||||
|     CoreCourseOptionsMenuHandlerToDisplay } from '../../providers/options-delegate'; |     CoreCourseOptionsMenuHandlerToDisplay } from '../../providers/options-delegate'; | ||||||
| import { CoreCourseSyncProvider } from '../../providers/sync'; | import { CoreCourseSyncProvider } from '../../providers/sync'; | ||||||
| import { CoreCourseFormatComponent } from '../../components/format/format'; | 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. |  * 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"> |         <core-loading [hideUntil]="dataLoaded"> | ||||||
| 
 |  | ||||||
|                 <ion-list> |                 <ion-list> | ||||||
|                     <!-- Site home main contents. --> |                     <!-- Site home main contents. --> | ||||||
|                     <ng-container *ngIf="section && section.hasContent"> |                     <ng-container *ngIf="section && section.hasContent"> | ||||||
| @ -21,12 +22,9 @@ | |||||||
|                             <core-sitehome-news *ngIf="item == 'news'"></core-sitehome-news> |                             <core-sitehome-news *ngIf="item == 'news'"></core-sitehome-news> | ||||||
|                         </ng-container> |                         </ng-container> | ||||||
|                     </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> |                 </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> |         </core-loading> | ||||||
|  |     </ion-content> | ||||||
|  | </core-block-course-blocks> | ||||||
|  | |||||||
| @ -12,14 +12,13 @@ | |||||||
| // See the License for the specific language governing permissions and
 | // See the License for the specific language governing permissions and
 | ||||||
| // limitations under the License.
 | // 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 { CoreSitesProvider } from '@providers/sites'; | ||||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||||
| import { CoreCourseProvider } from '@core/course/providers/course'; | import { CoreCourseProvider } from '@core/course/providers/course'; | ||||||
| import { CoreCourseHelperProvider } from '@core/course/providers/helper'; | import { CoreCourseHelperProvider } from '@core/course/providers/helper'; | ||||||
| import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate'; | import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate'; | ||||||
| import { CoreBlockDelegate } from '@core/block/providers/delegate'; | import { CoreBlockCourseBlocksComponent } from '@core/block/components/course-blocks/course-blocks'; | ||||||
| import { CoreBlockComponent } from '@core/block/components/block/block'; |  | ||||||
| import { CoreSite } from '@classes/site'; | import { CoreSite } from '@classes/site'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -30,21 +29,19 @@ import { CoreSite } from '@classes/site'; | |||||||
|     templateUrl: 'core-sitehome-index.html', |     templateUrl: 'core-sitehome-index.html', | ||||||
| }) | }) | ||||||
| export class CoreSiteHomeIndexComponent implements OnInit { | export class CoreSiteHomeIndexComponent implements OnInit { | ||||||
|     @ViewChildren(CoreBlockComponent) blocksComponents: QueryList<CoreBlockComponent>; |  | ||||||
|     @Input() downloadEnabled: boolean; |     @Input() downloadEnabled: boolean; | ||||||
|  |     @ViewChild(CoreBlockCourseBlocksComponent) courseBlocksComponent: CoreBlockCourseBlocksComponent; | ||||||
| 
 | 
 | ||||||
|     dataLoaded = false; |     dataLoaded = false; | ||||||
|     section: any; |     section: any; | ||||||
|     hasContent: boolean; |     hasContent: boolean; | ||||||
|     hasSupportedBlock: boolean; |  | ||||||
|     items: any[] = []; |     items: any[] = []; | ||||||
|     siteHomeId: number; |     siteHomeId: number; | ||||||
|     currentSite: CoreSite; |     currentSite: CoreSite; | ||||||
|     blocks = []; |  | ||||||
| 
 | 
 | ||||||
|     constructor(private domUtils: CoreDomUtilsProvider, sitesProvider: CoreSitesProvider, |     constructor(private domUtils: CoreDomUtilsProvider, sitesProvider: CoreSitesProvider, | ||||||
|             private courseProvider: CoreCourseProvider, private courseHelper: CoreCourseHelperProvider, |             private courseProvider: CoreCourseProvider, private courseHelper: CoreCourseHelperProvider, | ||||||
|             private prefetchDelegate: CoreCourseModulePrefetchDelegate, private blockDelegate: CoreBlockDelegate) { |             private prefetchDelegate: CoreCourseModulePrefetchDelegate) { | ||||||
|         this.currentSite = sitesProvider.getCurrentSite(); |         this.currentSite = sitesProvider.getCurrentSite(); | ||||||
|         this.siteHomeId = this.currentSite.getSiteHomeId(); |         this.siteHomeId = this.currentSite.getSiteHomeId(); | ||||||
|     } |     } | ||||||
| @ -79,19 +76,15 @@ export class CoreSiteHomeIndexComponent implements OnInit { | |||||||
|             promises.push(this.prefetchDelegate.invalidateModules(this.section.modules, this.siteHomeId)); |             promises.push(this.prefetchDelegate.invalidateModules(this.section.modules, this.siteHomeId)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (this.courseProvider.canGetCourseBlocks()) { |         promises.push(this.courseBlocksComponent.invalidateBlocks()); | ||||||
|             promises.push(this.courseProvider.invalidateCourseBlocks(this.siteHomeId)); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // Invalidate the blocks.
 |  | ||||||
|         this.blocksComponents.forEach((blockComponent) => { |  | ||||||
|             promises.push(blockComponent.invalidate().catch(() => { |  | ||||||
|                 // Ignore errors.
 |  | ||||||
|             })); |  | ||||||
|         }); |  | ||||||
| 
 | 
 | ||||||
|         Promise.all(promises).finally(() => { |         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(); |                 refresher.complete(); | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
| @ -149,32 +142,6 @@ export class CoreSiteHomeIndexComponent implements OnInit { | |||||||
|                     this.currentSite && this.currentSite.getInfo().sitename).catch(() => { |                     this.currentSite && this.currentSite.getInfo().sitename).catch(() => { | ||||||
|                 // Ignore errors.
 |                 // 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) => { |         }).catch((error) => { | ||||||
|             this.domUtils.showErrorModalDefault(error, 'core.course.couldnotloadsectioncontent', true); |             this.domUtils.showErrorModalDefault(error, 'core.course.couldnotloadsectioncontent', true); | ||||||
|         }); |         }); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user