diff --git a/src/core/course/providers/helper.ts b/src/core/course/providers/helper.ts index 5bd0893d9..3c015a056 100644 --- a/src/core/course/providers/helper.ts +++ b/src/core/course/providers/helper.ts @@ -830,8 +830,13 @@ export class CoreCourseHelperProvider { moduleInfo.statusIcon = 'spinner'; break; case CoreConstants.OUTDATED: - moduleInfo.statusIcon = 'ion-android-refresh'; + moduleInfo.statusIcon = 'refresh'; break; + case CoreConstants.DOWNLOADED: + if (!this.prefetchDelegate.canCheckUpdates()) { + moduleInfo.statusIcon = 'refresh'; + break; + } default: moduleInfo.statusIcon = ''; break; diff --git a/src/core/siteaddons/components/addon-content/addon-content.ts b/src/core/siteaddons/components/addon-content/addon-content.ts index bf1d8317e..ea2ee703f 100644 --- a/src/core/siteaddons/components/addon-content/addon-content.ts +++ b/src/core/siteaddons/components/addon-content/addon-content.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, Input } from '@angular/core'; +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; import { CoreDomUtilsProvider } from '../../../../providers/utils/dom'; import { CoreSiteAddonsProvider } from '../../providers/siteaddons'; @@ -27,12 +27,17 @@ export class CoreSiteAddonsAddonContentComponent implements OnInit { @Input() component: string; @Input() method: string; @Input() args: any; + @Output() onContentLoaded?: EventEmitter; // Emits an event when the content is loaded. + @Output() onLoadingContent?: EventEmitter; // Emits an event when starts to load the content. content: string; // Content. javascript: string; // Javascript to execute. dataLoaded: boolean; - constructor(protected domUtils: CoreDomUtilsProvider, protected siteAddonsProvider: CoreSiteAddonsProvider) { } + constructor(protected domUtils: CoreDomUtilsProvider, protected siteAddonsProvider: CoreSiteAddonsProvider) { + this.onContentLoaded = new EventEmitter(); + this.onLoadingContent = new EventEmitter(); + } /** * Component being initialized. @@ -46,12 +51,17 @@ export class CoreSiteAddonsAddonContentComponent implements OnInit { /** * Fetches the content to render. * + * @param {boolean} [refresh] Whether the user is refreshing. * @return {Promise} Promise resolved when done. */ - fetchContent(): Promise { + fetchContent(refresh?: boolean): Promise { + this.onLoadingContent.emit(refresh); + return this.siteAddonsProvider.getContent(this.component, this.method, this.args).then((result) => { this.content = result.html; this.javascript = result.javascript; + + this.onContentLoaded.emit(refresh); }).catch((error) => { this.domUtils.showErrorModalDefault(error, 'core.errorloadingcontent', true); }); @@ -62,7 +72,7 @@ export class CoreSiteAddonsAddonContentComponent implements OnInit { */ refreshData(): Promise { return this.siteAddonsProvider.invalidateContent(this.component, this.method, this.args).finally(() => { - return this.fetchContent(); + return this.fetchContent(true); }); } diff --git a/src/core/siteaddons/components/components.module.ts b/src/core/siteaddons/components/components.module.ts index 929c13dd5..5b7747e16 100644 --- a/src/core/siteaddons/components/components.module.ts +++ b/src/core/siteaddons/components/components.module.ts @@ -15,6 +15,7 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { IonicModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; import { CoreComponentsModule } from '../../../components/components.module'; import { CoreCompileHtmlComponentsModule } from '../../../components/compile-html/compile-html.module'; import { CoreSiteAddonsAddonContentComponent } from './addon-content/addon-content'; @@ -29,7 +30,8 @@ import { CoreSiteAddonsModuleIndexComponent } from './module-index/module-index' CommonModule, IonicModule, CoreComponentsModule, - CoreCompileHtmlComponentsModule + CoreCompileHtmlComponentsModule, + TranslateModule.forChild() ], providers: [ ], diff --git a/src/core/siteaddons/components/module-index/module-index.html b/src/core/siteaddons/components/module-index/module-index.html index 72cb07d7c..6e6ef1862 100644 --- a/src/core/siteaddons/components/module-index/module-index.html +++ b/src/core/siteaddons/components/module-index/module-index.html @@ -1,2 +1,12 @@ - + + + + + + + + + + + diff --git a/src/core/siteaddons/components/module-index/module-index.ts b/src/core/siteaddons/components/module-index/module-index.ts index b0c52f36f..19220cdd5 100644 --- a/src/core/siteaddons/components/module-index/module-index.ts +++ b/src/core/siteaddons/components/module-index/module-index.ts @@ -12,9 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, Input, ViewChild } from '@angular/core'; +import { Component, OnInit, OnDestroy, Input, ViewChild } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { CoreTextUtilsProvider } from '../../../../providers/utils/text'; import { CoreSiteAddonsProvider } from '../../providers/siteaddons'; import { CoreCourseModuleMainComponent } from '../../../course/providers/module-delegate'; +import { CoreCourseModulePrefetchDelegate } from '../../../course/providers/module-prefetch-delegate'; +import { CoreCourseHelperProvider } from '../../../course/providers/helper'; import { CoreSiteAddonsAddonContentComponent } from '../addon-content/addon-content'; /** @@ -24,7 +28,7 @@ import { CoreSiteAddonsAddonContentComponent } from '../addon-content/addon-cont selector: 'core-site-addons-module-index', templateUrl: 'module-index.html', }) -export class CoreSiteAddonsModuleIndexComponent implements OnInit, CoreCourseModuleMainComponent { +export class CoreSiteAddonsModuleIndexComponent implements OnInit, OnDestroy, CoreCourseModuleMainComponent { @Input() module: any; // The module. @Input() courseId: number; // Course ID the module belongs to. @@ -34,12 +38,27 @@ export class CoreSiteAddonsModuleIndexComponent implements OnInit, CoreCourseMod method: string; args: any; - constructor(protected siteAddonsProvider: CoreSiteAddonsProvider) { } + // Data for context menu. + externalUrl: string; + description: string; + refreshIcon: string; + prefetchStatusIcon: string; + prefetchText: string; + size: string; + + protected isDestroyed = false; + protected statusObserver; + + constructor(protected siteAddonsProvider: CoreSiteAddonsProvider, protected courseHelper: CoreCourseHelperProvider, + protected prefetchDelegate: CoreCourseModulePrefetchDelegate, protected textUtils: CoreTextUtilsProvider, + protected translate: TranslateService) { } /** * Component being initialized. */ ngOnInit(): void { + this.refreshIcon = 'spinner'; + if (this.module) { const handler = this.siteAddonsProvider.getModuleSiteAddonHandler(this.module.modname); if (handler) { @@ -50,6 +69,10 @@ export class CoreSiteAddonsModuleIndexComponent implements OnInit, CoreCourseMod cmid: this.module.id }; } + + // Get the data for the context menu. + this.description = this.module.description; + this.externalUrl = this.module.url; } } @@ -62,13 +85,65 @@ export class CoreSiteAddonsModuleIndexComponent implements OnInit, CoreCourseMod */ doRefresh(refresher?: any, done?: () => void): Promise { if (this.addonContent) { + this.refreshIcon = 'spinner'; + return Promise.resolve(this.addonContent.refreshData()).finally(() => { - refresher.complete(); + refresher && refresher.complete(); + done && done(); }); } else { - refresher.complete(); + refresher && refresher.complete(); + done && done(); return Promise.resolve(); } } + + /** + * Function called when the data of the site addon content is loaded. + */ + contentLoaded(refresh: boolean): void { + this.refreshIcon = 'refresh'; + + // Check if there is a prefetch handler for this type of module. + if (this.prefetchDelegate.getPrefetchHandlerFor(this.module)) { + this.courseHelper.fillContextMenu(this, this.module, this.courseId, refresh, this.component); + } + } + + /** + * Function called when starting to load the data of the site addon content. + */ + contentLoading(refresh: boolean): void { + this.refreshIcon = 'spinner'; + } + + /** + * Expand the description. + */ + expandDescription(): void { + this.textUtils.expandText(this.translate.instant('core.description'), this.description, this.component, this.module.id); + } + + /** + * Prefetch the module. + */ + prefetch(): void { + this.courseHelper.contextMenuPrefetch(this, this.module, this.courseId); + } + + /** + * Confirm and remove downloaded files. + */ + removeFiles(): void { + this.courseHelper.confirmAndRemoveFiles(this.module, this.courseId); + } + + /** + * Component destroyed. + */ + ngOnDestroy(): void { + this.isDestroyed = true; + this.statusObserver && this.statusObserver.off(); + } } diff --git a/src/core/siteaddons/pages/addon-page/addon-page.html b/src/core/siteaddons/pages/addon-page/addon-page.html index 14555dcec..16b323097 100644 --- a/src/core/siteaddons/pages/addon-page/addon-page.html +++ b/src/core/siteaddons/pages/addon-page/addon-page.html @@ -3,7 +3,7 @@ {{ title }} - + diff --git a/src/core/siteaddons/pages/addon-page/addon-page.module.ts b/src/core/siteaddons/pages/addon-page/addon-page.module.ts index 021766bd3..053a147b4 100644 --- a/src/core/siteaddons/pages/addon-page/addon-page.module.ts +++ b/src/core/siteaddons/pages/addon-page/addon-page.module.ts @@ -16,8 +16,6 @@ import { NgModule } from '@angular/core'; import { IonicPageModule } from 'ionic-angular'; import { TranslateModule } from '@ngx-translate/core'; import { CoreSiteAddonsAddonPage } from './addon-page'; -import { CoreComponentsModule } from '../../../../components/components.module'; -import { CoreCompileHtmlComponentsModule } from '../../../../components/compile-html/compile-html.module'; import { CoreSiteAddonsComponentsModule } from '../../components/components.module'; /** @@ -28,8 +26,6 @@ import { CoreSiteAddonsComponentsModule } from '../../components/components.modu CoreSiteAddonsAddonPage ], imports: [ - CoreComponentsModule, - CoreCompileHtmlComponentsModule, CoreSiteAddonsComponentsModule, IonicPageModule.forChild(CoreSiteAddonsAddonPage), TranslateModule.forChild() diff --git a/src/core/siteaddons/pages/addon-page/addon-page.ts b/src/core/siteaddons/pages/addon-page/addon-page.ts index 6501c247f..772c4dc91 100644 --- a/src/core/siteaddons/pages/addon-page/addon-page.ts +++ b/src/core/siteaddons/pages/addon-page/addon-page.ts @@ -14,8 +14,6 @@ import { Component, ViewChild } from '@angular/core'; import { IonicPage, NavParams } from 'ionic-angular'; -import { CoreDomUtilsProvider } from '../../../../providers/utils/dom'; -import { CoreSiteAddonsProvider } from '../../providers/siteaddons'; import { CoreSiteAddonsAddonContentComponent } from '../../components/addon-content/addon-content'; /** @@ -31,11 +29,11 @@ export class CoreSiteAddonsAddonPage { title: string; // Page title. - protected component: string; - protected method: string; - protected args: any; + component: string; + method: string; + args: any; - constructor(params: NavParams, protected domUtils: CoreDomUtilsProvider, protected siteAddonsProvider: CoreSiteAddonsProvider) { + constructor(params: NavParams) { this.title = params.get('title'); this.component = params.get('component'); this.method = params.get('method'); diff --git a/src/core/siteaddons/pages/module-index/module-index.html b/src/core/siteaddons/pages/module-index/module-index.html new file mode 100644 index 000000000..463923a47 --- /dev/null +++ b/src/core/siteaddons/pages/module-index/module-index.html @@ -0,0 +1,15 @@ + + + {{ title }} + + + + + + + + + + + + diff --git a/src/core/siteaddons/pages/module-index/module-index.module.ts b/src/core/siteaddons/pages/module-index/module-index.module.ts new file mode 100644 index 000000000..9ba33ae12 --- /dev/null +++ b/src/core/siteaddons/pages/module-index/module-index.module.ts @@ -0,0 +1,34 @@ +// (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 { CoreSiteAddonsModuleIndexPage } from './module-index'; +import { CoreSiteAddonsComponentsModule } from '../../components/components.module'; + +/** + * Module to lazy load the page. + */ +@NgModule({ + declarations: [ + CoreSiteAddonsModuleIndexPage + ], + imports: [ + CoreSiteAddonsComponentsModule, + IonicPageModule.forChild(CoreSiteAddonsModuleIndexPage), + TranslateModule.forChild() + ] +}) +export class CoreSiteAddonsAddonPageModule {} diff --git a/src/core/siteaddons/pages/module-index/module-index.ts b/src/core/siteaddons/pages/module-index/module-index.ts new file mode 100644 index 000000000..264a023e3 --- /dev/null +++ b/src/core/siteaddons/pages/module-index/module-index.ts @@ -0,0 +1,51 @@ +// (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, ViewChild } from '@angular/core'; +import { IonicPage, NavParams } from 'ionic-angular'; +import { CoreSiteAddonsModuleIndexComponent } from '../../components/module-index/module-index'; + +/** + * Page to render the index page of a module site addon. + */ +@IonicPage({ segment: 'core-site-addons-module-index-page' }) +@Component({ + selector: 'page-core-site-addons-module-index', + templateUrl: 'module-index.html', +}) +export class CoreSiteAddonsModuleIndexPage { + @ViewChild(CoreSiteAddonsModuleIndexComponent) content: CoreSiteAddonsModuleIndexComponent; + + title: string; // Page title. + + module: any; + courseId: number; + + constructor(params: NavParams) { + this.title = params.get('title'); + this.module = params.get('module'); + this.courseId = params.get('courseId'); + } + + /** + * Refresh the data. + * + * @param {any} refresher Refresher. + */ + refreshData(refresher: any): void { + this.content.doRefresh().finally(() => { + refresher.complete(); + }); + } +} diff --git a/src/core/siteaddons/providers/helper.ts b/src/core/siteaddons/providers/helper.ts index 463f5b079..65d89d0b0 100644 --- a/src/core/siteaddons/providers/helper.ts +++ b/src/core/siteaddons/providers/helper.ts @@ -265,14 +265,10 @@ export class CoreSiteAddonsHelperProvider { event.preventDefault(); event.stopPropagation(); - navCtrl.push('CoreSiteAddonsAddonPage', { + navCtrl.push('CoreSiteAddonsModuleIndexPage', { title: module.name, - component: addon.component, - method: handlerSchema.method, - args: { - courseid: courseId, - cmid: module.id - } + module: module, + courseId: courseId }, options); } };