MOBILE-3847 resource: Display error if resource WS call fails
parent
9c3251ec1d
commit
2175a11dbb
|
@ -14,9 +14,7 @@
|
||||||
|
|
||||||
import { Component, Optional, Input, OnInit } from '@angular/core';
|
import { Component, Optional, Input, OnInit } from '@angular/core';
|
||||||
import { IonContent } from '@ionic/angular';
|
import { IonContent } from '@ionic/angular';
|
||||||
import {
|
import { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component';
|
||||||
CoreCourseModuleMainResourceComponent, CoreCourseResourceDownloadResult,
|
|
||||||
} from '@features/course/classes/main-resource-component';
|
|
||||||
import {
|
import {
|
||||||
AddonModBookProvider,
|
AddonModBookProvider,
|
||||||
AddonModBookContentsMap,
|
AddonModBookContentsMap,
|
||||||
|
@ -130,35 +128,10 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
protected async fetchContent(refresh = false): Promise<void> {
|
protected async fetchContent(refresh = false): Promise<void> {
|
||||||
const promises: Promise<void>[] = [];
|
|
||||||
let downloadResult: CoreCourseResourceDownloadResult | undefined;
|
|
||||||
|
|
||||||
// Try to get the book data. Ignore errors since this WS isn't available in some Moodle versions.
|
|
||||||
promises.push(CoreUtils.ignoreErrors(AddonModBook.getBook(this.courseId, this.module.id))
|
|
||||||
.then((book) => {
|
|
||||||
if (!book) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.book = book;
|
|
||||||
this.dataRetrieved.emit(book);
|
|
||||||
|
|
||||||
this.description = book.intro;
|
|
||||||
this.displayNavBar = book.navstyle != AddonModBookNavStyle.TOC_ONLY;
|
|
||||||
this.displayTitlesInNavBar = book.navstyle == AddonModBookNavStyle.TEXT;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Get module status to determine if it needs to be downloaded.
|
|
||||||
promises.push(this.downloadResourceIfNeeded(refresh).then((result) => {
|
|
||||||
downloadResult = result;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Promise.all(promises);
|
const downloadResult = await this.downloadResourceIfNeeded(refresh);
|
||||||
|
|
||||||
|
await this.loadBookData();
|
||||||
|
|
||||||
this.contentsMap = AddonModBook.getContentsMap(this.module.contents);
|
this.contentsMap = AddonModBook.getContentsMap(this.module.contents);
|
||||||
this.chapters = AddonModBook.getTocList(this.module.contents);
|
this.chapters = AddonModBook.getTocList(this.module.contents);
|
||||||
|
@ -191,6 +164,21 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load book data from WS.
|
||||||
|
*
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async loadBookData(): Promise<void> {
|
||||||
|
this.book = await AddonModBook.getBook(this.courseId, this.module.id);
|
||||||
|
|
||||||
|
this.dataRetrieved.emit(this.book);
|
||||||
|
|
||||||
|
this.description = this.book.intro;
|
||||||
|
this.displayNavBar = this.book.navstyle != AddonModBookNavStyle.TOC_ONLY;
|
||||||
|
this.displayTitlesInNavBar = this.book.navstyle == AddonModBookNavStyle.TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a book chapter.
|
* Load a book chapter.
|
||||||
*
|
*
|
||||||
|
|
|
@ -14,10 +14,7 @@
|
||||||
|
|
||||||
import { Component, OnInit, Optional } from '@angular/core';
|
import { Component, OnInit, Optional } from '@angular/core';
|
||||||
import { CoreSilentError } from '@classes/errors/silenterror';
|
import { CoreSilentError } from '@classes/errors/silenterror';
|
||||||
import {
|
import { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component';
|
||||||
CoreCourseModuleMainResourceComponent,
|
|
||||||
CoreCourseResourceDownloadResult,
|
|
||||||
} from '@features/course/classes/main-resource-component';
|
|
||||||
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
|
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
|
||||||
import { CoreCourse } from '@features/course/services/course';
|
import { CoreCourse } from '@features/course/services/course';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
@ -81,25 +78,13 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
protected async fetchContent(refresh = false): Promise<void> {
|
protected async fetchContent(refresh = false): Promise<void> {
|
||||||
let downloadResult: CoreCourseResourceDownloadResult;
|
try {
|
||||||
const promises: Promise<void>[] = [];
|
const downloadResult = await this.downloadResourceIfNeeded(refresh);
|
||||||
|
|
||||||
promises.push(AddonModImscp.getImscp(this.courseId, this.module.id).then((imscp) => {
|
const imscp = await AddonModImscp.getImscp(this.courseId, this.module.id);
|
||||||
this.description = imscp.intro;
|
this.description = imscp.intro;
|
||||||
this.dataRetrieved.emit(imscp);
|
this.dataRetrieved.emit(imscp);
|
||||||
|
|
||||||
return;
|
|
||||||
}));
|
|
||||||
|
|
||||||
promises.push(this.downloadResourceIfNeeded(refresh).then((result) => {
|
|
||||||
downloadResult = result;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}));
|
|
||||||
|
|
||||||
try {
|
|
||||||
await Promise.all(promises);
|
|
||||||
|
|
||||||
this.items = AddonModImscp.createItemList(this.module.contents);
|
this.items = AddonModImscp.createItemList(this.module.contents);
|
||||||
|
|
||||||
if (this.items.length && typeof this.currentItem == 'undefined') {
|
if (this.items.length && typeof this.currentItem == 'undefined') {
|
||||||
|
|
|
@ -13,9 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnInit, Optional } from '@angular/core';
|
import { Component, OnInit, Optional } from '@angular/core';
|
||||||
import {
|
import { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component';
|
||||||
CoreCourseModuleMainResourceComponent,
|
|
||||||
} from '@features/course/classes/main-resource-component';
|
|
||||||
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
|
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
|
||||||
import { CoreCourse, CoreCourseWSModule } from '@features/course/services/course';
|
import { CoreCourse, CoreCourseWSModule } from '@features/course/services/course';
|
||||||
import { CoreTextUtils } from '@services/utils/text';
|
import { CoreTextUtils } from '@services/utils/text';
|
||||||
|
@ -82,70 +80,57 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
protected async fetchContent(refresh?: boolean): Promise<void> {
|
protected async fetchContent(refresh?: boolean): Promise<void> {
|
||||||
// Download the resource if it needs to be downloaded.
|
|
||||||
try {
|
try {
|
||||||
|
// Download the resource if it needs to be downloaded.
|
||||||
const downloadResult = await this.downloadResourceIfNeeded(refresh);
|
const downloadResult = await this.downloadResourceIfNeeded(refresh);
|
||||||
|
|
||||||
const promises: Promise<void>[] = [];
|
const results = await Promise.all([
|
||||||
|
this.loadPageData(),
|
||||||
|
AddonModPageHelper.getPageHtml(this.module.contents, this.module.id),
|
||||||
|
]);
|
||||||
|
|
||||||
let getPagePromise: Promise<CoreCourseWSModule | AddonModPagePage>;
|
this.contents = results[1];
|
||||||
|
this.warning = downloadResult?.failed ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error!) : '';
|
||||||
// Get the module to get the latest title and description. Data should've been updated in download.
|
|
||||||
if (this.canGetPage) {
|
|
||||||
getPagePromise = AddonModPage.getPageData(this.courseId, this.module.id);
|
|
||||||
} else {
|
|
||||||
getPagePromise = CoreCourse.getModule(this.module.id, this.courseId);
|
|
||||||
}
|
|
||||||
|
|
||||||
promises.push(getPagePromise.then((page) => {
|
|
||||||
if (!page) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.description = 'intro' in page ? page.intro : page.description;
|
|
||||||
this.dataRetrieved.emit(page);
|
|
||||||
|
|
||||||
if (!this.canGetPage) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.page = page;
|
|
||||||
|
|
||||||
// Check if description and timemodified should be displayed.
|
|
||||||
if ('displayoptions' in this.page) {
|
|
||||||
const options: Record<string, string | boolean> =
|
|
||||||
CoreTextUtils.unserialize(this.page.displayoptions) || {};
|
|
||||||
|
|
||||||
this.displayDescription = typeof options.printintro == 'undefined' ||
|
|
||||||
CoreUtils.isTrueOrOne(options.printintro);
|
|
||||||
this.displayTimemodified = typeof options.printlastmodified == 'undefined' ||
|
|
||||||
CoreUtils.isTrueOrOne(options.printlastmodified);
|
|
||||||
} else {
|
|
||||||
this.displayDescription = true;
|
|
||||||
this.displayTimemodified = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.timemodified = 'timemodified' in this.page ? this.page.timemodified : undefined;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}).catch(() => {
|
|
||||||
// Ignore errors.
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Get the page HTML.
|
|
||||||
promises.push(AddonModPageHelper.getPageHtml(this.module.contents, this.module.id).then((content) => {
|
|
||||||
|
|
||||||
this.contents = content;
|
|
||||||
this.warning = downloadResult?.failed ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error!) : '';
|
|
||||||
|
|
||||||
return;
|
|
||||||
}));
|
|
||||||
|
|
||||||
await Promise.all(promises);
|
|
||||||
} finally {
|
} finally {
|
||||||
// Pass false because downloadResourceIfNeeded already invalidates and refresh data if refresh=true.
|
this.fillContextMenu(refresh);
|
||||||
this.fillContextMenu(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load page data from WS.
|
||||||
|
*
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async loadPageData(): Promise<void> {
|
||||||
|
// Get latest title, description and some extra data. Data should've been updated in download.
|
||||||
|
const page = this.canGetPage ?
|
||||||
|
await AddonModPage.getPageData(this.courseId, this.module.id) :
|
||||||
|
await CoreCourse.getModule(this.module.id, this.courseId);
|
||||||
|
|
||||||
|
this.description = 'intro' in page ? page.intro : page.description;
|
||||||
|
this.dataRetrieved.emit(page);
|
||||||
|
|
||||||
|
if (!this.canGetPage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.page = page;
|
||||||
|
|
||||||
|
// Check if description and timemodified should be displayed.
|
||||||
|
if ('displayoptions' in this.page) {
|
||||||
|
const options: Record<string, string | boolean> =
|
||||||
|
CoreTextUtils.unserialize(this.page.displayoptions) || {};
|
||||||
|
|
||||||
|
this.displayDescription = typeof options.printintro == 'undefined' ||
|
||||||
|
CoreUtils.isTrueOrOne(options.printintro);
|
||||||
|
this.displayTimemodified = typeof options.printlastmodified == 'undefined' ||
|
||||||
|
CoreUtils.isTrueOrOne(options.printlastmodified);
|
||||||
|
} else {
|
||||||
|
this.displayDescription = true;
|
||||||
|
this.displayTimemodified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.timemodified = 'timemodified' in this.page ? this.page.timemodified : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,7 @@
|
||||||
|
|
||||||
import { Component, OnDestroy, OnInit, Optional } from '@angular/core';
|
import { Component, OnDestroy, OnInit, Optional } from '@angular/core';
|
||||||
import { CoreError } from '@classes/errors/error';
|
import { CoreError } from '@classes/errors/error';
|
||||||
import {
|
import { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component';
|
||||||
CoreCourseModuleMainResourceComponent,
|
|
||||||
} from '@features/course/classes/main-resource-component';
|
|
||||||
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
|
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
|
||||||
import { CoreCourse, CoreCourseWSModule } from '@features/course/services/course';
|
import { CoreCourse, CoreCourseWSModule } from '@features/course/services/course';
|
||||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||||
|
@ -118,13 +116,13 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
|
||||||
|
|
||||||
// Get the resource instance to get the latest name/description and to know if it's embedded.
|
// Get the resource instance to get the latest name/description and to know if it's embedded.
|
||||||
if (this.canGetResource) {
|
if (this.canGetResource) {
|
||||||
resource = await CoreUtils.ignoreErrors(AddonModResource.getResourceData(this.courseId, this.module.id));
|
resource = await AddonModResource.getResourceData(this.courseId, this.module.id);
|
||||||
this.description = resource?.intro || '';
|
this.description = resource.intro || '';
|
||||||
options = resource?.displayoptions ? CoreTextUtils.unserialize(resource.displayoptions) : {};
|
options = resource.displayoptions ? CoreTextUtils.unserialize(resource.displayoptions) : {};
|
||||||
} else {
|
} else {
|
||||||
resource = await CoreUtils.ignoreErrors(CoreCourse.getModule(this.module.id, this.courseId));
|
resource = await CoreCourse.getModule(this.module.id, this.courseId);
|
||||||
this.description = resource?.description || '';
|
this.description = resource.description || '';
|
||||||
options = resource?.customdata ? CoreTextUtils.unserialize(CoreTextUtils.parseJSON(resource.customdata)) : {};
|
options = resource.customdata ? CoreTextUtils.unserialize(CoreTextUtils.parseJSON(resource.customdata)) : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<core-iframe [src]="url"></core-iframe>
|
<core-iframe [src]="url"></core-iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ion-list *ngIf="!shouldIframe && (!shouldEmbed || !isOther)">
|
<ion-list *ngIf="url && !shouldIframe && (!shouldEmbed || !isOther)">
|
||||||
<ion-item *ngIf="shouldEmbed">
|
<ion-item *ngIf="shouldEmbed">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<img *ngIf="isImage" [alt]="name" [src]="url">
|
<img *ngIf="isImage" [alt]="name" [src]="url">
|
||||||
|
|
|
@ -26,6 +26,7 @@ import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreWSExternalWarning } from '@services/ws';
|
import { CoreWSExternalWarning } from '@services/ws';
|
||||||
import { CoreCourseContentsPage } from '../pages/contents/contents';
|
import { CoreCourseContentsPage } from '../pages/contents/contents';
|
||||||
import { CoreConstants } from '@/core/constants';
|
import { CoreConstants } from '@/core/constants';
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template class to easily create CoreCourseModuleMainComponent of activities.
|
* Template class to easily create CoreCourseModuleMainComponent of activities.
|
||||||
|
@ -211,7 +212,7 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
|
||||||
|
|
||||||
await this.fetchContent(refresh, sync, showErrors);
|
await this.fetchContent(refresh, sync, showErrors);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!refresh) {
|
if (!refresh && !CoreSites.getCurrentSite()?.isOfflineDisabled()) {
|
||||||
// Some call failed, retry without using cache since it might be a new activity.
|
// Some call failed, retry without using cache since it might be a new activity.
|
||||||
return await this.refreshContent(sync);
|
return await this.refreshContent(sync);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue