MOBILE-3025 blocks: Show blocks on sidebar
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>
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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,8 +5,10 @@
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Default course format. -->
|
<core-block-course-blocks [courseId]="course.id" [hideBlocks]="selectedSection && selectedSection.id == allSectionsId && canLoadMore" [downloadEnabled]="downloadEnabled">
|
||||||
<core-dynamic-component [component]="courseFormatComponent" [data]="data">
|
<ion-content>
|
||||||
|
<!-- Default course format. -->
|
||||||
|
<core-dynamic-component [component]="courseFormatComponent" [data]="data">
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<!-- Section selector. -->
|
<!-- Section selector. -->
|
||||||
<core-dynamic-component [component]="sectionSelectorComponent" [data]="data">
|
<core-dynamic-component [component]="sectionSelectorComponent" [data]="data">
|
||||||
|
@ -65,7 +67,9 @@
|
||||||
</button>
|
</button>
|
||||||
</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-loading [hideUntil]="dataLoaded">
|
<core-block-course-blocks [courseId]="siteHomeId" [downloadEnabled]="downloadEnabled">
|
||||||
|
<ion-content>
|
||||||
|
<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…
Reference in New Issue