MOBILE-2310 course: Implement unsupported module page

main
Dani Palou 2018-01-02 15:30:50 +01:00
parent 2e73942083
commit cbc9bc715c
11 changed files with 217 additions and 14 deletions

View File

@ -226,6 +226,12 @@ core-format-text, *[core-format-text] {
.badge {
position: initial !important;
}
// Images in ion-card have width 100% and display block. Remove that when the image is in core-format-text.
img {
width: initial;
display: inline;
}
}
// Message item.

View File

@ -21,12 +21,14 @@ import { CoreDirectivesModule } from '../../../directives/directives.module';
import { CoreCourseFormatComponent } from './format/format';
import { CoreCourseModuleComponent } from './module/module';
import { CoreCourseModuleCompletionComponent } from './module-completion/module-completion';
import { CoreCourseModuleDescriptionComponent } from './module-description/module-description';
@NgModule({
declarations: [
CoreCourseFormatComponent,
CoreCourseModuleComponent,
CoreCourseModuleCompletionComponent
CoreCourseModuleCompletionComponent,
CoreCourseModuleDescriptionComponent
],
imports: [
CommonModule,
@ -40,7 +42,8 @@ import { CoreCourseModuleCompletionComponent } from './module-completion/module-
exports: [
CoreCourseFormatComponent,
CoreCourseModuleComponent,
CoreCourseModuleCompletionComponent
CoreCourseModuleCompletionComponent,
CoreCourseModuleDescriptionComponent
]
})
export class CoreCourseComponentsModule {}

View File

@ -0,0 +1,6 @@
<ion-card *ngIf="description">
<ion-item text-wrap>
<core-format-text [text]="description" [component]="component" [componentId]="componentId" [maxHeight]="showFull && showFull !== 'false' ? 0 : 120" fullOnClick="true"></core-format-text>
<ion-note *ngIf="note" item-end>{{ note }}</ion-note>
</ion-item>
</ion-card>

View File

@ -0,0 +1,45 @@
// (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 { Component, Input } from '@angular/core';
/**
* Component to display the description of a module.
*
* This directive is meant to display a module description in a similar way throughout all the app.
*
* You can add a note at the right side of the description by using the 'note' attribute.
*
* You can also pass a component and componentId to be used in format-text.
*
* Module descriptions are shortened by default, allowing the user to see the full description by clicking in it.
* If you want the whole description to be shown you can use the 'showFull' attribute.
*
* Example usage:
*
* <core-course-module-description [description]="myDescription"></core-course-module-description
*/
@Component({
selector: 'core-course-module-description',
templateUrl: 'module-description.html'
})
export class CoreCourseModuleDescriptionComponent {
@Input() description: string; // The description to display.
@Input() note?: string; // A note to display along with the description.
@Input() component?: string; // Component for format text directive.
@Input() componentId?: string|number; // Component ID to use in conjunction with the component.
@Input() showFull?: string|boolean; // Whether to always display the full description.
constructor() {}
}

View File

@ -1,17 +1,17 @@
<a *ngIf="module && module.visibleoncoursepage !== 0" ion-item text-wrap id="mm-course-module-{{module.id}}" class="mm-course-module-handler {{module.handlerData.class}}" (click)="moduleClicked($event)" [ngClass]="{'item-media': module.handlerData.icon, 'mm-not-clickable': !module.handlerData.action || !module.uservisible === false, 'item-dimmed': module.visible === 0 || module.uservisible === false}" title="{{ module.handlerData.title }}">
<a *ngIf="module && module.visibleoncoursepage !== 0" ion-item text-wrap id="core-course-module-{{module.id}}" class="core-course-module-handler {{module.handlerData.class}}" (click)="moduleClicked($event)" [ngClass]="{'item-media': module.handlerData.icon, 'core-not-clickable': !module.handlerData.action || !module.uservisible === false, 'item-dimmed': module.visible === 0 || module.uservisible === false}" title="{{ module.handlerData.title }}">
<img item-start *ngIf="module.handlerData.icon" [src]="module.handlerData.icon" alt="" role="presentation">
<core-format-text [text]="module.handlerData.title"></core-format-text>
<div item-end *ngIf="module.uservisible !== false && ((module.handlerData.buttons && module.handlerData.buttons.length > 0) || spinner || module.completionstatus)" class="buttons mm-module-buttons" [ngClass]="{'mm-button-completion': module.completionstatus}">
<div item-end *ngIf="module.uservisible !== false && ((module.handlerData.buttons && module.handlerData.buttons.length > 0) || spinner || module.completionstatus)" class="buttons core-module-buttons" [ngClass]="{'core-button-completion': module.completionstatus}">
<core-course-module-completion *ngIf="module.completionstatus" [completion]="module.completionstatus" [moduleName]="module.name" (completionChanged)="completionChanged.emit()"></core-course-module-completion>
<button ion-button icon-only clear *ngFor="let button of module.handlerData.buttons" [hidden]="button.hidden" (click)="button.action($event, module, courseId)" class="mm-animate-show-hide" [attr.aria-label]="button.label | translate">
<button ion-button icon-only clear *ngFor="let button of module.handlerData.buttons" [hidden]="button.hidden" (click)="buttonClicked($event, button)" class="core-animate-show-hide" [attr.aria-label]="button.label | translate">
<ion-icon [name]="button.icon" [ios]="button.iosIcon || ''" [md]="button.mdIcon || ''"></ion-icon>
</button>
<ion-spinner *ngIf="module.handlerData.spinner" class="mm-animate-show-hide"></ion-spinner>
<ion-spinner *ngIf="module.handlerData.spinner" class="core-animate-show-hide"></ion-spinner>
</div>
<div *ngIf="module.visible === 0 || module.availabilityinfo">

View File

@ -13,6 +13,8 @@
// limitations under the License.
import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
import { NavController } from 'ionic-angular';
import { CoreCourseModuleHandlerButton } from '../../providers/module-delegate';
/**
* Component to display a module entry in a list of modules.
@ -30,7 +32,7 @@ export class CoreCourseModuleComponent implements OnInit {
@Input() courseId: number; // The course the module belongs to.
@Output() completionChanged?: EventEmitter<void>; // Will emit an event when the module completion changes.
constructor() {
constructor(private navCtrl: NavController) {
this.completionChanged = new EventEmitter();
}
@ -51,7 +53,19 @@ export class CoreCourseModuleComponent implements OnInit {
*/
moduleClicked(event: Event) {
if (this.module.uservisible !== false && this.module.handlerData.action) {
this.module.handlerData.action(event, this.module, this.courseId);
this.module.handlerData.action(event, this.navCtrl, this.module, this.courseId);
}
}
/**
* Function called when a button is clicked.
*
* @param {Event} event Click event.
* @param {CoreCourseModuleHandlerButton} button The clicked button.
*/
buttonClicked(event: Event, button: CoreCourseModuleHandlerButton) {
if (button && button.action) {
button.action(event, this.navCtrl, this.module, this.courseId);
}
}
}

