MOBILE-3099 module: Add preview page to show restricted activities
parent
132007b207
commit
007835b6b8
|
@ -19,7 +19,7 @@ import { CoreModuleHandlerBase } from '@features/course/classes/module-base-hand
|
|||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreCourseModule } from '@features/course/services/course-helper';
|
||||
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate';
|
||||
import { CoreNavigationOptions, CoreNavigator } from '@services/navigator';
|
||||
import { CoreNavigationOptions } from '@services/navigator';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { makeSingleton } from '@singletons';
|
||||
|
@ -90,12 +90,7 @@ export class AddonModUrlModuleHandlerService extends CoreModuleHandlerBase imple
|
|||
if (shouldOpen) {
|
||||
openUrl(module, courseId);
|
||||
} else {
|
||||
options = options || {};
|
||||
options.params = options.params || {};
|
||||
Object.assign(options.params, { module });
|
||||
const routeParams = '/' + courseId + '/' + module.id;
|
||||
|
||||
CoreNavigator.navigateToSitePath(AddonModUrlModuleHandlerService.PAGE_NAME + routeParams, options);
|
||||
this.openActivityPage(module, courseId, options);
|
||||
}
|
||||
} finally {
|
||||
modal.dismiss();
|
||||
|
|
|
@ -51,14 +51,31 @@ export class CoreModuleHandlerBase implements Partial<CoreCourseModuleHandler> {
|
|||
courseId: number,
|
||||
options?: CoreNavigationOptions,
|
||||
): Promise<void> => {
|
||||
options = options || {};
|
||||
options.params = options.params || {};
|
||||
Object.assign(options.params, { module });
|
||||
const routeParams = '/' + courseId + '/' + module.id;
|
||||
|
||||
await CoreNavigator.navigateToSitePath(this.pageName + routeParams, options);
|
||||
await this.openActivityPage(module, courseId, options);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the activity page.
|
||||
*
|
||||
* @param module The module object.
|
||||
* @param courseId The course ID.
|
||||
* @param options Options for the navigation.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
async openActivityPage(module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions): Promise<void> {
|
||||
if (!CoreCourse.moduleHasView(module)) {
|
||||
return;
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
options.params = options.params || {};
|
||||
Object.assign(options.params, { module });
|
||||
|
||||
const routeParams = '/' + courseId + '/' + module.id;
|
||||
|
||||
await CoreNavigator.navigateToSitePath(this.pageName + routeParams, options);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,24 +13,25 @@
|
|||
<ion-item class="ion-text-wrap" *ngIf="description" lines="none">
|
||||
<ion-label>
|
||||
<core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module"
|
||||
[contextInstanceId]="module.id" [courseId]="courseId" [maxHeight]="120">
|
||||
[contextInstanceId]="module.id" [courseId]="courseId" [maxHeight]="expandDescription ? null : 120">
|
||||
</core-format-text>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ng-content select="[description]"></ng-content>
|
||||
<ion-item class="ion-text-wrap" lines="none" *ngIf="showCompletion && (module.dates?.length || module.completiondata)">
|
||||
<ion-item class="ion-text-wrap" lines="none" *ngIf="showCompletion && (module.dates?.length ||
|
||||
(module.completiondata && (module.completiondata.isautomatic || showManualCompletion) && module.uservisible))">
|
||||
<ion-label>
|
||||
<!-- Activity dates. -->
|
||||
<div *ngIf="module.dates && module.dates.length" class="core-module-dates">
|
||||
<div *ngIf="module.dates?.length" class="core-module-dates">
|
||||
<p *ngFor="let date of module.dates">
|
||||
<strong>{{ date.label }}</strong> {{ date.timestamp * 1000 | coreFormatDate:'strftimedatetime' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Module completion. -->
|
||||
<core-course-module-completion *ngIf="module.completiondata" [completion]="module.completiondata" [moduleName]="module.name"
|
||||
[moduleId]="module.id" [showCompletionConditions]="true" [showManualCompletion]="true"
|
||||
(completionChanged)="completionChanged.emit($event)">
|
||||
<core-course-module-completion *ngIf="module.completiondata && module.uservisible" [completion]="module.completiondata"
|
||||
[moduleName]="module.name" [moduleId]="module.id" [showCompletionConditions]="true"
|
||||
[showManualCompletion]="showManualCompletion" (completionChanged)="completionChanged.emit($event)">
|
||||
</core-course-module-completion>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
|
|
@ -36,12 +36,14 @@ import { CoreSites } from '@services/sites';
|
|||
export class CoreCourseModuleInfoComponent implements OnInit {
|
||||
|
||||
@Input() module!: CoreCourseModule; // The module to render.
|
||||
@Input() showManualCompletion = true; // Whether to show manual completion, true by default.
|
||||
@Input() courseId!: number; // The courseId the module belongs to.
|
||||
|
||||
@Input() component!: string; // Component for format text directive.
|
||||
@Input() componentId!: string | number; // Component ID to use in conjunction with the component.
|
||||
|
||||
@Input() description?: string | false; // The description to display. If false, no description will be shown.
|
||||
@Input() expandDescription = false; // If the description should be expanded by default.
|
||||
|
||||
@Input() hasDataToSync = false; // If the activity has any data to be synced.
|
||||
|
||||
|
|
|
@ -2,20 +2,22 @@
|
|||
|
||||
<ng-container *ngIf="completion.istrackeduser">
|
||||
<ng-container *ngIf="completion.state">
|
||||
<ion-button color="success" fill="outline" [attr.aria-label]="accessibleDescription" (click)="completionClicked($event)">
|
||||
<ion-button color="success" expand="block" fill="outline" [attr.aria-label]="accessibleDescription"
|
||||
(click)="completionClicked($event)">
|
||||
<ion-icon name="fas-check" slot="start" aria-hidden="true"></ion-icon>
|
||||
{{ 'core.course.completion_manual:done' | translate }}
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!completion.state">
|
||||
<ion-button color="light" [attr.aria-label]="accessibleDescription" (click)="completionClicked($event)">
|
||||
<ion-button color="dark" expand="block" fill="outline" [attr.aria-label]="accessibleDescription"
|
||||
(click)="completionClicked($event)">
|
||||
{{ 'core.course.completion_manual:markdone' | translate }}
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="!completion.istrackeduser">
|
||||
<ion-button disabled="true" color="light">
|
||||
<ion-button disabled="true" color="dark" expand="block" fill="outline">
|
||||
{{ 'core.course.completion_manual:markdone' | translate }}
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
|
|
|
@ -14,10 +14,11 @@
|
|||
|
||||
import { Component, ElementRef, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { CoreCourse, CoreCourseProvider, CoreCourseWSSection } from '@features/course/services/course';
|
||||
import { CoreCourseModule } from '@features/course/services/course-helper';
|
||||
import { CoreCourseModule, CoreCourseSection } from '@features/course/services/course-helper';
|
||||
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
|
||||
import { IonContent } from '@ionic/angular';
|
||||
import { ScrollDetail } from '@ionic/core';
|
||||
import { CoreNavigationOptions, CoreNavigator } from '@services/navigator';
|
||||
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
|
@ -41,6 +42,8 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy {
|
|||
|
||||
nextModule?: CoreCourseModule;
|
||||
previousModule?: CoreCourseModule;
|
||||
nextModuleSection?: CoreCourseSection;
|
||||
previousModuleSection?: CoreCourseSection;
|
||||
loaded = false;
|
||||
|
||||
protected element: HTMLElement;
|
||||
|
@ -201,9 +204,10 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy {
|
|||
for (let j = startModule; j < section.modules.length && this.nextModule == undefined; j++) {
|
||||
const module = section.modules[j];
|
||||
|
||||
const found = await this.isModuleAvailable(module, section.id);
|
||||
const found = await this.isModuleAvailable(module);
|
||||
if (found) {
|
||||
this.nextModule = module;
|
||||
this.nextModuleSection = section;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -224,9 +228,10 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy {
|
|||
for (let j = startModule; j >= 0 && this.previousModule == undefined; j--) {
|
||||
const module = section.modules[j];
|
||||
|
||||
const found = await this.isModuleAvailable(module, section.id);
|
||||
const found = await this.isModuleAvailable(module);
|
||||
if (found) {
|
||||
this.previousModule = module;
|
||||
this.previousModuleSection = section;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -237,20 +242,10 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy {
|
|||
* Module is visible by the user and it has a specific view (e.g. not a label).
|
||||
*
|
||||
* @param module Module to check.
|
||||
* @param sectionId Section ID the module belongs to.
|
||||
* @return Wether the module is available to the user or not.
|
||||
*/
|
||||
protected async isModuleAvailable(module: CoreCourseModule, sectionId: number): Promise<boolean> {
|
||||
if (module.uservisible === false || !CoreCourse.instance.moduleHasView(module)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!module.handlerData) {
|
||||
module.handlerData =
|
||||
await CoreCourseModuleDelegate.getModuleDataFor(module.modname, module, this.courseId, sectionId);
|
||||
}
|
||||
|
||||
return !!module.handlerData?.action;
|
||||
protected async isModuleAvailable(module: CoreCourseModule): Promise<boolean> {
|
||||
return CoreCourse.instance.moduleHasView(module);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -291,11 +286,19 @@ export class CoreCourseModuleNavigationComponent implements OnInit, OnDestroy {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!module.handlerData?.action) {
|
||||
return;
|
||||
if (module.uservisible === false) {
|
||||
const section = next ? this.nextModuleSection : this.previousModuleSection;
|
||||
const options: CoreNavigationOptions = {
|
||||
replace: true,
|
||||
params: {
|
||||
module,
|
||||
section,
|
||||
},
|
||||
};
|
||||
CoreNavigator.navigateToSitePath('course/' + this.courseId + '/' + module.id +'/module-preview', options);
|
||||
} else {
|
||||
CoreCourseModuleDelegate.openActivityPage(module.modname, module, this.courseId, { replace: true });
|
||||
}
|
||||
|
||||
module.handlerData.action(new Event('click'), module, this.courseId, { replace: true });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -75,8 +75,8 @@
|
|||
</div>
|
||||
|
||||
<!-- Module completion. -->
|
||||
<core-course-module-completion *ngIf="module.completiondata" [completion]="module.completiondata" [moduleName]="module.name"
|
||||
[moduleId]="module.id" [showCompletionConditions]="showCompletionConditions"
|
||||
<core-course-module-completion *ngIf="module.completiondata && module.uservisible" [completion]="module.completiondata"
|
||||
[moduleName]="module.name" [moduleId]="module.id" [showCompletionConditions]="showCompletionConditions"
|
||||
[showManualCompletion]="showManualCompletion" (completionChanged)="completionChanged.emit($event)">
|
||||
</core-course-module-completion>
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
<core-course-module-info [description]="module?.description" [courseId]="courseId" [module]="module">
|
||||
</core-course-module-info>
|
||||
|
||||
<div class="ion-padding">
|
||||
<h2 *ngIf="!isDisabledInSite && isSupportedByTheApp">{{ 'core.whoops' | translate }}</h2>
|
||||
<h2 *ngIf="isDisabledInSite || !isSupportedByTheApp">{{ 'core.uhoh' | translate }}</h2>
|
||||
|
|
|
@ -23,9 +23,9 @@ const routes: Routes = [
|
|||
loadChildren: () => import('./pages/index/index.module').then( m => m.CoreCourseIndexPageModule),
|
||||
},
|
||||
{
|
||||
path: ':courseId/unsupported-module',
|
||||
loadChildren: () => import('./pages/unsupported-module/unsupported-module.module')
|
||||
.then( m => m.CoreCourseUnsupportedModulePageModule),
|
||||
path: ':courseId/:cmId/module-preview',
|
||||
loadChildren: () => import('./pages/module-preview/module-preview.module')
|
||||
.then( m => m.CoreCourseModulePreviewPageModule),
|
||||
},
|
||||
{
|
||||
path: ':courseId/list-mod-type',
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<ion-header collapsible>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button [text]="'core.back' | translate"></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>
|
||||
<h1>
|
||||
<core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
|
||||
</core-format-text>
|
||||
</h1>
|
||||
</ion-title>
|
||||
|
||||
<ion-buttons slot="end">
|
||||
<core-context-menu>
|
||||
<core-context-menu-item [priority]="900" *ngIf="module.url" [href]="module!.url"
|
||||
[content]="'core.openinbrowser' | translate" iconAction="fas-external-link-alt">
|
||||
</core-context-menu-item>
|
||||
</core-context-menu>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-refresher slot="fixed" [disabled]="!loaded" (ionRefresh)="doRefresh($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-course-module-info [module]="module" [courseId]="courseId" [description]="module.description" [component]="module.modname"
|
||||
[componentId]="module.id" (completionChanged)="onCompletionChange()" [expandDescription]="true"
|
||||
[showManualCompletion]="showManualCompletion">
|
||||
|
||||
<div class="safe-area-padding-horizontal ion-padding" *ngIf="module.handlerData?.extraBadge">
|
||||
<ion-badge class="ion-text-wrap ion-text-start" [color]="module.handlerData?.extraBadgeColor">
|
||||
<span [innerHTML]="module.handlerData?.extraBadge"></span>
|
||||
</ion-badge>
|
||||
</div>
|
||||
<div class="safe-area-padding-horizontal ion-padding" *ngIf="module.visible === 0 && (!section || section.visible)">
|
||||
<ion-badge class="ion-text-wrap">
|
||||
{{ 'core.course.hiddenfromstudents' | translate }}
|
||||
</ion-badge>
|
||||
</div>
|
||||
<div class="safe-area-padding-horizontal ion-padding" *ngIf="module.visible !== 0 && module.isStealth">
|
||||
<ion-badge class="ion-text-wrap">
|
||||
{{ 'core.course.hiddenoncoursepage' | translate }}
|
||||
</ion-badge>
|
||||
</div>
|
||||
<div class="safe-area-padding-horizontal ion-padding core-module-availabilityinfo" *ngIf="module.availabilityinfo">
|
||||
<ion-badge class="ion-text-wrap">{{ 'core.restricted' | translate }}</ion-badge>
|
||||
<div>
|
||||
<core-format-text [text]="module.availabilityinfo" contextLevel="module" [contextInstanceId]="module.id"
|
||||
[courseId]="courseId" class="ion-text-wrap">
|
||||
</core-format-text>
|
||||
</div>
|
||||
</div>
|
||||
<div class="safe-area-padding-horizontal ion-padding" *ngIf="module.completiondata?.offline">
|
||||
<ion-badge color="warning" class="ion-text-wrap">
|
||||
{{ 'core.course.manualcompletionnotsynced' | translate }}
|
||||
</ion-badge>
|
||||
</div>
|
||||
|
||||
<core-course-unsupported-module *ngIf="unsupported" [module]="module" [courseId]="courseId"></core-course-unsupported-module>
|
||||
</core-course-module-info>
|
||||
</core-loading>
|
||||
|
||||
<core-course-module-navigation [hidden]="!loaded" [courseId]="courseId" [currentModuleId]="module.id"></core-course-module-navigation>
|
||||
</ion-content>
|
|
@ -16,13 +16,13 @@ import { NgModule } from '@angular/core';
|
|||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { CoreSharedModule } from '@/core/shared.module';
|
||||
import { CoreCourseUnsupportedModulePage } from './unsupported-module.page';
|
||||
import { CoreCourseModulePreviewPage } from './module-preview.page';
|
||||
import { CoreCourseComponentsModule } from '@features/course/components/components.module';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: CoreCourseUnsupportedModulePage,
|
||||
component: CoreCourseModulePreviewPage,
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -33,8 +33,8 @@ const routes: Routes = [
|
|||
CoreCourseComponentsModule,
|
||||
],
|
||||
declarations: [
|
||||
CoreCourseUnsupportedModulePage,
|
||||
CoreCourseModulePreviewPage,
|
||||
],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class CoreCourseUnsupportedModulePageModule {}
|
||||
export class CoreCourseModulePreviewPageModule { }
|
|
@ -0,0 +1,118 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// 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, OnInit } from '@angular/core';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreCourseHelper, CoreCourseModule, CoreCourseSection } from '@features/course/services/course-helper';
|
||||
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
|
||||
import { IonRefresher } from '@ionic/angular';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
|
||||
/**
|
||||
* Page that displays a module preview.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'page-core-course-module-preview',
|
||||
templateUrl: 'module-preview.html',
|
||||
})
|
||||
export class CoreCourseModulePreviewPage implements OnInit {
|
||||
|
||||
title!: string;
|
||||
module!: CoreCourseModule;
|
||||
section?: CoreCourseSection; // The section the module belongs to.
|
||||
courseId!: number;
|
||||
loaded = false;
|
||||
unsupported = false;
|
||||
showManualCompletion = false;
|
||||
|
||||
protected debouncedUpdateModule?: () => void; // Update the module after a certain time.
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async ngOnInit(): Promise<void> {
|
||||
try {
|
||||
this.module = CoreNavigator.getRequiredRouteParam<CoreCourseModule>('module');
|
||||
this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
|
||||
this.section = CoreNavigator.getRouteParam<CoreCourseSection>('section');
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModal(error);
|
||||
|
||||
CoreNavigator.back();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.debouncedUpdateModule = CoreUtils.debounce(() => {
|
||||
this.doRefresh();
|
||||
}, 10000);
|
||||
|
||||
await this.fetchModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch module.
|
||||
*
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async fetchModule(refresh = false): Promise<void> {
|
||||
if (refresh) {
|
||||
this.module = await CoreCourse.getModule(this.module.id, this.courseId);
|
||||
}
|
||||
|
||||
CoreCourseHelper.calculateModuleCompletionData(this.module, this.courseId);
|
||||
|
||||
await CoreCourseHelper.loadModuleOfflineCompletion(this.courseId, this.module);
|
||||
|
||||
this.unsupported = !CoreCourseModuleDelegate.getHandlerName(this.module.modname);
|
||||
if (!this.unsupported) {
|
||||
this.module.handlerData =
|
||||
await CoreCourseModuleDelegate.getModuleDataFor(this.module.modname, this.module, this.courseId);
|
||||
}
|
||||
|
||||
this.title = this.module.name;
|
||||
|
||||
this.showManualCompletion = await CoreCourseModuleDelegate.manualCompletionAlwaysShown(this.module);
|
||||
|
||||
this.loaded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the data.
|
||||
*
|
||||
* @param refresher Refresher.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
async doRefresh(refresher?: IonRefresher): Promise<void> {
|
||||
|
||||
await CoreCourse.invalidateModule(this.module.id);
|
||||
|
||||
this.fetchModule(true);
|
||||
|
||||
refresher?.complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* The completion of the modules has changed.
|
||||
*
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
async onCompletionChange(): Promise<void> {
|
||||
// Update the module data after a while.
|
||||
this.debouncedUpdateModule?.();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
<ion-header collapsible>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button [text]="'core.back' | translate"></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>
|
||||
<h1>
|
||||
<core-format-text [text]="module?.name" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId">
|
||||
</core-format-text>
|
||||
</h1>
|
||||
</ion-title>
|
||||
|
||||
<ion-buttons slot="end">
|
||||
<core-context-menu>
|
||||
<core-context-menu-item [priority]="900" *ngIf="module?.url" [href]="module!.url"
|
||||
[content]="'core.openinbrowser' | translate" iconAction="fas-external-link-alt">
|
||||
</core-context-menu-item>
|
||||
<core-context-menu-item [priority]="800" *ngIf="module?.description" [content]="'core.moduleintro' | translate"
|
||||
(action)="expandDescription()" iconAction="fas-arrow-right">
|
||||
</core-context-menu-item>
|
||||
</core-context-menu>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<core-course-unsupported-module [module]="module" [courseId]="courseId"></core-course-unsupported-module>
|
||||
</ion-content>
|
|
@ -1,54 +0,0 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// 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, OnInit } from '@angular/core';
|
||||
|
||||
import { CoreCourseWSModule } from '@features/course/services/course';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { Translate } from '@singletons';
|
||||
|
||||
/**
|
||||
* Page that displays info about an unsupported module.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'page-core-course-unsupported-module',
|
||||
templateUrl: 'unsupported-module.html',
|
||||
})
|
||||
export class CoreCourseUnsupportedModulePage implements OnInit {
|
||||
|
||||
module?: CoreCourseWSModule;
|
||||
courseId?: number;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.module = CoreNavigator.getRouteParam('module');
|
||||
this.courseId = CoreNavigator.getRouteNumberParam('courseId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the description.
|
||||
*/
|
||||
expandDescription(): void {
|
||||
CoreTextUtils.viewText(Translate.instant('core.description'), this.module!.description!, {
|
||||
filter: true,
|
||||
contextLevel: 'module',
|
||||
instanceId: this.module!.id,
|
||||
courseId: this.courseId,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -49,14 +49,11 @@ export class CoreCourseModuleDefaultHandler implements CoreCourseModuleHandler {
|
|||
icon: await CoreCourse.getModuleIconSrc(module.modname, module.modicon),
|
||||
title: module.name,
|
||||
class: 'core-course-default-handler core-course-module-' + module.modname + '-handler',
|
||||
action: (event: Event, module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions) => {
|
||||
action: async (event: Event, module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
options = options || {};
|
||||
options.params = { module };
|
||||
|
||||
CoreNavigator.navigateToSitePath('course/' + courseId + '/unsupported-module', options);
|
||||
await this.openActivityPage(module, courseId, options);
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -92,4 +89,15 @@ export class CoreCourseModuleDefaultHandler implements CoreCourseModuleHandler {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async openActivityPage(module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions): Promise<void> {
|
||||
options = options || {};
|
||||
options.params = options.params || {};
|
||||
Object.assign(options.params, { module });
|
||||
|
||||
await CoreNavigator.navigateToSitePath('course/' + courseId + '/' + module.id +'/module-preview', options);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -102,6 +102,16 @@ export interface CoreCourseModuleHandler extends CoreDelegateHandler {
|
|||
* @return Promise resolved with boolean: whether the manual completion should always be displayed.
|
||||
*/
|
||||
manualCompletionAlwaysShown?(module: CoreCourseModule): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Opens the activity page.
|
||||
*
|
||||
* @param module The module object.
|
||||
* @param courseId The course ID.
|
||||
* @param options Options for the navigation.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
openActivityPage(module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -295,6 +305,27 @@ export class CoreCourseModuleDelegateService extends CoreDelegate<CoreCourseModu
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the activity page.
|
||||
*
|
||||
* @param module The module object.
|
||||
* @param courseId The course ID.
|
||||
* @param options Options for the navigation.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
async openActivityPage(
|
||||
modname: string,
|
||||
module: CoreCourseModule,
|
||||
courseId: number,
|
||||
options?: CoreNavigationOptions,
|
||||
): Promise<void> {
|
||||
return await this.executeFunctionOnEnabled<void>(
|
||||
modname,
|
||||
'openActivityPage',
|
||||
[module, courseId, options],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a certain module type is disabled in a site.
|
||||
*
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import { Type } from '@angular/core';
|
||||
|
||||
import { CoreConstants } from '@/core/constants';
|
||||
import { CoreCourseAnyModuleData, CoreCourseWSModule } from '@features/course/services/course';
|
||||
import { CoreCourse, CoreCourseAnyModuleData, CoreCourseWSModule } from '@features/course/services/course';
|
||||
import { CoreCourseModule } from '@features/course/services/course-helper';
|
||||
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate';
|
||||
import { CoreSitePluginsModuleIndexComponent } from '@features/siteplugins/components/module-index/module-index';
|
||||
|
@ -92,17 +92,16 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp
|
|||
|
||||
if (this.handlerSchema.method) {
|
||||
// There is a method, add an action.
|
||||
handlerData.action = (event: Event, module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions) => {
|
||||
handlerData.action = async (
|
||||
event: Event,
|
||||
module: CoreCourseModule,
|
||||
courseId: number,
|
||||
options?: CoreNavigationOptions,
|
||||
) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
options = options || {};
|
||||
options.params = {
|
||||
title: module.name,
|
||||
module,
|
||||
};
|
||||
|
||||
CoreNavigator.navigateToSitePath(`siteplugins/module/${courseId}/${module.id}`, options);
|
||||
await this.openActivityPage(module, courseId, options);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -229,4 +228,22 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async openActivityPage(module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions): Promise<void> {
|
||||
if (!CoreCourse.moduleHasView(module)) {
|
||||
return;
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
options.params = options.params || {};
|
||||
Object.assign(options.params, {
|
||||
title: module.name,
|
||||
module,
|
||||
});
|
||||
|
||||
CoreNavigator.navigateToSitePath(`siteplugins/module/${courseId}/${module.id}`, options);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue