MOBILE-3931 module: Adapt module site plugins code

main
Pau Ferrer Ocaña 2022-02-16 15:32:09 +01:00
parent 16cee9df14
commit 6c782e3b3e
7 changed files with 145 additions and 214 deletions

View File

@ -58,7 +58,6 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
hasOffline = false; // Resources don't have any data to sync. hasOffline = false; // Resources don't have any data to sync.
description?: string; // Module description. description?: string; // Module description.
isDestroyed = false; // Whether the component is destroyed.
protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents. protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents.
protected isCurrentView = false; // Whether the component is in the current view. protected isCurrentView = false; // Whether the component is in the current view.
@ -72,6 +71,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
protected debouncedUpdateModule?: () => void; // Update the module after a certain time. protected debouncedUpdateModule?: () => void; // Update the module after a certain time.
protected showCompletion = false; // Whether to show completion inside the activity. protected showCompletion = false; // Whether to show completion inside the activity.
protected displayDescription = true; // Wether to show Module description on module page, and not on summary or the contrary. protected displayDescription = true; // Wether to show Module description on module page, and not on summary or the contrary.
protected isDestroyed = false; // Whether the component is destroyed.
constructor( constructor(
@Optional() @Inject('') loggerName: string = 'CoreCourseModuleMainResourceComponent', @Optional() @Inject('') loggerName: string = 'CoreCourseModuleMainResourceComponent',
@ -111,11 +111,10 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
* Refresh the data. * Refresh the data.
* *
* @param refresher Refresher. * @param refresher Refresher.
* @param done Function to call when done. Never used.
* @param showErrors If show errors to the user of hide them. * @param showErrors If show errors to the user of hide them.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
async doRefresh(refresher?: IonRefresher | null, done?: () => void, showErrors: boolean = false): Promise<void> { async doRefresh(refresher?: IonRefresher | null, showErrors = false): Promise<void> {
if (!this.loaded || !this.module) { if (!this.loaded || !this.module) {
// Module can be undefined if course format changes from single activity to weekly/topics. // Module can be undefined if course format changes from single activity to weekly/topics.
return; return;
@ -405,10 +404,14 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
componentProps: { componentProps: {
moduleId: this.module.id, moduleId: this.module.id,
module: this.module, module: this.module,
description: !this.displayDescription ? this.description : '', description: this.description,
component: this.component, component: this.component,
courseId: this.courseId, courseId: this.courseId,
hasOffline: this.hasOffline, hasOffline: this.hasOffline,
displayOptions: {
// Show description on summary if not shown on the page.
displayDescription: !this.displayDescription,
},
}, },
}); });
@ -421,11 +424,11 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
} finally { } finally {
modal.dismiss(); modal.dismiss();
} }
} else if(data.action == 'sync') { } else if (data.action == 'sync') {
const modal = await CoreDomUtils.showModalLoading(); const modal = await CoreDomUtils.showModalLoading();
try { try {
await this.doRefresh( undefined, undefined, true); await this.doRefresh( undefined, true);
} finally { } finally {
modal.dismiss(); modal.dismiss();
} }

View File

@ -19,12 +19,12 @@
</core-format-text> </core-format-text>
</h1> </h1>
</ion-label> </ion-label>
<ion-button fill="clear" [href]="externalUrl" core-link [showBrowserWarning]="false" color="dark" <ion-button fill="clear" *ngIf="displayOptions.displayOpenInBrowser" [href]="externalUrl" core-link [showBrowserWarning]="false"
[attr.aria-label]="'core.openinbrowser' | translate" slot="end"> color="dark" [attr.aria-label]="'core.openinbrowser' | translate" slot="end">
<ion-icon name="fas-external-link-alt" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-external-link-alt" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>
</ion-item> </ion-item>
<ion-item class="ion-text-wrap" *ngIf="module && description"> <ion-item class="ion-text-wrap" *ngIf="module && description && displayOptions.displayDescription">
<ion-label> <ion-label>
<core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module" <core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module"
[contextInstanceId]="module.id" [courseId]="courseId" [maxHeight]="120"> [contextInstanceId]="module.id" [courseId]="courseId" [maxHeight]="120">
@ -32,7 +32,7 @@
</ion-label> </ion-label>
</ion-item> </ion-item>
<ion-item button class="ion-margin" *ngIf="prefetchText" class="ion-text-wrap"> <ion-item button class="ion-margin" *ngIf="prefetchText && displayOptions.displayPrefetch" class="ion-text-wrap">
<ion-label> <ion-label>
<p class="item-heading ion-text-wrap">{{ prefetchText }}</p> <p class="item-heading ion-text-wrap">{{ prefetchText }}</p>
<p *ngIf="downloadTimeReadable">{{ downloadTimeReadable }}</p> <p *ngIf="downloadTimeReadable">{{ downloadTimeReadable }}</p>
@ -45,7 +45,7 @@
<ion-spinner *ngIf="prefetchStatusIcon == 'spinner'" slot="end" aria-hidden="true"></ion-spinner> <ion-spinner *ngIf="prefetchStatusIcon == 'spinner'" slot="end" aria-hidden="true"></ion-spinner>
</ion-item> </ion-item>
<ion-item button class="ion-margin" *ngIf="sizeReadable" class="ion-text-wrap"> <ion-item button class="ion-margin" *ngIf="sizeReadable && displayOptions.displaySize" class="ion-text-wrap">
<ion-label> <ion-label>
<p class="item-heading ion-text-wrap">{{ 'addon.storagemanager.totalspaceusage' | translate }}</p> <p class="item-heading ion-text-wrap">{{ 'addon.storagemanager.totalspaceusage' | translate }}</p>
<ion-badge color="light">{{ sizeReadable | coreBytesToSize }}</ion-badge> <ion-badge color="light">{{ sizeReadable | coreBytesToSize }}</ion-badge>
@ -57,7 +57,7 @@
<ion-spinner *ngIf="removeFilesLoading" slot="end" aria-hidden="true"></ion-spinner> <ion-spinner *ngIf="removeFilesLoading" slot="end" aria-hidden="true"></ion-spinner>
</ion-item> </ion-item>
<ion-button *ngIf="blog" class="ion-margin" (click)="gotoBlog()" expand="block" fill="outline"> <ion-button *ngIf="blog && displayOptions.displayBlog" class="ion-margin" (click)="gotoBlog()" expand="block" fill="outline">
<ion-icon name="far-newspaper" slot="start" aria-hidden="true"></ion-icon> <ion-icon name="far-newspaper" slot="start" aria-hidden="true"></ion-icon>
<ion-label> <ion-label>
{{ 'addon.blog.blog' | translate }} {{ 'addon.blog.blog' | translate }}
@ -65,7 +65,7 @@
</ion-button> </ion-button>
</core-loading> </core-loading>
</ion-content> </ion-content>
<ion-footer *ngIf="loaded && isOnline"> <ion-footer *ngIf="loaded && isOnline && displayOptions.displayRefresh">
<ion-button class="ion-margin" *ngIf="!hasOffline" (click)="refresh()" expand="block"> <ion-button class="ion-margin" *ngIf="!hasOffline" (click)="refresh()" expand="block">
<ion-icon name="fas-redo-alt" slot="start" aria-hidden="true"></ion-icon> <ion-icon name="fas-redo-alt" slot="start" aria-hidden="true"></ion-icon>
<ion-label> <ion-label>

View File

@ -46,6 +46,7 @@ export class CoreCourseModuleSummaryComponent implements OnInit, OnDestroy {
@Input() component = ''; // Component name. @Input() component = ''; // Component name.
@Input() description = ''; // Module description. @Input() description = ''; // Module description.
@Input() hasOffline = false; // If it has offline data to be synced. @Input() hasOffline = false; // If it has offline data to be synced.
@Input() displayOptions: CoreCourseModuleSummaryDisplayOptions = {};
loaded = false; // If the component has been loaded. loaded = false; // If the component has been loaded.
componentId?: number; // Component ID. componentId?: number; // Component ID.
@ -95,6 +96,15 @@ export class CoreCourseModuleSummaryComponent implements OnInit, OnDestroy {
return; return;
} }
this.displayOptions = Object.assign({
displayOpenInBrowser: true,
displayDescription: true,
displayRefresh: true,
displayPrefetch: true,
displaySize: true,
displayBlog: true,
}, this.displayOptions);
this.fetchContent(); this.fetchContent();
if (this.component) { if (this.component) {
@ -306,6 +316,15 @@ export class CoreCourseModuleSummaryComponent implements OnInit, OnDestroy {
} }
export type CoreCourseModuleSummaryResult = { export type CoreCourseModuleSummaryResult = {
action: 'sync'|'refresh'; action: 'sync'|'refresh';
}; };
export type CoreCourseModuleSummaryDisplayOptions = {
displayOpenInBrowser?: boolean;
displayDescription?: boolean;
displayRefresh?: boolean;
displayPrefetch?: boolean;
displaySize?: boolean;
displayBlog?: boolean;
};

View File

@ -64,7 +64,6 @@ import { CoreFile } from '@services/file';
import { CoreUrlUtils } from '@services/utils/url'; import { CoreUrlUtils } from '@services/utils/url';
import { CoreTextUtils } from '@services/utils/text'; import { CoreTextUtils } from '@services/utils/text';
import { CoreTimeUtils } from '@services/utils/time'; import { CoreTimeUtils } from '@services/utils/time';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreFilterHelper } from '@features/filter/services/filter-helper'; import { CoreFilterHelper } from '@features/filter/services/filter-helper';
import { CoreNetworkError } from '@classes/errors/network-error'; import { CoreNetworkError } from '@classes/errors/network-error';
import { CoreSiteHome } from '@features/sitehome/services/sitehome'; import { CoreSiteHome } from '@features/sitehome/services/sitehome';
@ -474,23 +473,18 @@ export class CoreCourseHelperProvider {
* *
* @param module Module to remove the files. * @param module Module to remove the files.
* @param courseId Course ID the module belongs to. * @param courseId Course ID the module belongs to.
* @param done Function to call when done. It will close the context menu.
* @return Promise resolved when done. * @return Promise resolved when done.
* @deprecated since 4.0 * @deprecated since 4.0
*/ */
async confirmAndRemoveFiles(module: CoreCourseModuleData, courseId: number, done?: () => void): Promise<void> { async confirmAndRemoveFiles(module: CoreCourseModuleData, courseId: number): Promise<void> {
let modal: CoreIonLoadingElement | undefined; let modal: CoreIonLoadingElement | undefined;
try { try {
await CoreDomUtils.showDeleteConfirm('addon.storagemanager.confirmdeletedatafrom', { name: module.name }); await CoreDomUtils.showDeleteConfirm('addon.storagemanager.confirmdeletedatafrom', { name: module.name });
modal = await CoreDomUtils.showModalLoading(); modal = await CoreDomUtils.showModalLoading();
await this.removeModuleStoredData(module, courseId); await this.removeModuleStoredData(module, courseId);
done && done();
} catch (error) { } catch (error) {
if (error) { if (error) {
CoreDomUtils.showErrorModal(error); CoreDomUtils.showErrorModal(error);
@ -555,45 +549,6 @@ export class CoreCourseHelperProvider {
await CoreDomUtils.confirmDownloadSize(sizeSum, undefined, undefined, undefined, undefined, alwaysConfirm); await CoreDomUtils.confirmDownloadSize(sizeSum, undefined, undefined, undefined, undefined, alwaysConfirm);
} }
/**
* Helper function to prefetch a module, showing a confirmation modal if the size is big.
* This function is meant to be called from a context menu option. It will also modify some data like the prefetch icon.
*
* @param instance The component instance that has the context menu.
* @param module Module to be prefetched
* @param courseId Course ID the module belongs to.
* @param done Function to call when done. It will close the context menu.
* @return Promise resolved when done.
* @deprecated since 4.0
*/
async contextMenuPrefetch(
instance: ComponentWithContextMenu,
module: CoreCourseModuleData,
courseId: number,
done?: () => void,
): Promise<void> {
const initialIcon = instance.prefetchStatusIcon;
instance.prefetchStatusIcon = CoreConstants.ICON_DOWNLOADING; // Show spinner since this operation might take a while.
try {
// We need to call getDownloadSize, the package might have been updated.
const size = await CoreCourseModulePrefetchDelegate.getModuleDownloadSize(module, courseId, true);
await CoreDomUtils.confirmDownloadSize(size);
await CoreCourseModulePrefetchDelegate.prefetchModule(module, courseId, true);
// Success, close menu.
done && done();
} catch (error) {
instance.prefetchStatusIcon = initialIcon;
if (!instance.isDestroyed) {
CoreDomUtils.showErrorModalDefault(error, 'core.errordownloading', true);
}
}
}
/** /**
* Check whether a course is accessed using guest access. * Check whether a course is accessed using guest access.
* *
@ -1030,87 +985,6 @@ export class CoreCourseHelperProvider {
await CoreFilepool.downloadOrPrefetchFiles(siteId, files, false, false, component, componentId); await CoreFilepool.downloadOrPrefetchFiles(siteId, files, false, false, component, componentId);
} }
/**
* Fill the Context Menu for a certain module.
*
* @param instance The component instance that has the context menu.
* @param module Module to be prefetched
* @param courseId Course ID the module belongs to.
* @param invalidateCache Invalidates the cache first.
* @param component Component of the module.
* @return Promise resolved when done.
*/
async fillContextMenu(
instance: ComponentWithContextMenu,
module: CoreCourseModuleData,
courseId: number,
invalidateCache?: boolean,
component?: string,
): Promise<void> {
const siteId = CoreSites.getCurrentSiteId();
const moduleInfo = await this.getModulePrefetchInfo(module, courseId, invalidateCache, component);
instance.size = moduleInfo.sizeReadable;
instance.prefetchStatusIcon = moduleInfo.statusIcon;
instance.prefetchStatus = moduleInfo.status;
instance.downloadTimeReadable = CoreTextUtils.ucFirst(moduleInfo.downloadTimeReadable);
if (moduleInfo.status != CoreConstants.NOT_DOWNLOADABLE) {
// Module is downloadable, get the text to display to prefetch.
if (moduleInfo.downloadTime && moduleInfo.downloadTime > 0) {
instance.prefetchText = Translate.instant('core.lastdownloaded') + ': ' + moduleInfo.downloadTimeReadable;
} else {
// Module not downloaded, show a default text.
instance.prefetchText = Translate.instant('core.download');
}
}
if (moduleInfo.status == CoreConstants.DOWNLOADING) {
// Set this to empty to prevent "remove file" option showing up while downloading.
instance.size = '';
}
if (!instance.contextMenuStatusObserver && component) {
instance.contextMenuStatusObserver = CoreEvents.on(
CoreEvents.PACKAGE_STATUS_CHANGED,
(data) => {
if (data.componentId == module.id && data.component == component) {
this.fillContextMenu(instance, module, courseId, false, component);
}
},
siteId,
);
}
if (!instance.contextFileStatusObserver && component) {
// Debounce the update size function to prevent too many calls when downloading or deleting a whole activity.
const debouncedUpdateSize = CoreUtils.debounce(async () => {
const moduleSize = await CoreCourseModulePrefetchDelegate.getModuleStoredSize(module, courseId);
instance.size = moduleSize > 0 ? CoreTextUtils.bytesToSize(moduleSize, 2) : '';
}, 1000);
instance.contextFileStatusObserver = CoreEvents.on(
CoreEvents.COMPONENT_FILE_ACTION,
(data) => {
if (data.component != component || data.componentId != module.id) {
// The event doesn't belong to this component, ignore.
return;
}
if (!CoreFilepool.isFileEventDownloadedOrDeleted(data)) {
return;
}
// Update the module size.
debouncedUpdateSize();
},
siteId,
);
}
}
/** /**
* Get a course. It will first check the user courses, and fallback to another WS if not enrolled. * Get a course. It will first check the user courses, and fallback to another WS if not enrolled.
* *
@ -2225,14 +2099,3 @@ export type CoreCourseOpenModuleOptions = {
sectionId?: number; // Section the module belongs to. sectionId?: number; // Section the module belongs to.
modNavOptions?: CoreNavigationOptions; // Navigation options to open the module, including params to pass to the module. modNavOptions?: CoreNavigationOptions; // Navigation options to open the module, including params to pass to the module.
}; };
type ComponentWithContextMenu = {
prefetchStatusIcon?: string;
isDestroyed?: boolean;
size?: string;
prefetchStatus?: string;
prefetchText?: string;
downloadTimeReadable?: string;
contextMenuStatusObserver?: CoreEventObserver;
contextFileStatusObserver?: CoreEventObserver;
};

View File

@ -202,10 +202,10 @@ export interface CoreCourseModuleMainComponent {
* Refresh the data. * Refresh the data.
* *
* @param refresher Refresher. * @param refresher Refresher.
* @param done Function to call when done. * @param showErrors If show errors to the user of hide them.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
doRefresh(refresher?: IonRefresher, done?: () => void): Promise<void>; doRefresh(refresher?: IonRefresher | null, showErrors?: boolean): Promise<void>;
} }
/** /**

View File

@ -1,28 +1,8 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu> <ion-button fill="clear" (click)="openModuleSummary()" [attr.aria-label]="'core.info' | translate">
<core-context-menu-item [hidden]="!displayOpenInBrowser || !externalUrl || ( <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
content?.compileComponent?.componentInstance?.displayOpenInBrowser === false)" [priority]="900" </ion-button>
[content]="'core.openinbrowser' | translate" [href]="externalUrl" iconAction="fas-external-link-alt">
</core-context-menu-item>
<core-context-menu-item [hidden]="!displayDescription || !description || (
content?.compileComponent?.componentInstance?.displayDescription === false)" [priority]="800"
[content]="'core.moduleintro' | translate" (action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item [hidden]="!displayRefresh || (
content?.compileComponent?.componentInstance?.displayRefresh === false)" [priority]="700"
[content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item [hidden]="!displayPrefetch || !prefetchStatusIcon || (
content?.compileComponent?.componentInstance?.displayPrefetch === false)" [priority]="600" [content]="prefetchText"
(action)="prefetch()" [iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item [hidden]="!displaySize || !size || (
content?.compileComponent?.componentInstance?.displaySize === false)" [priority]="500"
[content]="'core.clearstoreddata' | translate:{$a: size}" [iconDescription]="'fas-archive'" (action)="removeFiles()"
iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
</core-navbar-buttons> </core-navbar-buttons>
<core-site-plugins-plugin-content *ngIf="component && method" [component]="component" [method]="method" [args]="args" <core-site-plugins-plugin-content *ngIf="component && method" [component]="component" [method]="method" [args]="args"

View File

@ -14,8 +14,13 @@
import { CoreConstants } from '@/core/constants'; import { CoreConstants } from '@/core/constants';
import { Component, OnInit, OnDestroy, Input, ViewChild } from '@angular/core'; import { Component, OnInit, OnDestroy, Input, ViewChild } from '@angular/core';
import { CoreIonLoadingElement } from '@classes/ion-loading';
import { CoreSiteWSPreSets } from '@classes/site'; import { CoreSiteWSPreSets } from '@classes/site';
import {
CoreCourseModuleSummaryResult,
CoreCourseModuleSummaryComponent,
} from '@features/course/components/module-summary/module-summary';
import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper'; import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper';
import { import {
CoreCourseModuleDelegate, CoreCourseModuleDelegate,
@ -28,10 +33,8 @@ import {
CoreSitePluginsCourseModuleHandlerData, CoreSitePluginsCourseModuleHandlerData,
} from '@features/siteplugins/services/siteplugins'; } from '@features/siteplugins/services/siteplugins';
import { IonRefresher } from '@ionic/angular'; import { IonRefresher } from '@ionic/angular';
import { CoreTextUtils } from '@services/utils/text'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { Translate } from '@singletons';
import { CoreEventObserver } from '@singletons/events';
import { CoreSitePluginsPluginContentComponent } from '../plugin-content/plugin-content'; import { CoreSitePluginsPluginContentComponent } from '../plugin-content/plugin-content';
/** /**
@ -55,22 +58,39 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
args?: Record<string, unknown>; args?: Record<string, unknown>;
initResult?: CoreSitePluginsContent | null; initResult?: CoreSitePluginsContent | null;
preSets?: CoreSiteWSPreSets; preSets?: CoreSiteWSPreSets;
// Data for context menu.
externalUrl?: string;
description?: string; description?: string;
refreshIcon?: string;
/**
* @deprecated since 4.0, use module.url instead.
*/
externalUrl?: string;
/**
* @deprecated since 4.0. It won't be populated anymore.
*/
refreshIcon = CoreConstants.ICON_REFRESH;
/**
* @deprecated since 4.0.. It won't be populated anymore.
*/
prefetchStatus?: string; prefetchStatus?: string;
/**
* @deprecated since 4.0. It won't be populated anymore.
*/
prefetchStatusIcon?: string; prefetchStatusIcon?: string;
/**
* @deprecated since 4.0. It won't be populated anymore.
*/
prefetchText?: string; prefetchText?: string;
/**
* @deprecated since 4.0. It won't be populated anymore.
*/
size?: string; size?: string;
contextMenuStatusObserver?: CoreEventObserver;
contextFileStatusObserver?: CoreEventObserver;
displayOpenInBrowser = true; displayOpenInBrowser = true;
displayDescription = true; displayDescription = true;
displayRefresh = true; displayRefresh = true;
displayPrefetch = true; displayPrefetch = true;
displaySize = true; displaySize = true;
ptrEnabled = true; ptrEnabled = true;
isDestroyed = false; isDestroyed = false;
@ -80,8 +100,6 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
* Component being initialized. * Component being initialized.
*/ */
ngOnInit(): void { ngOnInit(): void {
this.refreshIcon = CoreConstants.ICON_LOADING;
if (!this.module) { if (!this.module) {
return; return;
} }
@ -122,71 +140,119 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
* Refresh the data. * Refresh the data.
* *
* @param refresher Refresher. * @param refresher Refresher.
* @param done Function to call when done.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
async doRefresh(refresher?: IonRefresher | null, done?: () => void): Promise<void> { async doRefresh(refresher?: IonRefresher | null): Promise<void> {
if (this.content) {
this.refreshIcon = CoreConstants.ICON_LOADING;
}
try { try {
await this.content?.refreshContent(false); await this.content?.refreshContent(false);
} finally { } finally {
refresher?.complete(); refresher?.complete();
done && done();
} }
} }
/** /**
* Function called when the data of the site plugin content is loaded. * Function called when the data of the site plugin content is loaded.
*/ */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
contentLoaded(refresh: boolean): void { contentLoaded(refresh: boolean): void {
this.refreshIcon = CoreConstants.ICON_REFRESH; return;
// Check if there is a prefetch handler for this type of module.
if (CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor(this.module.modname)) {
CoreCourseHelper.fillContextMenu(this, this.module, this.courseId, refresh, this.component);
}
} }
/** /**
* Function called when starting to load the data of the site plugin content. * Function called when starting to load the data of the site plugin content.
*/ */
contentLoading(): void { contentLoading(): void {
this.refreshIcon = CoreConstants.ICON_LOADING; return;
} }
/** /**
* Expand the description. * Expand the description.
*
* @deprecated since 4.0
*/ */
expandDescription(): void { expandDescription(): void {
if (!this.description) { this.openModuleSummary();
}
/**
* Opens a module summary page.
*/
async openModuleSummary(): Promise<void> {
if (!this.module) {
return; return;
} }
CoreTextUtils.viewText(Translate.instant('core.description'), this.description, { const data = await CoreDomUtils.openSideModal<CoreCourseModuleSummaryResult>({
component: this.component, component: CoreCourseModuleSummaryComponent,
componentId: this.module.id, componentProps: {
filter: true, moduleId: this.module.id,
contextLevel: 'module', module: this.module,
instanceId: this.module.id, description: this.description,
courseId: this.courseId, component: this.component,
courseId: this.courseId,
displayOptions: {
displayOpenInBrowser: this.displayOpenInBrowser,
displayDescription: this.displayDescription,
displayRefresh: this.displayRefresh,
displayPrefetch: this.displayPrefetch,
displaySize: this.displaySize,
displayBlog: false,
},
},
}); });
if (data && data.action == 'refresh') {
const modal = await CoreDomUtils.showModalLoading();
try {
await this.doRefresh();
} finally {
modal.dismiss();
}
}
} }
/** /**
* Prefetch the module. * Prefetch the module.
*
* @deprecated since 4.0
*/ */
prefetch(): void { async prefetch(): Promise<void> {
CoreCourseHelper.contextMenuPrefetch(this, this.module, this.courseId); try {
// We need to call getDownloadSize, the package might have been updated.
const size = await CoreCourseModulePrefetchDelegate.getModuleDownloadSize(this.module, this.courseId, true);
await CoreDomUtils.confirmDownloadSize(size);
await CoreCourseModulePrefetchDelegate.prefetchModule(this.module, this.courseId, true);
} catch (error) {
if (!this.isDestroyed) {
CoreDomUtils.showErrorModalDefault(error, 'core.errordownloading', true);
}
}
} }
/** /**
* Confirm and remove downloaded files. * Confirm and remove downloaded files.
*
* @deprecated since 4.0
*/ */
removeFiles(): void { async removeFiles(): Promise<void> {
CoreCourseHelper.confirmAndRemoveFiles(this.module, this.courseId); let modal: CoreIonLoadingElement | undefined;
try {
await CoreDomUtils.showDeleteConfirm('addon.storagemanager.confirmdeletedatafrom', { name: this.module.name });
modal = await CoreDomUtils.showModalLoading();
await CoreCourseHelper.removeModuleStoredData(this.module, this.courseId);
} catch (error) {
if (error) {
CoreDomUtils.showErrorModal(error);
}
} finally {
modal?.dismiss();
}
} }
/** /**