View File

@ -0,0 +1,30 @@
<ion-header>
<ion-navbar>
<ion-title><core-format-text [text]="module.name"></core-format-text></ion-title>
<ion-buttons end>
<core-context-menu>
<core-context-menu-item [priority]="900" *ngIf="module.url" [href]="module.url" [content]="'core.openinbrowser' | translate" [iconAction]="'open'"></core-context-menu-item>
<core-context-menu-item [priority]="800" *ngIf="module.description" [content]="'core.moduleintro' | translate" (action)="expandDescription()" [iconAction]="'arrow-forward'"></core-context-menu-item>
</core-context-menu>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content padding>
<core-course-module-description [description]="module.description"></core-course-module-description>
<h2 *ngIf="!isDisabledInSite && isSupportedByTheApp">{{ 'core.whoops' | translate }}</h2>
<h2 *ngIf="isDisabledInSite || !isSupportedByTheApp">{{ 'core.uhoh' | translate }}</h2>
<p class="core-big" *ngIf="isDisabledInSite">{{ 'core.course.activitydisabled' | translate }}</p>
<p class="core-big" *ngIf="!isDisabledInSite && isSupportedByTheApp">{{ 'core.course.activitynotyetviewablesiteupgradeneeded' | translate }}</p>
<p class="core-big" *ngIf="!isDisabledInSite && !isSupportedByTheApp">{{ 'core.course.activitynotyetviewableremoteaddon' | translate }}</p>
<p *ngIf="isDisabledInSite || !isSupportedByTheApp"><strong>{{ 'core.course.askadmintosupport' | translate }}</strong></p>
<div *ngIf="module.url">
<p><strong>{{ 'core.course.useactivityonbrowser' | translate }}</strong></p>
<a ion-button block icon-end [href]="module.url" core-link>
{{ 'core.openinbrowser' | translate }}
<ion-icon name="open"></ion-icon>
</a>
</div>
</ion-content>

View File

@ -0,0 +1,35 @@
// (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 { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { CoreCourseUnsupportedModulePage } from './unsupported-module';
import { CoreComponentsModule } from '../../../../components/components.module';
import { CoreDirectivesModule } from '../../../../directives/directives.module';
import { CoreCourseComponentsModule } from '../../components/components.module';
@NgModule({
declarations: [
CoreCourseUnsupportedModulePage,
],
imports: [
CoreComponentsModule,
CoreDirectivesModule,
CoreCourseComponentsModule,
IonicPageModule.forChild(CoreCourseUnsupportedModulePage),
TranslateModule.forChild()
],
})
export class CoreCourseUnsupportedModulePageModule {}

View File

@ -0,0 +1,57 @@
// (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 { Component } from '@angular/core';
import { IonicPage, NavParams } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core';
import { CoreTextUtilsProvider } from '../../../../providers/utils/text';
import { CoreCourseProvider } from '../../providers/course';
import { CoreCourseModuleDelegate } from '../../providers/module-delegate';
/**
* Page that displays info about an unsupported module.
*/
@IonicPage({segment: 'core-course-unsupported-module'})
@Component({
selector: 'page-core-course-unsupported-module',
templateUrl: 'unsupported-module.html',
})
export class CoreCourseUnsupportedModulePage {
module: any;
isDisabledInSite: boolean;
isSupportedByTheApp: boolean;
moduleName: string;
constructor(navParams: NavParams, private translate: TranslateService, private textUtils: CoreTextUtilsProvider,
private moduleDelegate: CoreCourseModuleDelegate, private courseProvider: CoreCourseProvider) {
this.module = navParams.get('module') || {};
}
/**
* View loaded.
*/
ionViewDidLoad() {
this.isDisabledInSite = this.moduleDelegate.isModuleDisabledInSite(this.module.modname);
this.isSupportedByTheApp = this.moduleDelegate.hasHandler(this.module.modname);
this.moduleName = this.courseProvider.translateModuleName(this.module.modname);
}
/**
* Expand the description.
*/
expandDescription() {
this.textUtils.expandText(this.translate.instant('core.description'), this.module.description, false);
}
}

View File

@ -13,6 +13,7 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { NavController } from 'ionic-angular';
import { CoreEventsProvider } from '../../../providers/events';
import { CoreLoggerProvider } from '../../../providers/logger';
import { CoreSitesProvider } from '../../../providers/sites';
@ -91,10 +92,11 @@ export interface CoreCourseModuleHandlerData {
* Action to perform when the module is clicked.
*
* @param {Event} event The click event.
* @param {NavController} navCtrl NavController instance.
* @param {any} module The module object.
* @param {number} courseId The course ID.
*/
action?(event: Event, module: any, courseId: number) : void;
action?(event: Event, navCtrl: NavController, module: any, courseId: number) : void;
};
/**
@ -135,10 +137,11 @@ export interface CoreCourseModuleHandlerButton {
* Action to perform when the button is clicked.
*
* @param {Event} event The click event.
* @param {NavController} navCtrl NavController instance.
* @param {any} module The module object.
* @param {number} courseId The course ID.
*/
action?(event: Event, module: any, courseId: number) : void;
action(event: Event, navCtrl: NavController, module: any, courseId: number) : void;
};
/**
@ -179,10 +182,11 @@ export class CoreCourseModuleDelegate {
icon: this.courseProvider.getModuleIconSrc(module.modname),
title: module.name,
class: 'core-course-default-handler core-course-module-' + module.modname + '-handler',
action: (event: Event, module: any, courseId: number) => {
action: (event: Event, navCtrl: NavController, module: any, courseId: number) => {
event.preventDefault();
event.stopPropagation();
// @todo: Default content.
navCtrl.push('CoreCourseUnsupportedModulePage', {module: module});
}
};

View File

@ -171,9 +171,12 @@ export class CoreFormatTextDirective implements OnChanges {
// If cannot calculate height, shorten always.
if (!height || height > this.maxHeight) {
let expandInFullview = this.utils.isTrueOrOne(this.fullOnClick) || false;
let expandInFullview = this.utils.isTrueOrOne(this.fullOnClick) || false,
showMoreDiv = document.createElement('div');
this.element.innerHTML += '<div class="core-show-more">' + this.translate.instant('core.showmore') + '</div>';
showMoreDiv.classList.add('core-show-more');
showMoreDiv.innerHTML = this.translate.instant('core.showmore');
this.element.appendChild(showMoreDiv);
if (expandInFullview) {
this.element.classList.add('core-expand-in-fullview');