commit
bb524a384d
|
@ -6,12 +6,13 @@ const customConfig = {
|
|||
resolve: {
|
||||
alias: {
|
||||
'@addon': resolve('./src/addon'),
|
||||
'@app': resolve('./src/app'),
|
||||
'@classes': resolve('./src/classes'),
|
||||
'@core': resolve('./src/core'),
|
||||
'@providers': resolve('./src/providers'),
|
||||
'@components': resolve('./src/components'),
|
||||
'@directives': resolve('./src/directives/directives.module'),
|
||||
'@pipes': resolve('./src/pipes/pipes.module')
|
||||
'@directives': resolve('./src/directives'),
|
||||
'@pipes': resolve('./src/pipes')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -16,8 +16,8 @@ import { NgModule } from '@angular/core';
|
|||
import { IonicPageModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CorePipesModule } from '@pipes';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CorePipesModule } from '@pipes/pipes.module';
|
||||
import { AddonCalendarEventPage } from './event';
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -16,8 +16,8 @@ import { NgModule } from '@angular/core';
|
|||
import { IonicPageModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CorePipesModule } from '@pipes';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CorePipesModule } from '@pipes/pipes.module';
|
||||
import { AddonCalendarListPage } from './list';
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -16,7 +16,7 @@ import { NgModule } from '@angular/core';
|
|||
import { IonicPageModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { AddonCalendarSettingsPage } from './settings';
|
||||
import { CorePipesModule } from '@pipes';
|
||||
import { CorePipesModule } from '@pipes/pipes.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -16,7 +16,7 @@ import { NgModule } from '@angular/core';
|
|||
import { IonicPageModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { AddonFilesListPage } from './list';
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -17,8 +17,8 @@ import { CommonModule } from '@angular/common';
|
|||
import { IonicModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CorePipesModule } from '@pipes';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CorePipesModule } from '@pipes/pipes.module';
|
||||
import { AddonMessagesDiscussionsComponent } from '../components/discussions/discussions';
|
||||
import { AddonMessagesContactsComponent } from '../components/contacts/contacts';
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ import { IonicPageModule } from 'ionic-angular';
|
|||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { AddonMessagesDiscussionPage } from './discussion';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CorePipesModule } from '@pipes';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CorePipesModule } from '@pipes/pipes.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -17,7 +17,7 @@ import { IonicPageModule } from 'ionic-angular';
|
|||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { AddonMessagesSettingsPage } from './settings';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { AddonMessagesComponentsModule } from '../../components/components.module';
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -21,6 +21,7 @@ import { AddonMessagesOfflineProvider } from './messages-offline';
|
|||
import { AddonMessagesProvider } from './messages';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreSyncProvider } from '@providers/sync';
|
||||
|
@ -37,8 +38,8 @@ export class AddonMessagesSyncProvider extends CoreSyncBaseProvider {
|
|||
protected appProvider: CoreAppProvider, private messagesOffline: AddonMessagesOfflineProvider,
|
||||
private eventsProvider: CoreEventsProvider, private messagesProvider: AddonMessagesProvider,
|
||||
private userProvider: CoreUserProvider, private translate: TranslateService, private utils: CoreUtilsProvider,
|
||||
syncProvider: CoreSyncProvider) {
|
||||
super('AddonMessagesSync', sitesProvider, loggerProvider, appProvider, syncProvider);
|
||||
syncProvider: CoreSyncProvider, protected textUtils: CoreTextUtilsProvider) {
|
||||
super('AddonMessagesSync', sitesProvider, loggerProvider, appProvider, syncProvider, textUtils);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,7 +17,7 @@ import { CommonModule } from '@angular/common';
|
|||
import { IonicModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CoreCourseComponentsModule } from '@core/course/components/components.module';
|
||||
import { AddonModBookIndexComponent } from './index/index';
|
||||
import { AddonModBookTocPopoverComponent } from './toc-popover/toc-popover';
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, OnInit, OnDestroy, Input, Output, EventEmitter, Optional } from '@angular/core';
|
||||
import { NavParams, NavController, Content, PopoverController } from 'ionic-angular';
|
||||
import { Content, PopoverController } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { IonicPageModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { AddonModBookComponentsModule } from '../../components/components.module';
|
||||
import { AddonModBookIndexPage } from './index';
|
||||
|
||||
|
|
|
@ -288,7 +288,7 @@ export class AddonModBookProvider {
|
|||
return [];
|
||||
}
|
||||
|
||||
return JSON.parse(contents[0].content);
|
||||
return this.textUtils.parseJSON(contents[0].content, []);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { NavController, NavOptions } from 'ionic-angular';
|
||||
import { AddonModBookProvider } from './book';
|
||||
import { AddonModBookIndexComponent } from '../components/index/index';
|
||||
|
@ -60,12 +60,14 @@ export class AddonModBookModuleHandler implements CoreCourseModuleHandler {
|
|||
/**
|
||||
* Get the component to render the module. This is needed to support singleactivity course format.
|
||||
* The component returned must implement CoreCourseModuleMainComponent.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course object.
|
||||
* @param {any} module The module object.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getMainComponent(course: any, module: any): any {
|
||||
getMainComponent(injector: Injector, course: any, module: any): any | Promise<any> {
|
||||
return AddonModBookIndexComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,22 +78,6 @@ export class AddonModBookPrefetchHandler extends CoreCourseModulePrefetchHandler
|
|||
return this.bookProvider.invalidateContent(moduleId, courseId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate WS calls needed to determine module status.
|
||||
*
|
||||
* @param {any} module Module.
|
||||
* @param {number} courseId Course ID the module belongs to.
|
||||
* @return {Promise<any>} Promise resolved when invalidated.
|
||||
*/
|
||||
invalidateModule(module: any, courseId: number): Promise<any> {
|
||||
const promises = [];
|
||||
|
||||
promises.push(this.bookProvider.invalidateBookData(courseId));
|
||||
promises.push(this.courseProvider.invalidateModule(module.id));
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the handler is enabled on a site level.
|
||||
*
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@core/course/providers/module-delegate';
|
||||
|
||||
/**
|
||||
|
@ -58,12 +58,14 @@ export class AddonModLabelModuleHandler implements CoreCourseModuleHandler {
|
|||
/**
|
||||
* Get the component to render the module. This is needed to support singleactivity course format.
|
||||
* The component returned must implement CoreCourseModuleMainComponent.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course object.
|
||||
* @param {any} module The module object.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getMainComponent(course: any, module: any): any {
|
||||
getMainComponent(injector: Injector, course: any, module: any): any | Promise<any> {
|
||||
// There's no need to implement this because label cannot be used in singleactivity course format.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import { CoreLocalNotificationsProvider } from '@providers/local-notifications';
|
|||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreConfigProvider } from '@providers/config';
|
||||
import { CoreConfigConstants } from '.././../../configconstants';
|
||||
import { CoreConfigConstants } from '../../../configconstants';
|
||||
|
||||
/**
|
||||
* Service to handle push notifications.
|
||||
|
|
|
@ -12,9 +12,8 @@
|
|||
// 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 { Injectable } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from
|
||||
'../../../../core/user/providers/user-profile-field-delegate';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from '@core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldCheckboxComponent } from '../component/checkbox';
|
||||
|
||||
/**
|
||||
|
@ -60,10 +59,12 @@ export class AddonUserProfileFieldCheckboxHandler implements CoreUserProfileFiel
|
|||
|
||||
/**
|
||||
* Return the Component to use to display the user profile field.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @param {Injector} injector Injector.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getComponent(): any {
|
||||
getComponent(injector: Injector): any | Promise<any> {
|
||||
return AddonUserProfileFieldCheckboxComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import { AddonUserProfileFieldDatetimeHandler } from './providers/handler';
|
|||
import { CoreUserProfileFieldDelegate } from '@core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldDatetimeComponent } from './component/datetime';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CorePipesModule } from '@pipes';
|
||||
import { CorePipesModule } from '@pipes/pipes.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -12,9 +12,8 @@
|
|||
// 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 { Injectable } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from
|
||||
'../../../../core/user/providers/user-profile-field-delegate';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from '@core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldDatetimeComponent } from '../component/datetime';
|
||||
|
||||
/**
|
||||
|
@ -62,10 +61,12 @@ export class AddonUserProfileFieldDatetimeHandler implements CoreUserProfileFiel
|
|||
|
||||
/**
|
||||
* Return the Component to use to display the user profile field.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @param {Injector} injector Injector.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getComponent(): any {
|
||||
getComponent(injector: Injector): any | Promise<any> {
|
||||
return AddonUserProfileFieldDatetimeComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import { AddonUserProfileFieldMenuHandler } from './providers/handler';
|
|||
import { CoreUserProfileFieldDelegate } from '@core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldMenuComponent } from './component/menu';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -12,9 +12,8 @@
|
|||
// 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 { Injectable } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from
|
||||
'../../../../core/user/providers/user-profile-field-delegate';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from '@core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldMenuComponent } from '../component/menu';
|
||||
|
||||
/**
|
||||
|
@ -60,10 +59,12 @@ export class AddonUserProfileFieldMenuHandler implements CoreUserProfileFieldHan
|
|||
|
||||
/**
|
||||
* Return the Component to use to display the user profile field.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @param {Injector} injector Injector.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getComponent(): any {
|
||||
getComponent(injector: Injector): any | Promise<any> {
|
||||
return AddonUserProfileFieldMenuComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,8 @@
|
|||
// 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 { Injectable } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from
|
||||
'../../../../core/user/providers/user-profile-field-delegate';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from '@core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldTextComponent } from '../component/text';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
|
||||
|
@ -57,10 +56,12 @@ export class AddonUserProfileFieldTextHandler implements CoreUserProfileFieldHan
|
|||
|
||||
/**
|
||||
* Return the Component to use to display the user profile field.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @param {Injector} injector Injector.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getComponent(): any {
|
||||
getComponent(injector: Injector): any | Promise<any> {
|
||||
return AddonUserProfileFieldTextComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import { AddonUserProfileFieldTextHandler } from './providers/handler';
|
|||
import { CoreUserProfileFieldDelegate } from '@core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldTextComponent } from './component/text';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -12,9 +12,8 @@
|
|||
// 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 { Injectable } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from
|
||||
'../../../../core/user/providers/user-profile-field-delegate';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreUserProfileFieldHandler, CoreUserProfileFieldHandlerData } from '@core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldTextareaComponent } from '../component/textarea';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
|
||||
|
@ -66,10 +65,12 @@ export class AddonUserProfileFieldTextareaHandler implements CoreUserProfileFiel
|
|||
|
||||
/**
|
||||
* Return the Component to use to display the user profile field.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @param {Injector} injector Injector.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getComponent(): any {
|
||||
getComponent(injector: Injector): any | Promise<any> {
|
||||
return AddonUserProfileFieldTextareaComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import { AddonUserProfileFieldTextareaHandler } from './providers/handler';
|
|||
import { CoreUserProfileFieldDelegate } from '@core/user/providers/user-profile-field-delegate';
|
||||
import { AddonUserProfileFieldTextareaComponent } from './component/textarea';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -49,6 +49,7 @@ import { CoreFilepoolProvider } from '@providers/filepool';
|
|||
import { CoreUpdateManagerProvider } from '@providers/update-manager';
|
||||
import { CorePluginFileDelegate } from '@providers/plugin-file-delegate';
|
||||
import { CoreSyncProvider } from '@providers/sync';
|
||||
import { CoreFileHelperProvider } from '@providers/file-helper';
|
||||
|
||||
// Core modules.
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
|
@ -64,6 +65,8 @@ import { CoreContentLinksModule } from '@core/contentlinks/contentlinks.module';
|
|||
import { CoreUserModule } from '@core/user/user.module';
|
||||
import { CoreGradesModule } from '@core/grades/grades.module';
|
||||
import { CoreSettingsModule } from '@core/settings/settings.module';
|
||||
import { CoreSitePluginsModule } from '@core/siteplugins/siteplugins.module';
|
||||
import { CoreCompileModule } from '@core/compile/compile.module';
|
||||
|
||||
// Addon modules.
|
||||
import { AddonCalendarModule } from '@addon/calendar/calendar.module';
|
||||
|
@ -79,6 +82,36 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
|
|||
return new TranslateHttpLoader(http, './assets/lang/', '.json');
|
||||
}
|
||||
|
||||
// List of providers.
|
||||
export const CORE_PROVIDERS: any[] = [
|
||||
CoreLoggerProvider,
|
||||
CoreDbProvider,
|
||||
CoreAppProvider,
|
||||
CoreConfigProvider,
|
||||
CoreLangProvider,
|
||||
CoreTextUtilsProvider,
|
||||
CoreDomUtilsProvider,
|
||||
CoreTimeUtilsProvider,
|
||||
CoreUrlUtilsProvider,
|
||||
CoreUtilsProvider,
|
||||
CoreMimetypeUtilsProvider,
|
||||
CoreInitDelegate,
|
||||
CoreFileProvider,
|
||||
CoreWSProvider,
|
||||
CoreEventsProvider,
|
||||
CoreSitesFactoryProvider,
|
||||
CoreSitesProvider,
|
||||
CoreLocalNotificationsProvider,
|
||||
CoreGroupsProvider,
|
||||
CoreCronDelegate,
|
||||
CoreFileSessionProvider,
|
||||
CoreFilepoolProvider,
|
||||
CoreUpdateManagerProvider,
|
||||
CorePluginFileDelegate,
|
||||
CoreSyncProvider,
|
||||
CoreFileHelperProvider
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
MoodleMobileApp
|
||||
|
@ -111,6 +144,8 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
|
|||
CoreUserModule,
|
||||
CoreGradesModule,
|
||||
CoreSettingsModule,
|
||||
CoreSitePluginsModule,
|
||||
CoreCompileModule,
|
||||
AddonCalendarModule,
|
||||
AddonUserProfileFieldModule,
|
||||
AddonFilesModule,
|
||||
|
@ -123,38 +158,13 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
|
|||
entryComponents: [
|
||||
MoodleMobileApp
|
||||
],
|
||||
providers: [
|
||||
providers: CORE_PROVIDERS.concat([
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: CoreInterceptor,
|
||||
multi: true,
|
||||
},
|
||||
CoreLoggerProvider,
|
||||
CoreDbProvider,
|
||||
CoreAppProvider,
|
||||
CoreConfigProvider,
|
||||
CoreLangProvider,
|
||||
CoreTextUtilsProvider,
|
||||
CoreDomUtilsProvider,
|
||||
CoreTimeUtilsProvider,
|
||||
CoreUrlUtilsProvider,
|
||||
CoreUtilsProvider,
|
||||
CoreMimetypeUtilsProvider,
|
||||
CoreInitDelegate,
|
||||
CoreFileProvider,
|
||||
CoreWSProvider,
|
||||
CoreEventsProvider,
|
||||
CoreSitesFactoryProvider,
|
||||
CoreSitesProvider,
|
||||
CoreLocalNotificationsProvider,
|
||||
CoreGroupsProvider,
|
||||
CoreCronDelegate,
|
||||
CoreFileSessionProvider,
|
||||
CoreFilepoolProvider,
|
||||
CoreUpdateManagerProvider,
|
||||
CorePluginFileDelegate,
|
||||
CoreSyncProvider
|
||||
]
|
||||
}
|
||||
])
|
||||
})
|
||||
export class AppModule {
|
||||
constructor(platform: Platform, initDelegate: CoreInitDelegate, updateManager: CoreUpdateManagerProvider,
|
||||
|
|
|
@ -16,6 +16,7 @@ import { CoreSitesProvider } from '@providers/sites';
|
|||
import { CoreSyncProvider } from '@providers/sync';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
|
||||
/**
|
||||
* Base class to create sync providers. It provides some common functions.
|
||||
|
@ -44,7 +45,8 @@ export class CoreSyncBaseProvider {
|
|||
protected syncPromises: { [siteId: string]: { [uniqueId: string]: Promise<any> } } = {};
|
||||
|
||||
constructor(component: string, protected sitesProvider: CoreSitesProvider, protected loggerProvider: CoreLoggerProvider,
|
||||
protected appProvider: CoreAppProvider, protected syncProvider: CoreSyncProvider) {
|
||||
protected appProvider: CoreAppProvider, protected syncProvider: CoreSyncProvider,
|
||||
protected textUtils: CoreTextUtilsProvider) {
|
||||
this.logger = this.loggerProvider.getInstance(component);
|
||||
this.component = component;
|
||||
}
|
||||
|
@ -115,11 +117,7 @@ export class CoreSyncBaseProvider {
|
|||
*/
|
||||
getSyncWarnings(id: string | number, siteId?: string): Promise<string[]> {
|
||||
return this.syncProvider.getSyncRecord(this.component, id, siteId).then((entry) => {
|
||||
try {
|
||||
return JSON.parse(entry.warnings);
|
||||
} catch (ex) {
|
||||
return [];
|
||||
}
|
||||
return this.textUtils.parseJSON(entry.warnings, []);
|
||||
}).catch(() => {
|
||||
return [];
|
||||
});
|
||||
|
|
|
@ -91,7 +91,7 @@ export class CoreDelegate {
|
|||
// Update handlers on this cases.
|
||||
eventsProvider.on(CoreEventsProvider.LOGIN, this.updateHandlers.bind(this));
|
||||
eventsProvider.on(CoreEventsProvider.SITE_UPDATED, this.updateHandlers.bind(this));
|
||||
eventsProvider.on(CoreEventsProvider.REMOTE_ADDONS_LOADED, this.updateHandlers.bind(this));
|
||||
eventsProvider.on(CoreEventsProvider.SITE_PLUGINS_LOADED, this.updateHandlers.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -734,7 +734,7 @@ export class CoreSite {
|
|||
const expires = (entry.expirationTime - now) / 1000;
|
||||
this.logger.info(`Cached element found, id: ${id} expires in ${expires} seconds`);
|
||||
|
||||
return JSON.parse(entry.data);
|
||||
return this.textUtils.parseJSON(entry.data, {});
|
||||
}
|
||||
|
||||
return Promise.reject(null);
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { IonicModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CorePipesModule } from '@pipes';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CorePipesModule } from '@pipes/pipes.module';
|
||||
import { CoreLoadingComponent } from './loading/loading';
|
||||
import { CoreMarkRequiredComponent } from './mark-required/mark-required';
|
||||
import { CoreInputErrorsComponent } from './input-errors/input-errors';
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
// limitations under the License.
|
||||
|
||||
import {
|
||||
Component, Input, ViewChild, OnInit, OnChanges, DoCheck, ViewContainerRef, ComponentFactoryResolver,
|
||||
KeyValueDiffers, SimpleChange
|
||||
Component, Input, ViewChild, OnInit, OnChanges, DoCheck, ViewContainerRef, ComponentFactoryResolver, ComponentRef,
|
||||
KeyValueDiffers, SimpleChange, ChangeDetectorRef, Optional, ElementRef
|
||||
} from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
|
||||
/**
|
||||
|
@ -39,6 +40,10 @@ import { CoreLoggerProvider } from '@providers/logger';
|
|||
*
|
||||
* Please notice that the component that you pass needs to be declared in entryComponents of the module to be created dynamically.
|
||||
*
|
||||
* Alternatively, you can also supply a ComponentRef instead of the class of the component. In this case, the component won't
|
||||
* be instantiated because it already is, it will be attached to the view and the right data will be passed to it.
|
||||
* Passing ComponentRef is meant for site plugins, so we'll inject a NavController instance to the component.
|
||||
*
|
||||
* The contents of this component will be displayed if no component is supplied or it cannot be created. In the example above,
|
||||
* if no component is supplied then the template will show the message "Cannot render the data.".
|
||||
*/
|
||||
|
@ -62,7 +67,8 @@ export class CoreDynamicComponent implements OnInit, OnChanges, DoCheck {
|
|||
protected logger: any;
|
||||
protected differ: any; // To detect changes in the data input.
|
||||
|
||||
constructor(logger: CoreLoggerProvider, private factoryResolver: ComponentFactoryResolver, differs: KeyValueDiffers) {
|
||||
constructor(logger: CoreLoggerProvider, protected factoryResolver: ComponentFactoryResolver, differs: KeyValueDiffers,
|
||||
@Optional() protected navCtrl: NavController, protected cdr: ChangeDetectorRef, protected element: ElementRef) {
|
||||
this.logger = logger.getInstance('CoreDynamicComponent');
|
||||
this.differ = differs.find([]).create();
|
||||
}
|
||||
|
@ -128,21 +134,32 @@ export class CoreDynamicComponent implements OnInit, OnChanges, DoCheck {
|
|||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
// Create the component and add it to the container.
|
||||
const factory = this.factoryResolver.resolveComponentFactory(this.component),
|
||||
componentRef = this.container.createComponent(factory);
|
||||
if (this.component instanceof ComponentRef) {
|
||||
// A ComponentRef was supplied instead of the component class. Add it to the view.
|
||||
this.container.insert(this.component.hostView);
|
||||
this.instance = this.component.instance;
|
||||
|
||||
this.instance = componentRef.instance;
|
||||
// This feature is usually meant for site plugins. Inject some properties.
|
||||
this.instance['ChangeDetectorRef'] = this.cdr;
|
||||
this.instance['NavController'] = this.navCtrl;
|
||||
this.instance['componentContainer'] = this.element.nativeElement;
|
||||
} else {
|
||||
try {
|
||||
// Create the component and add it to the container.
|
||||
const factory = this.factoryResolver.resolveComponentFactory(this.component),
|
||||
componentRef = this.container.createComponent(factory);
|
||||
|
||||
this.setInputData();
|
||||
this.instance = componentRef.instance;
|
||||
} catch (ex) {
|
||||
this.logger.error('Error creating component', ex);
|
||||
|
||||
return true;
|
||||
} catch (ex) {
|
||||
this.logger.error('Error creating component', ex);
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.setInputData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,11 +13,10 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, Input, Output, OnInit, OnDestroy, EventEmitter } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreFileProvider } from '@providers/file';
|
||||
import { CoreFilepoolProvider } from '@providers/filepool';
|
||||
import { CoreFileHelperProvider } from '@providers/file-helper';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype';
|
||||
|
@ -36,7 +35,6 @@ export class CoreFileComponent implements OnInit, OnDestroy {
|
|||
@Input() file: any; // The file. Must have a property 'filename' and a 'fileurl' or 'url'
|
||||
@Input() component?: string; // Component the file belongs to.
|
||||
@Input() componentId?: string | number; // Component ID.
|
||||
@Input() timemodified?: number; // If set, the value will be used to check if the file is outdated.
|
||||
@Input() canDelete?: boolean | string; // Whether file can be deleted.
|
||||
@Input() alwaysDownload?: boolean | string; // Whether it should always display the refresh button when the file is downloaded.
|
||||
// Use it for files that you cannot determine if they're outdated or not.
|
||||
|
@ -52,12 +50,14 @@ export class CoreFileComponent implements OnInit, OnDestroy {
|
|||
protected fileUrl: string;
|
||||
protected siteId: string;
|
||||
protected fileSize: number;
|
||||
protected state: string;
|
||||
protected timemodified: number;
|
||||
protected observer;
|
||||
|
||||
constructor(private translate: TranslateService, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider,
|
||||
private domUtils: CoreDomUtilsProvider, private filepoolProvider: CoreFilepoolProvider,
|
||||
private fileProvider: CoreFileProvider, private appProvider: CoreAppProvider,
|
||||
private mimeUtils: CoreMimetypeUtilsProvider, private eventsProvider: CoreEventsProvider) {
|
||||
constructor(private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider, private domUtils: CoreDomUtilsProvider,
|
||||
private filepoolProvider: CoreFilepoolProvider, private appProvider: CoreAppProvider,
|
||||
private fileHelper: CoreFileHelperProvider, private mimeUtils: CoreMimetypeUtilsProvider,
|
||||
private eventsProvider: CoreEventsProvider) {
|
||||
this.onDelete = new EventEmitter();
|
||||
}
|
||||
|
||||
|
@ -68,9 +68,9 @@ export class CoreFileComponent implements OnInit, OnDestroy {
|
|||
this.canDelete = this.utils.isTrueOrOne(this.canDelete);
|
||||
this.alwaysDownload = this.utils.isTrueOrOne(this.alwaysDownload);
|
||||
this.canDownload = this.utils.isTrueOrOne(this.canDownload);
|
||||
this.timemodified = this.timemodified || 0;
|
||||
|
||||
this.fileUrl = this.file.fileurl || this.file.url;
|
||||
this.fileUrl = this.fileHelper.getFileUrl(this.file);
|
||||
this.timemodified = this.fileHelper.getFileTimemodified(this.file);
|
||||
this.siteId = this.sitesProvider.getCurrentSiteId();
|
||||
this.fileSize = this.file.filesize;
|
||||
this.fileName = this.file.filename;
|
||||
|
@ -102,6 +102,7 @@ export class CoreFileComponent implements OnInit, OnDestroy {
|
|||
return this.filepoolProvider.getFileStateByUrl(this.siteId, this.fileUrl, this.timemodified).then((state) => {
|
||||
const canDownload = this.sitesProvider.getCurrentSite().canDownloadFiles();
|
||||
|
||||
this.state = state;
|
||||
this.isDownloaded = state === CoreConstants.DOWNLOADED || state === CoreConstants.OUTDATED;
|
||||
this.isDownloading = canDownload && state === CoreConstants.DOWNLOADING;
|
||||
this.showDownload = canDownload && (state === CoreConstants.NOT_DOWNLOADED || state === CoreConstants.OUTDATED ||
|
||||
|
@ -109,123 +110,19 @@ export class CoreFileComponent implements OnInit, OnDestroy {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the file.
|
||||
*
|
||||
* @return {Promise<string>} Promise resolved when file is downloaded.
|
||||
*/
|
||||
protected downloadFile(): Promise<string> {
|
||||
if (!this.sitesProvider.getCurrentSite().canDownloadFiles()) {
|
||||
this.domUtils.showErrorModal('core.cannotdownloadfiles', true);
|
||||
|
||||
return Promise.reject(null);
|
||||
}
|
||||
|
||||
this.isDownloading = true;
|
||||
|
||||
return this.filepoolProvider.downloadUrl(this.siteId, this.fileUrl, false, this.component, this.componentId,
|
||||
this.timemodified, undefined, undefined, this.file).catch(() => {
|
||||
|
||||
// Call calculateState to make sure we have the right state.
|
||||
return this.calculateState().then(() => {
|
||||
if (this.isDownloaded) {
|
||||
return this.filepoolProvider.getInternalUrlByUrl(this.siteId, this.fileUrl);
|
||||
} else {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to open a file, downloading it if needed.
|
||||
*
|
||||
* @return {Promise<string>} Promise resolved when file is opened.
|
||||
*/
|
||||
protected openFile(): Promise<any> {
|
||||
const fixedUrl = this.sitesProvider.getCurrentSite().fixPluginfileURL(this.fileUrl);
|
||||
let promise;
|
||||
|
||||
if (this.fileProvider.isAvailable()) {
|
||||
promise = Promise.resolve().then(() => {
|
||||
// The file system is available.
|
||||
const isWifi = !this.appProvider.isNetworkAccessLimited(),
|
||||
isOnline = this.appProvider.isOnline();
|
||||
|
||||
if (this.isDownloaded && !this.showDownload) {
|
||||
// File is downloaded, get the local file URL.
|
||||
return this.filepoolProvider.getUrlByUrl(this.siteId, this.fileUrl,
|
||||
this.component, this.componentId, this.timemodified, false, false, this.file);
|
||||
} else {
|
||||
if (!isOnline && !this.isDownloaded) {
|
||||
// Not downloaded and user is offline, reject.
|
||||
return Promise.reject(this.translate.instant('core.networkerrormsg'));
|
||||
}
|
||||
|
||||
const isDownloading = this.isDownloading;
|
||||
this.isDownloading = true; // This check could take a while, show spinner.
|
||||
|
||||
return this.filepoolProvider.shouldDownloadBeforeOpen(fixedUrl, this.fileSize).then(() => {
|
||||
if (isDownloading) {
|
||||
// It's already downloading, stop.
|
||||
return;
|
||||
}
|
||||
|
||||
// Download and then return the local URL.
|
||||
return this.downloadFile();
|
||||
}, () => {
|
||||
// Start the download if in wifi, but return the URL right away so the file is opened.
|
||||
if (isWifi && isOnline) {
|
||||
this.downloadFile();
|
||||
}
|
||||
|
||||
if (isDownloading || !this.isDownloaded || isOnline) {
|
||||
// Not downloaded or outdated and online, return the online URL.
|
||||
return fixedUrl;
|
||||
} else {
|
||||
// Outdated but offline, so we return the local URL.
|
||||
return this.filepoolProvider.getUrlByUrl(this.siteId, this.fileUrl,
|
||||
this.component, this.componentId, this.timemodified, false, false, this.file);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Use the online URL.
|
||||
promise = Promise.resolve(fixedUrl);
|
||||
}
|
||||
|
||||
return promise.then((url) => {
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (url.indexOf('http') === 0) {
|
||||
return this.utils.openOnlineFile(url).catch((error) => {
|
||||
// Error opening the file, some apps don't allow opening online files.
|
||||
if (!this.fileProvider.isAvailable()) {
|
||||
return Promise.reject(error);
|
||||
} else if (this.isDownloading) {
|
||||
return Promise.reject(this.translate.instant('core.erroropenfiledownloading'));
|
||||
}
|
||||
|
||||
let subPromise;
|
||||
|
||||
if (status === CoreConstants.NOT_DOWNLOADED) {
|
||||
// File is not downloaded, download and then return the local URL.
|
||||
subPromise = this.downloadFile();
|
||||
} else {
|
||||
// File is outdated and can't be opened in online, return the local URL.
|
||||
subPromise = this.filepoolProvider.getInternalUrlByUrl(this.siteId, this.fileUrl);
|
||||
}
|
||||
|
||||
return subPromise.then((url) => {
|
||||
return this.utils.openFile(url);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return this.utils.openFile(url);
|
||||
return this.fileHelper.downloadAndOpenFile(this.file, this.component, this.componentId, this.state, (event) => {
|
||||
if (event && event.calculating) {
|
||||
// The process is calculating some data required for the download, show the spinner.
|
||||
this.isDownloading = true;
|
||||
}
|
||||
}).catch((error) => {
|
||||
this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
// Code based on https://github.com/martinpritchardelevate/ionic-split-pane-demo
|
||||
|
||||
import { Component, ViewChild, Input, ElementRef, OnInit } from '@angular/core';
|
||||
import { Component, ViewChild, Input, ElementRef, OnInit, Optional } from '@angular/core';
|
||||
import { NavController, Nav } from 'ionic-angular';
|
||||
|
||||
/**
|
||||
|
@ -54,7 +54,7 @@ export class CoreSplitViewComponent implements OnInit {
|
|||
// Empty placeholder for the 'detail' page.
|
||||
detailPage: any = null;
|
||||
|
||||
constructor(private masterNav: NavController, element: ElementRef) {
|
||||
constructor(@Optional() private masterNav: NavController, element: ElementRef) {
|
||||
this.element = element.nativeElement;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// (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 { CoreCompileProvider } from './providers/compile';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
],
|
||||
imports: [
|
||||
],
|
||||
providers: [
|
||||
CoreCompileProvider
|
||||
]
|
||||
})
|
||||
export class CoreCompileModule { }
|
|
@ -0,0 +1,30 @@
|
|||
// (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 { CommonModule } from '@angular/common';
|
||||
import { CoreCompileHtmlComponent } from './compile-html';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
CoreCompileHtmlComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule
|
||||
],
|
||||
exports: [
|
||||
CoreCompileHtmlComponent
|
||||
]
|
||||
})
|
||||
export class CoreCompileHtmlComponentModule {}
|
|
@ -0,0 +1,122 @@
|
|||
// (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, OnInit, OnChanges, OnDestroy, ViewContainerRef, ViewChild, ComponentRef, SimpleChange, ChangeDetectorRef,
|
||||
ElementRef, Optional
|
||||
} from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreCompileProvider } from '../../providers/compile';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
/**
|
||||
* This component has a behaviour similar to $compile for AngularJS. Given an HTML code, it will compile it so all its
|
||||
* components and directives are instantiated.
|
||||
*
|
||||
* IMPORTANT: Use this component only if it is a must. It will create and compile a new component and module everytime this
|
||||
* component is used, so it can slow down the app.
|
||||
*
|
||||
* This component has its own module to prevent circular dependencies. If you want to use it,
|
||||
* you need to import CoreCompileHtmlComponentModule.
|
||||
*
|
||||
* You can provide some Javascript code (as text) to be executed inside the component. The context of the javascript code (this)
|
||||
* will be the component instance created to compile the template. This means your javascript code can interact with the template.
|
||||
* The component instance will have most of the providers so you can use them in the javascript code. E.g. if you want to use
|
||||
* CoreAppProvider, you can do it with "this.CoreAppProvider".
|
||||
*/
|
||||
@Component({
|
||||
selector: 'core-compile-html',
|
||||
template: '<ng-container #dynamicComponent></ng-container>'
|
||||
})
|
||||
export class CoreCompileHtmlComponent implements OnChanges, OnDestroy {
|
||||
@Input() text: string; // The HTML text to display.
|
||||
@Input() javascript: string; // The Javascript to execute in the component.
|
||||
@Input() jsData; // Data to pass to the fake component.
|
||||
|
||||
// Get the container where to put the content.
|
||||
@ViewChild('dynamicComponent', { read: ViewContainerRef }) container: ViewContainerRef;
|
||||
|
||||
protected componentRef: ComponentRef<any>;
|
||||
protected element;
|
||||
componentObservable: BehaviorSubject<any>; // An observable to notify observers when the component is instantiated.
|
||||
|
||||
constructor(protected compileProvider: CoreCompileProvider, protected cdr: ChangeDetectorRef, element: ElementRef,
|
||||
@Optional() protected navCtrl: NavController) {
|
||||
this.element = element.nativeElement;
|
||||
this.componentObservable = new BehaviorSubject<any>(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect changes on input properties.
|
||||
*/
|
||||
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
|
||||
if ((changes.text || changes.javascript) && this.text) {
|
||||
// Create a new component and a new module.
|
||||
this.compileProvider.createAndCompileComponent(this.text, this.getComponentClass()).then((factory) => {
|
||||
// Destroy previous components.
|
||||
this.componentRef && this.componentRef.destroy();
|
||||
|
||||
if (factory) {
|
||||
// Create the component.
|
||||
this.componentRef = this.container.createComponent(factory);
|
||||
this.componentObservable.next(this.componentRef.instance);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Component destroyed.
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.componentRef && this.componentRef.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a class that defines the dynamic component.
|
||||
*
|
||||
* @return {any} The component class.
|
||||
*/
|
||||
protected getComponentClass(): any {
|
||||
// tslint:disable: no-this-assignment
|
||||
const compileInstance = this;
|
||||
|
||||
// Create the component, using the text as the template.
|
||||
return class CoreCompileHtmlFakeComponent implements OnInit {
|
||||
constructor() {
|
||||
// If there is some javascript to run, prepare the instance.
|
||||
if (compileInstance.javascript) {
|
||||
compileInstance.compileProvider.injectLibraries(this);
|
||||
|
||||
// Add some more components and classes.
|
||||
this['ChangeDetectorRef'] = compileInstance.cdr;
|
||||
this['NavController'] = compileInstance.navCtrl;
|
||||
this['componentContainer'] = compileInstance.element;
|
||||
}
|
||||
|
||||
// Add the data passed to the component.
|
||||
for (const name in compileInstance.jsData) {
|
||||
this[name] = compileInstance.jsData[name];
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
// If there is some javascript to run, do it now.
|
||||
if (compileInstance.javascript) {
|
||||
compileInstance.compileProvider.executeJavascript(this, compileInstance.javascript);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
// (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 { Injectable, Injector, Component, NgModule, Compiler, ComponentFactory, ComponentRef, NgModuleRef } from '@angular/core';
|
||||
import {
|
||||
Platform, ActionSheetController, AlertController, LoadingController, ModalController, PopoverController, ToastController,
|
||||
IonicModule
|
||||
} from 'ionic-angular';
|
||||
import { TranslateService, TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
|
||||
// Import core providers.
|
||||
import { CORE_PROVIDERS } from '@app/app.module';
|
||||
import { CORE_CONTENTLINKS_PROVIDERS } from '@core/contentlinks/contentlinks.module';
|
||||
import { CORE_COURSE_PROVIDERS } from '@core/course/course.module';
|
||||
import { CORE_COURSES_PROVIDERS } from '@core/courses/courses.module';
|
||||
import { CORE_FILEUPLOADER_PROVIDERS } from '@core/fileuploader/fileuploader.module';
|
||||
import { CORE_GRADES_PROVIDERS } from '@core/grades/grades.module';
|
||||
import { CORE_LOGIN_PROVIDERS } from '@core/login/login.module';
|
||||
import { CORE_MAINMENU_PROVIDERS } from '@core/mainmenu/mainmenu.module';
|
||||
import { CORE_SHAREDFILES_PROVIDERS } from '@core/sharedfiles/sharedfiles.module';
|
||||
import { CORE_SITEHOME_PROVIDERS } from '@core/sitehome/sitehome.module';
|
||||
import { CORE_USER_PROVIDERS } from '@core/user/user.module';
|
||||
import { IONIC_NATIVE_PROVIDERS } from '@core/emulator/emulator.module';
|
||||
|
||||
// Import only this provider to prevent circular dependencies.
|
||||
import { CoreSitePluginsProvider } from '@core/siteplugins/providers/siteplugins';
|
||||
|
||||
// Import other libraries and providers.
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { FormBuilder, Validators } from '@angular/forms';
|
||||
import { Http } from '@angular/http';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { CoreConfigConstants } from '../../../configconstants';
|
||||
import { CoreConstants } from '@core/constants';
|
||||
import * as moment from 'moment';
|
||||
import { Md5 } from 'ts-md5/dist/md5';
|
||||
|
||||
// Import core classes that can be useful for site plugins.
|
||||
import { CoreSyncBaseProvider } from '@classes/base-sync';
|
||||
import { CoreCache } from '@classes/cache';
|
||||
import { CoreDelegate } from '@classes/delegate';
|
||||
import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksModuleGradeHandler } from '@core/contentlinks/classes/module-grade-handler';
|
||||
import { CoreContentLinksModuleIndexHandler } from '@core/contentlinks/classes/module-index-handler';
|
||||
import { CoreCourseModulePrefetchHandlerBase } from '@core/course/classes/module-prefetch-handler';
|
||||
|
||||
// Import all modules that define components, directives and pipes.
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CorePipesModule } from '@pipes/pipes.module';
|
||||
import { CoreCourseComponentsModule } from '@core/course/components/components.module';
|
||||
import { CoreCourseDirectivesModule } from '@core/course/directives/directives.module';
|
||||
import { CoreCoursesComponentsModule } from '@core/courses/components/components.module';
|
||||
import { CoreSitePluginsDirectivesModule } from '@core/siteplugins/directives/directives.module';
|
||||
import { CoreSiteHomeComponentsModule } from '@core/sitehome/components/components.module';
|
||||
import { CoreUserComponentsModule } from '@core/user/components/components.module';
|
||||
|
||||
// Import some components listed in entryComponents so they can be injected dynamically.
|
||||
import { CoreCourseUnsupportedModuleComponent } from '@core/course/components/unsupported-module/unsupported-module';
|
||||
import { CoreCourseFormatSingleActivityComponent } from '@core/course/formats/singleactivity/components/singleactivity';
|
||||
import { CoreSitePluginsModuleIndexComponent } from '@core/siteplugins/components/module-index/module-index';
|
||||
import { CoreSitePluginsCourseOptionComponent } from '@core/siteplugins/components/course-option/course-option';
|
||||
import { CoreSitePluginsCourseFormatComponent } from '@core/siteplugins/components/course-format/course-format';
|
||||
|
||||
/**
|
||||
* Service to provide functionalities regarding compiling dynamic HTML and Javascript.
|
||||
*/
|
||||
@Injectable()
|
||||
export class CoreCompileProvider {
|
||||
|
||||
protected logger;
|
||||
|
||||
// Other Ionic/Angular providers that don't depend on where they are injected.
|
||||
protected OTHER_PROVIDERS = [
|
||||
TranslateService, Http, HttpClient, Platform, DomSanitizer, ActionSheetController, AlertController, LoadingController,
|
||||
ModalController, PopoverController, ToastController, FormBuilder
|
||||
];
|
||||
|
||||
// List of imports for dynamic module. Since the template can have any component we need to import all core components modules.
|
||||
protected IMPORTS = [
|
||||
IonicModule, TranslateModule.forChild(), CoreComponentsModule, CoreDirectivesModule, CorePipesModule,
|
||||
CoreCourseComponentsModule, CoreCoursesComponentsModule, CoreSiteHomeComponentsModule, CoreUserComponentsModule,
|
||||
CoreCourseDirectivesModule, CoreSitePluginsDirectivesModule
|
||||
];
|
||||
|
||||
constructor(protected injector: Injector, logger: CoreLoggerProvider, protected compiler: Compiler) {
|
||||
this.logger = logger.getInstance('CoreCompileProvider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and compile a dynamic component.
|
||||
*
|
||||
* @param {string} template The template of the component.
|
||||
* @param {any} componentClass The JS class of the component.
|
||||
* @return {Promise<ComponentFactory<any>>} Promise resolved with the factory to instantiate the component.
|
||||
*/
|
||||
createAndCompileComponent(template: string, componentClass: any): Promise<ComponentFactory<any>> {
|
||||
// Create the component using the template and the class.
|
||||
const component = Component({
|
||||
template: template
|
||||
})
|
||||
(componentClass);
|
||||
|
||||
// Now create the module containing the component.
|
||||
const module = NgModule({imports: this.IMPORTS, declarations: [component]})(class {});
|
||||
|
||||
// Compile the module and the component.
|
||||
return this.compiler.compileModuleAndAllComponentsAsync(module).then((factories) => {
|
||||
// Search and return the factory of the component we just created.
|
||||
for (const i in factories.componentFactories) {
|
||||
const factory = factories.componentFactories[i];
|
||||
if (factory.componentType == component) {
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Eval some javascript using the context of the function.
|
||||
*
|
||||
* @param {string} javascript The javascript to eval.
|
||||
* @return {any} Result of the eval.
|
||||
*/
|
||||
protected evalInContext(javascript: string): any {
|
||||
// tslint:disable: no-eval
|
||||
return eval(javascript);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute some javascript code, using a certain instance as the context.
|
||||
*
|
||||
* @param {any} instance Instance to use as the context. In the JS code, "this" will be this instance.
|
||||
* @param {string} javascript The javascript code to eval.
|
||||
* @return {any} Result of the javascript execution.
|
||||
*/
|
||||
executeJavascript(instance: any, javascript: string): any {
|
||||
try {
|
||||
return this.evalInContext.call(instance, javascript);
|
||||
} catch (ex) {
|
||||
this.logger.error('Error evaluating javascript', ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject all the core libraries in a certain object.
|
||||
*
|
||||
* @param {any} instance The instance where to inject the libraries.
|
||||
*/
|
||||
injectLibraries(instance: any): void {
|
||||
const providers = (<any[]> CORE_PROVIDERS).concat(CORE_CONTENTLINKS_PROVIDERS).concat(CORE_COURSE_PROVIDERS)
|
||||
.concat(CORE_COURSES_PROVIDERS).concat(CORE_FILEUPLOADER_PROVIDERS).concat(CORE_GRADES_PROVIDERS)
|
||||
.concat(CORE_LOGIN_PROVIDERS).concat(CORE_MAINMENU_PROVIDERS).concat(CORE_SHAREDFILES_PROVIDERS)
|
||||
.concat(CORE_SITEHOME_PROVIDERS).concat([CoreSitePluginsProvider]).concat(CORE_USER_PROVIDERS)
|
||||
.concat(IONIC_NATIVE_PROVIDERS).concat(this.OTHER_PROVIDERS);
|
||||
|
||||
// We cannot inject anything to this constructor. Use the Injector to inject all the providers into the instance.
|
||||
for (const i in providers) {
|
||||
const providerDef = providers[i];
|
||||
if (typeof providerDef == 'function' && providerDef.name) {
|
||||
try {
|
||||
// Inject the provider to the instance. We use the class name as the property name.
|
||||
instance[providerDef.name] = this.injector.get(providerDef);
|
||||
} catch (ex) {
|
||||
this.logger.warn('Error injecting provider', providerDef.name, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inject current service.
|
||||
instance['CoreCompileProvider'] = this;
|
||||
|
||||
// Add some final classes.
|
||||
instance['injector'] = this.injector;
|
||||
instance['Validators'] = Validators;
|
||||
instance['CoreConfigConstants'] = CoreConfigConstants;
|
||||
instance['CoreConstants'] = CoreConstants;
|
||||
instance['moment'] = moment;
|
||||
instance['Md5'] = Md5;
|
||||
instance['CoreSyncBaseProvider'] = CoreSyncBaseProvider;
|
||||
instance['CoreCache'] = CoreCache;
|
||||
instance['CoreDelegate'] = CoreDelegate;
|
||||
instance['CoreContentLinksHandlerBase'] = CoreContentLinksHandlerBase;
|
||||
instance['CoreContentLinksModuleGradeHandler'] = CoreContentLinksModuleGradeHandler;
|
||||
instance['CoreContentLinksModuleIndexHandler'] = CoreContentLinksModuleIndexHandler;
|
||||
instance['CoreCourseModulePrefetchHandlerBase'] = CoreCourseModulePrefetchHandlerBase;
|
||||
instance['CoreCourseUnsupportedModuleComponent'] = CoreCourseUnsupportedModuleComponent;
|
||||
instance['CoreCourseFormatSingleActivityComponent'] = CoreCourseFormatSingleActivityComponent;
|
||||
instance['CoreSitePluginsModuleIndexComponent'] = CoreSitePluginsModuleIndexComponent;
|
||||
instance['CoreSitePluginsCourseOptionComponent'] = CoreSitePluginsCourseOptionComponent;
|
||||
instance['CoreSitePluginsCourseFormatComponent'] = CoreSitePluginsCourseFormatComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a dynamic component.
|
||||
*
|
||||
* @param {string} template The template of the component.
|
||||
* @param {any} componentClass The JS class of the component.
|
||||
* @param {Injector} [injector] The injector to use. It's recommended to pass it so NavController and similar can be injected.
|
||||
* @return {Promise<ComponentRef<any>>} Promise resolved with the component instance.
|
||||
*/
|
||||
instantiateDynamicComponent(template: string, componentClass: any, injector?: Injector): Promise<ComponentRef<any>> {
|
||||
injector = injector || this.injector;
|
||||
|
||||
return this.createAndCompileComponent(template, componentClass).then((factory) => {
|
||||
if (factory) {
|
||||
// Create and return the component.
|
||||
return factory.create(injector, undefined, undefined, injector.get(NgModuleRef));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ import { CoreContentLinksAction } from '../providers/delegate';
|
|||
import { CoreContentLinksHandlerBase } from './base-handler';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreCourseHelperProvider } from '../../course/providers/helper';
|
||||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||
|
||||
/**
|
||||
* Handler to handle URLs pointing to the grade of a module.
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { CoreContentLinksAction } from '../providers/delegate';
|
||||
import { CoreContentLinksHandlerBase } from './base-handler';
|
||||
import { CoreCourseHelperProvider } from '../../course/providers/helper';
|
||||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||
|
||||
/**
|
||||
* Handler to handle URLs pointing to the index of a module.
|
||||
|
|
|
@ -16,14 +16,17 @@ import { NgModule } from '@angular/core';
|
|||
import { CoreContentLinksDelegate } from './providers/delegate';
|
||||
import { CoreContentLinksHelperProvider } from './providers/helper';
|
||||
|
||||
// List of providers.
|
||||
export const CORE_CONTENTLINKS_PROVIDERS = [
|
||||
CoreContentLinksDelegate,
|
||||
CoreContentLinksHelperProvider
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [
|
||||
],
|
||||
providers: [
|
||||
CoreContentLinksDelegate,
|
||||
CoreContentLinksHelperProvider
|
||||
],
|
||||
providers: CORE_CONTENTLINKS_PROVIDERS,
|
||||
exports: []
|
||||
})
|
||||
export class CoreContentLinksModule {}
|
||||
|
|
|
@ -17,7 +17,7 @@ import { IonicPageModule } from 'ionic-angular';
|
|||
import { CoreContentLinksChooseSitePage } from './choose-site';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -23,10 +23,11 @@ import { CoreSitesProvider } from '@providers/sites';
|
|||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreUrlUtilsProvider } from '@providers/utils/url';
|
||||
import { CoreLoginHelperProvider } from '../../login/providers/helper';
|
||||
import { CoreLoginHelperProvider } from '@core/login/providers/helper';
|
||||
import { CoreContentLinksDelegate, CoreContentLinksAction } from './delegate';
|
||||
import { CoreConstants } from '../../constants';
|
||||
import { CoreConstants } from '@core/constants';
|
||||
import { CoreConfigConstants } from '../../../configconstants';
|
||||
import { CoreSitePluginsProvider } from '@core/siteplugins/providers/siteplugins';
|
||||
|
||||
/**
|
||||
* Service that provides some features regarding content links.
|
||||
|
@ -38,7 +39,8 @@ export class CoreContentLinksHelperProvider {
|
|||
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, private loginHelper: CoreLoginHelperProvider,
|
||||
private contentLinksDelegate: CoreContentLinksDelegate, private appProvider: CoreAppProvider,
|
||||
private domUtils: CoreDomUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private translate: TranslateService,
|
||||
private initDelegate: CoreInitDelegate, eventsProvider: CoreEventsProvider, private textUtils: CoreTextUtilsProvider) {
|
||||
private initDelegate: CoreInitDelegate, eventsProvider: CoreEventsProvider, private textUtils: CoreTextUtilsProvider,
|
||||
private sitePluginsProvider: CoreSitePluginsProvider) {
|
||||
this.logger = logger.getInstance('CoreContentLinksHelperProvider');
|
||||
|
||||
// Listen for app launched URLs. If we receive one, check if it's a content link.
|
||||
|
@ -144,7 +146,6 @@ export class CoreContentLinksHelperProvider {
|
|||
return this.sitesProvider.checkSite(siteUrl).then((result) => {
|
||||
// Site exists. We'll allow to add it.
|
||||
const ssoNeeded = this.loginHelper.isSSOLoginNeeded(result.code),
|
||||
hasRemoteAddonsLoaded = false,
|
||||
pageName = 'CoreLoginCredentialsPage',
|
||||
pageParams = {
|
||||
siteUrl: result.siteUrl,
|
||||
|
@ -152,7 +153,8 @@ export class CoreContentLinksHelperProvider {
|
|||
urlToOpen: url,
|
||||
siteConfig: result.config
|
||||
};
|
||||
let promise;
|
||||
let promise,
|
||||
hasSitePluginsLoaded = false;
|
||||
|
||||
modal.dismiss(); // Dismiss modal so it doesn't collide with confirms.
|
||||
|
||||
|
@ -164,8 +166,8 @@ export class CoreContentLinksHelperProvider {
|
|||
const confirmMsg = this.translate.instant('core.contentlinks.confirmurlothersite');
|
||||
promise = this.domUtils.showConfirm(confirmMsg).then(() => {
|
||||
if (!ssoNeeded) {
|
||||
// @todo hasRemoteAddonsLoaded = $mmAddonManager.hasRemoteAddonsLoaded(); @todo
|
||||
if (hasRemoteAddonsLoaded) {
|
||||
hasSitePluginsLoaded = this.sitePluginsProvider.hasSitePluginsLoaded;
|
||||
if (hasSitePluginsLoaded) {
|
||||
// Store the redirect since logout will restart the app.
|
||||
this.appProvider.storeRedirect(CoreConstants.NO_SITE_ID, pageName, pageParams);
|
||||
}
|
||||
|
@ -181,7 +183,7 @@ export class CoreContentLinksHelperProvider {
|
|||
if (ssoNeeded) {
|
||||
this.loginHelper.confirmAndOpenBrowserForSSOLogin(
|
||||
result.siteUrl, result.code, result.service, result.config && result.config.launchurl);
|
||||
} else if (!hasRemoteAddonsLoaded) {
|
||||
} else if (!hasSitePluginsLoaded) {
|
||||
this.appProvider.getRootNavController().setRoot(pageName, pageParams);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -133,10 +133,11 @@ export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePref
|
|||
*
|
||||
* @param {any} module The module object returned by WS.
|
||||
* @param {number} courseId Course ID.
|
||||
* @param {string} [dirPath] Path of the directory where to store all the content files. @see downloadOrPrefetch.
|
||||
* @return {Promise<any>} Promise resolved when all content is downloaded.
|
||||
*/
|
||||
download(module: any, courseId: number): Promise<any> {
|
||||
return this.downloadOrPrefetch(module, courseId, false);
|
||||
download(module: any, courseId: number, dirPath?: string): Promise<any> {
|
||||
return this.downloadOrPrefetch(module, courseId, false, dirPath);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -332,8 +333,8 @@ export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePref
|
|||
}
|
||||
|
||||
/**
|
||||
* Invalidate WS calls needed to determine module status. It doesn't need to invalidate check updates.
|
||||
* It should NOT invalidate files nor all the prefetched data.
|
||||
* Invalidate WS calls needed to determine module status (usually, to check if module is downloadable).
|
||||
* It doesn't need to invalidate check updates. It should NOT invalidate files nor all the prefetched data.
|
||||
*
|
||||
* @param {any} module Module.
|
||||
* @param {number} courseId Course ID the module belongs to.
|
||||
|
@ -409,10 +410,11 @@ export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePref
|
|||
* @param {any} module Module.
|
||||
* @param {number} courseId Course ID the module belongs to.
|
||||
* @param {boolean} [single] True if we're downloading a single module, false if we're downloading a whole section.
|
||||
* @param {string} [dirPath] Path of the directory where to store all the content files. @see downloadOrPrefetch.
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
prefetch(module: any, courseId?: number, single?: boolean): Promise<any> {
|
||||
return this.downloadOrPrefetch(module, courseId, true);
|
||||
prefetch(module: any, courseId?: number, single?: boolean, dirPath?: string): Promise<any> {
|
||||
return this.downloadOrPrefetch(module, courseId, true, dirPath);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,7 +17,7 @@ import { CommonModule } from '@angular/common';
|
|||
import { IonicModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CoreCourseFormatComponent } from './format/format';
|
||||
import { CoreCourseModuleComponent } from './module/module';
|
||||
import { CoreCourseModuleCompletionComponent } from './module-completion/module-completion';
|
||||
|
|
|
@ -13,17 +13,17 @@
|
|||
// limitations under the License.
|
||||
|
||||
import {
|
||||
Component, Input, OnInit, OnChanges, OnDestroy, SimpleChange, Output, EventEmitter, ViewChildren, QueryList
|
||||
Component, Input, OnInit, OnChanges, OnDestroy, SimpleChange, Output, EventEmitter, ViewChildren, QueryList, Injector
|
||||
} from '@angular/core';
|
||||
import { Content } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreCourseProvider } from '../../../course/providers/course';
|
||||
import { CoreCourseHelperProvider } from '../../../course/providers/helper';
|
||||
import { CoreCourseFormatDelegate } from '../../../course/providers/format-delegate';
|
||||
import { CoreCourseModulePrefetchDelegate } from '../../../course/providers/module-prefetch-delegate';
|
||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||
import { CoreCourseFormatDelegate } from '@core/course/providers/format-delegate';
|
||||
import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate';
|
||||
import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-component';
|
||||
|
||||
/**
|
||||
|
@ -69,7 +69,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
|
||||
protected sectionStatusObserver;
|
||||
|
||||
constructor(private cfDelegate: CoreCourseFormatDelegate, translate: TranslateService,
|
||||
constructor(private cfDelegate: CoreCourseFormatDelegate, translate: TranslateService, private injector: Injector,
|
||||
private courseHelper: CoreCourseHelperProvider, private domUtils: CoreDomUtilsProvider,
|
||||
eventsProvider: CoreEventsProvider, private sitesProvider: CoreSitesProvider, private content: Content,
|
||||
prefetchDelegate: CoreCourseModulePrefetchDelegate) {
|
||||
|
@ -194,19 +194,29 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
protected getComponents(): void {
|
||||
if (this.course) {
|
||||
if (!this.courseFormatComponent) {
|
||||
this.courseFormatComponent = this.cfDelegate.getCourseFormatComponent(this.course);
|
||||
this.cfDelegate.getCourseFormatComponent(this.injector, this.course).then((component) => {
|
||||
this.courseFormatComponent = component;
|
||||
});
|
||||
}
|
||||
if (!this.courseSummaryComponent) {
|
||||
this.courseSummaryComponent = this.cfDelegate.getCourseSummaryComponent(this.course);
|
||||
this.cfDelegate.getCourseSummaryComponent(this.injector, this.course).then((component) => {
|
||||
this.courseSummaryComponent = component;
|
||||
});
|
||||
}
|
||||
if (!this.sectionSelectorComponent) {
|
||||
this.sectionSelectorComponent = this.cfDelegate.getSectionSelectorComponent(this.course);
|
||||
this.cfDelegate.getSectionSelectorComponent(this.injector, this.course).then((component) => {
|
||||
this.sectionSelectorComponent = component;
|
||||
});
|
||||
}
|
||||
if (!this.singleSectionComponent) {
|
||||
this.singleSectionComponent = this.cfDelegate.getSingleSectionComponent(this.course);
|
||||
this.cfDelegate.getSingleSectionComponent(this.injector, this.course).then((component) => {
|
||||
this.singleSectionComponent = component;
|
||||
});
|
||||
}
|
||||
if (!this.allSectionsComponent) {
|
||||
this.allSectionsComponent = this.cfDelegate.getAllSectionsComponent(this.course);
|
||||
this.cfDelegate.getAllSectionsComponent(this.injector, this.course).then((component) => {
|
||||
this.allSectionsComponent = component;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreUserProvider } from '../../../user/providers/user';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
|
||||
/**
|
||||
* Component to handle activity completion. It shows a checkbox with the current status, and allows manually changing
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, Input, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, Optional } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
|
@ -67,7 +67,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
protected prefetchHandler: CoreCourseModulePrefetchHandler;
|
||||
protected statusObserver;
|
||||
|
||||
constructor(protected navCtrl: NavController, protected prefetchDelegate: CoreCourseModulePrefetchDelegate,
|
||||
constructor(@Optional() protected navCtrl: NavController, protected prefetchDelegate: CoreCourseModulePrefetchDelegate,
|
||||
protected domUtils: CoreDomUtilsProvider, protected courseHelper: CoreCourseHelperProvider,
|
||||
protected eventsProvider: CoreEventsProvider, protected sitesProvider: CoreSitesProvider) {
|
||||
this.completionChanged = new EventEmitter();
|
||||
|
|
|
@ -25,6 +25,16 @@ import { CoreCourseFormatSocialModule } from './formats/social/social.module';
|
|||
import { CoreCourseFormatTopicsModule } from './formats/topics/topics.module';
|
||||
import { CoreCourseFormatWeeksModule } from './formats/weeks/weeks.module';
|
||||
|
||||
// List of providers (without handlers).
|
||||
export const CORE_COURSE_PROVIDERS: any[] = [
|
||||
CoreCourseProvider,
|
||||
CoreCourseHelperProvider,
|
||||
CoreCourseFormatDelegate,
|
||||
CoreCourseModuleDelegate,
|
||||
CoreCourseModulePrefetchDelegate,
|
||||
CoreCourseOptionsDelegate
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [
|
||||
|
@ -33,15 +43,9 @@ import { CoreCourseFormatWeeksModule } from './formats/weeks/weeks.module';
|
|||
CoreCourseFormatWeeksModule,
|
||||
CoreCourseFormatSocialModule
|
||||
],
|
||||
providers: [
|
||||
CoreCourseProvider,
|
||||
CoreCourseHelperProvider,
|
||||
CoreCourseFormatDelegate,
|
||||
CoreCourseModuleDelegate,
|
||||
CoreCourseModulePrefetchDelegate,
|
||||
CoreCourseOptionsDelegate,
|
||||
providers: CORE_COURSE_PROVIDERS.concat([
|
||||
CoreCourseFormatDefaultHandler
|
||||
],
|
||||
]),
|
||||
exports: []
|
||||
})
|
||||
export class CoreCourseModule {}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// (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 { CoreCourseDownloadModuleMainFileDirective } from './download-module-main-file';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
CoreCourseDownloadModuleMainFileDirective
|
||||
],
|
||||
imports: [],
|
||||
exports: [
|
||||
CoreCourseDownloadModuleMainFileDirective
|
||||
]
|
||||
})
|
||||
export class CoreCourseDirectivesModule {}
|
|
@ -0,0 +1,81 @@
|
|||
// (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 { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
||||
import { CoreCourseProvider } from '../providers/course';
|
||||
import { CoreCourseHelperProvider } from '../providers/helper';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
|
||||
/**
|
||||
* Directive to allow downloading and open the main file of a module.
|
||||
* When the item with this directive is clicked, the module will be downloaded (if needed) and opened.
|
||||
* This is meant for modules like mod_resource.
|
||||
*
|
||||
* This directive must receive either a module or a moduleId. If no files are provided, it will use module.contents.
|
||||
*/
|
||||
@Directive({
|
||||
selector: '[core-course-download-module-main-file]'
|
||||
})
|
||||
export class CoreCourseDownloadModuleMainFileDirective implements OnInit {
|
||||
@Input() module: any; // The module.
|
||||
@Input() moduleId: string | number; // The module ID. Required if module is not supplied.
|
||||
@Input() courseId: string | number; // The course ID.
|
||||
@Input() component?: string; // Component to link the file to.
|
||||
@Input() componentId?: string | number; // Component ID to use in conjunction with the component. If not defined, use moduleId.
|
||||
@Input() files?: any[]; // List of files of the module. If not provided, use module.contents.
|
||||
|
||||
protected element: HTMLElement;
|
||||
|
||||
constructor(element: ElementRef, protected domUtils: CoreDomUtilsProvider, protected courseHelper: CoreCourseHelperProvider,
|
||||
protected courseProvider: CoreCourseProvider) {
|
||||
this.element = element.nativeElement || element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.element.addEventListener('click', (ev: Event): void => {
|
||||
if (!this.module && !this.moduleId) {
|
||||
return;
|
||||
}
|
||||
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
const modal = this.domUtils.showModalLoading(),
|
||||
courseId = typeof this.courseId == 'string' ? parseInt(this.courseId, 10) : this.courseId;
|
||||
let promise;
|
||||
|
||||
if (this.module) {
|
||||
// We already have the module.
|
||||
promise = Promise.resolve(module);
|
||||
} else {
|
||||
// Try to get the module from cache.
|
||||
this.moduleId = typeof this.moduleId == 'string' ? parseInt(this.moduleId, 10) : this.moduleId;
|
||||
promise = this.courseProvider.getModule(this.moduleId, courseId);
|
||||
}
|
||||
|
||||
promise.then((module) => {
|
||||
const componentId = this.componentId || module.id;
|
||||
|
||||
return this.courseHelper.downloadModuleAndOpenFile(module, courseId, this.component, componentId, this.files);
|
||||
}).catch((error) => {
|
||||
this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
||||
}).finally(() => {
|
||||
modal.dismiss();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, Input, OnChanges, SimpleChange, ViewChild } from '@angular/core';
|
||||
import { Component, Input, OnChanges, SimpleChange, ViewChild, Injector } from '@angular/core';
|
||||
import { CoreCourseModuleDelegate } from '../../../providers/module-delegate';
|
||||
import { CoreCourseUnsupportedModuleComponent } from '../../../components/unsupported-module/unsupported-module';
|
||||
import { CoreDynamicComponent } from '../../../../../components/dynamic-component/dynamic-component';
|
||||
|
@ -36,7 +36,7 @@ export class CoreCourseFormatSingleActivityComponent implements OnChanges {
|
|||
componentClass: any; // The class of the component to render.
|
||||
data: any = {}; // Data to pass to the component.
|
||||
|
||||
constructor(private moduleDelegate: CoreCourseModuleDelegate) { }
|
||||
constructor(private moduleDelegate: CoreCourseModuleDelegate, private injector: Injector) { }
|
||||
|
||||
/**
|
||||
* Detect changes on input properties.
|
||||
|
@ -47,8 +47,9 @@ export class CoreCourseFormatSingleActivityComponent implements OnChanges {
|
|||
const module = this.sections[0] && this.sections[0].modules && this.sections[0].modules[0];
|
||||
if (module && !this.componentClass) {
|
||||
// We haven't obtained the class yet. Get it now.
|
||||
this.componentClass = this.moduleDelegate.getMainComponent(this.course, module) ||
|
||||
CoreCourseUnsupportedModuleComponent;
|
||||
this.moduleDelegate.getMainComponent(this.injector, this.course, module).then((component) => {
|
||||
this.componentClass = component || CoreCourseUnsupportedModuleComponent;
|
||||
});
|
||||
}
|
||||
|
||||
this.data.courseId = this.course.id;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreCourseFormatHandler } from '../../../providers/format-delegate';
|
||||
import { CoreCourseFormatSingleActivityComponent } from '../components/singleactivity';
|
||||
|
||||
|
@ -86,11 +86,13 @@ export class CoreCourseFormatSingleActivityHandler implements CoreCourseFormatHa
|
|||
* Return the Component to use to display the course format instead of using the default one.
|
||||
* Use it if you want to display a format completely different from the default one.
|
||||
* If you want to customize the default format there are several methods to customize parts of it.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getCourseFormatComponent(course: any): any {
|
||||
getCourseFormatComponent(injector: Injector, course: any): any | Promise<any> {
|
||||
return CoreCourseFormatSingleActivityComponent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<!-- One tab per handler. -->
|
||||
<core-tab *ngFor="let handler of courseHandlers" [title]="handler.data.title | translate" class="{{handler.data.class}}">
|
||||
<ng-template>
|
||||
<core-dynamic-component [component]="handler.data.component" [data]="handlerData"></core-dynamic-component>
|
||||
<core-dynamic-component [component]="handler.data.component" [data]="handler.data.componentData"></core-dynamic-component>
|
||||
</ng-template>
|
||||
</core-tab>
|
||||
</core-tabs>
|
||||
|
|
|
@ -17,7 +17,7 @@ import { IonicPageModule } from 'ionic-angular';
|
|||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreCourseSectionPage } from './section';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CoreCourseComponentsModule } from '../../components/components.module';
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, ViewChild, OnDestroy } from '@angular/core';
|
||||
import { Component, ViewChild, OnDestroy, Injector } from '@angular/core';
|
||||
import { IonicPage, NavParams, Content, NavController } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
|
@ -25,7 +25,7 @@ import { CoreCourseFormatDelegate } from '../../providers/format-delegate';
|
|||
import { CoreCourseModulePrefetchDelegate } from '../../providers/module-prefetch-delegate';
|
||||
import { CoreCourseOptionsDelegate, CoreCourseOptionsHandlerToDisplay } from '../../providers/options-delegate';
|
||||
import { CoreCourseFormatComponent } from '../../components/format/format';
|
||||
import { CoreCoursesProvider } from '../../../courses/providers/courses';
|
||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
|
||||
/**
|
||||
* Page that displays the list of courses the user is enrolled in.
|
||||
|
@ -45,7 +45,6 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
sectionId: number;
|
||||
sectionNumber: number;
|
||||
courseHandlers: CoreCourseOptionsHandlerToDisplay[];
|
||||
handlerData: any = {}; // Data to send to the handlers components.
|
||||
dataLoaded: boolean;
|
||||
downloadEnabled: boolean;
|
||||
downloadEnabledIcon = 'square-outline'; // Disabled by default.
|
||||
|
@ -64,13 +63,12 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
private courseFormatDelegate: CoreCourseFormatDelegate, private courseOptionsDelegate: CoreCourseOptionsDelegate,
|
||||
private translate: TranslateService, private courseHelper: CoreCourseHelperProvider, eventsProvider: CoreEventsProvider,
|
||||
private textUtils: CoreTextUtilsProvider, private coursesProvider: CoreCoursesProvider,
|
||||
sitesProvider: CoreSitesProvider, private navCtrl: NavController,
|
||||
sitesProvider: CoreSitesProvider, private navCtrl: NavController, private injector: Injector,
|
||||
private prefetchDelegate: CoreCourseModulePrefetchDelegate) {
|
||||
this.course = navParams.get('course');
|
||||
this.sectionId = navParams.get('sectionId');
|
||||
this.sectionNumber = navParams.get('sectionNumber');
|
||||
this.module = navParams.get('module');
|
||||
this.handlerData.courseId = this.course.id;
|
||||
|
||||
// Get the title to display. We dont't have sections yet.
|
||||
this.title = courseFormatDelegate.getCourseTitle(this.course);
|
||||
|
@ -193,7 +191,14 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
}));
|
||||
|
||||
// Load the course handlers.
|
||||
promises.push(this.courseOptionsDelegate.getHandlersToDisplay(this.course, refresh, false).then((handlers) => {
|
||||
promises.push(this.courseOptionsDelegate.getHandlersToDisplay(this.injector, this.course, refresh, false)
|
||||
.then((handlers) => {
|
||||
// Add the courseId to the handler component data.
|
||||
handlers.forEach((handler) => {
|
||||
handler.data.componentData = handler.data.componentData || {};
|
||||
handler.data.componentData.courseId = this.course.id;
|
||||
});
|
||||
|
||||
this.courseHandlers = handlers;
|
||||
}));
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ 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';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CoreCourseComponentsModule } from '../../components/components.module';
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -201,7 +201,7 @@ export class CoreCourseProvider {
|
|||
* @return {Promise<any>} Promise resolved with the module.
|
||||
*/
|
||||
getModule(moduleId: number, courseId?: number, sectionId?: number, preferCache?: boolean, ignoreCache?: boolean,
|
||||
siteId?: string): Promise<any> {
|
||||
siteId?: string): Promise<any> {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
let promise;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreCoursesProvider } from '../../courses/providers/courses';
|
||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
import { CoreCourseFormatHandler } from './format-delegate';
|
||||
import { CoreCourseProvider } from './course';
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
|
@ -85,44 +85,54 @@ export interface CoreCourseFormatHandler extends CoreDelegateHandler {
|
|||
* Return the Component to use to display the course format instead of using the default one.
|
||||
* Use it if you want to display a format completely different from the default one.
|
||||
* If you want to customize the default format there are several methods to customize parts of it.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getCourseFormatComponent?(course: any): any;
|
||||
getCourseFormatComponent?(injector: Injector, course: any): any | Promise<any>;
|
||||
|
||||
/**
|
||||
* Return the Component to use to display the course summary inside the default course format.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getCourseSummaryComponent?(course: any): any;
|
||||
getCourseSummaryComponent?(injector: Injector, course: any): any | Promise<any>;
|
||||
|
||||
/**
|
||||
* Return the Component to use to display the section selector inside the default course format.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getSectionSelectorComponent?(course: any): any;
|
||||
getSectionSelectorComponent?(injector: Injector, course: any): any | Promise<any>;
|
||||
|
||||
/**
|
||||
* Return the Component to use to display a single section. This component will only be used if the user is viewing a
|
||||
* single section. If all the sections are displayed at once then it won't be used.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getSingleSectionComponent?(course: any): any;
|
||||
getSingleSectionComponent?(injector: Injector, course: any): any | Promise<any>;
|
||||
|
||||
/**
|
||||
* Return the Component to use to display all sections in a course.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getAllSectionsComponent?(course: any): any;
|
||||
getAllSectionsComponent?(injector: Injector, course: any): any | Promise<any>;
|
||||
|
||||
/**
|
||||
* Invalidate the data required to load the course format.
|
||||
|
@ -199,31 +209,40 @@ export class CoreCourseFormatDelegate extends CoreDelegate {
|
|||
/**
|
||||
* Get the component to use to display all sections in a course.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getAllSectionsComponent(course: any): any {
|
||||
return this.executeFunction(course.format, 'getAllSectionsComponent', [course]);
|
||||
getAllSectionsComponent(injector: Injector, course: any): Promise<any> {
|
||||
return Promise.resolve(this.executeFunction(course.format, 'getAllSectionsComponent', [injector, course])).catch((e) => {
|
||||
this.logger.error('Error getting all sections component', e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the component to use to display a course format.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getCourseFormatComponent(course: any): any {
|
||||
return this.executeFunction(course.format, 'getCourseFormatComponent', [course]);
|
||||
getCourseFormatComponent(injector: Injector, course: any): Promise<any> {
|
||||
return Promise.resolve(this.executeFunction(course.format, 'getCourseFormatComponent', [injector, course])).catch((e) => {
|
||||
this.logger.error('Error getting course format component', e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the component to use to display the course summary in the default course format.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getCourseSummaryComponent(course: any): any {
|
||||
return this.executeFunction(course.format, 'getCourseSummaryComponent', [course]);
|
||||
getCourseSummaryComponent(injector: Injector, course: any): Promise<any> {
|
||||
return Promise.resolve(this.executeFunction(course.format, 'getCourseSummaryComponent', [injector, course])).catch((e) => {
|
||||
this.logger.error('Error getting course summary component', e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -259,22 +278,29 @@ export class CoreCourseFormatDelegate extends CoreDelegate {
|
|||
/**
|
||||
* Get the component to use to display the section selector inside the default course format.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getSectionSelectorComponent(course: any): any {
|
||||
return this.executeFunction(course.format, 'getSectionSelectorComponent', [course]);
|
||||
getSectionSelectorComponent(injector: Injector, course: any): Promise<any> {
|
||||
return Promise.resolve(this.executeFunction(course.format, 'getSectionSelectorComponent', [injector, course]))
|
||||
.catch((e) => {
|
||||
this.logger.error('Error getting section selector component', e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the component to use to display a single section. This component will only be used if the user is viewing
|
||||
* a single section. If all the sections are displayed at once then it won't be used.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course to render.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getSingleSectionComponent(course: any): any {
|
||||
return this.executeFunction(course.format, 'getSingleSectionComponent', [course]);
|
||||
getSingleSectionComponent(injector: Injector, course: any): Promise<any> {
|
||||
return Promise.resolve(this.executeFunction(course.format, 'getSingleSectionComponent', [injector, course])).catch((e) => {
|
||||
this.logger.error('Error getting single section component', e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,23 +12,26 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreFileProvider } from '@providers/file';
|
||||
import { CoreFilepoolProvider } from '@providers/filepool';
|
||||
import { CoreFileHelperProvider } from '@providers/file-helper';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreCourseOptionsDelegate, CoreCourseOptionsHandlerToDisplay } from './options-delegate';
|
||||
import { CoreSiteHomeProvider } from '../../sitehome/providers/sitehome';
|
||||
import { CoreSiteHomeProvider } from '@core/sitehome/providers/sitehome';
|
||||
import { CoreCourseProvider } from './course';
|
||||
import { CoreCourseModuleDelegate } from './module-delegate';
|
||||
import { CoreCourseModulePrefetchDelegate } from './module-prefetch-delegate';
|
||||
import { CoreLoginHelperProvider } from '../../login/providers/helper';
|
||||
import { CoreConstants } from '../../constants';
|
||||
import { CoreLoginHelperProvider } from '@core/login/providers/helper';
|
||||
import { CoreConstants } from '@core/constants';
|
||||
import { CoreSite } from '@classes/site';
|
||||
import * as moment from 'moment';
|
||||
|
||||
|
@ -116,7 +119,8 @@ export class CoreCourseHelperProvider {
|
|||
private textUtils: CoreTextUtilsProvider, private timeUtils: CoreTimeUtilsProvider,
|
||||
private utils: CoreUtilsProvider, private translate: TranslateService, private loginHelper: CoreLoginHelperProvider,
|
||||
private courseOptionsDelegate: CoreCourseOptionsDelegate, private siteHomeProvider: CoreSiteHomeProvider,
|
||||
private eventsProvider: CoreEventsProvider) { }
|
||||
private eventsProvider: CoreEventsProvider, private fileHelper: CoreFileHelperProvider,
|
||||
private appProvider: CoreAppProvider, private fileProvider: CoreFileProvider, private injector: Injector) { }
|
||||
|
||||
/**
|
||||
* This function treats every module on the sections provided to load the handler data, treat completion
|
||||
|
@ -271,7 +275,7 @@ export class CoreCourseHelperProvider {
|
|||
if (courseHandlers) {
|
||||
promise = Promise.resolve(courseHandlers);
|
||||
} else {
|
||||
promise = this.courseOptionsDelegate.getHandlersToDisplay(course);
|
||||
promise = this.courseOptionsDelegate.getHandlersToDisplay(this.injector, course);
|
||||
}
|
||||
|
||||
return promise.then((handlers: CoreCourseOptionsHandlerToDisplay[]) => {
|
||||
|
@ -319,7 +323,7 @@ export class CoreCourseHelperProvider {
|
|||
subPromises.push(this.courseProvider.getSections(course.id, false, true).then((courseSections) => {
|
||||
sections = courseSections;
|
||||
}));
|
||||
subPromises.push(this.courseOptionsDelegate.getHandlersToDisplay(course).then((cHandlers) => {
|
||||
subPromises.push(this.courseOptionsDelegate.getHandlersToDisplay(this.injector, course).then((cHandlers) => {
|
||||
handlers = cHandlers;
|
||||
}));
|
||||
|
||||
|
@ -470,6 +474,227 @@ export class CoreCourseHelperProvider {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to open a module main file, downloading the package if needed.
|
||||
* This is meant for modules like mod_resource.
|
||||
*
|
||||
* @param {any} module The module to download.
|
||||
* @param {number} courseId The course ID of the module.
|
||||
* @param {string} [component] The component to link the files to.
|
||||
* @param {string|number} [componentId] An ID to use in conjunction with the component.
|
||||
* @param {any[]} [files] List of files of the module. If not provided, use module.contents.
|
||||
* @param {string} [siteId] The site ID. If not defined, current site.
|
||||
* @return {Promise<any>} Resolved on success.
|
||||
*/
|
||||
downloadModuleAndOpenFile(module: any, courseId: number, component?: string, componentId?: string | number, files?: any[],
|
||||
siteId?: string): Promise<any> {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
let promise;
|
||||
if (files) {
|
||||
promise = Promise.resolve(files);
|
||||
} else {
|
||||
promise = this.courseProvider.loadModuleContents(module, courseId).then(() => {
|
||||
files = module.contents;
|
||||
});
|
||||
}
|
||||
|
||||
// Make sure that module contents are loaded.
|
||||
return promise.then(() => {
|
||||
if (!files || !files.length) {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
|
||||
return this.sitesProvider.getSite(siteId);
|
||||
}).then((site) => {
|
||||
const mainFile = files[0],
|
||||
fileUrl = this.fileHelper.getFileUrl(mainFile);
|
||||
|
||||
// Check if the file should be opened in browser.
|
||||
if (this.fileHelper.shouldOpenInBrowser(mainFile)) {
|
||||
if (this.appProvider.isOnline()) {
|
||||
// Open in browser.
|
||||
let fixedUrl = site.fixPluginfileURL(fileUrl).replace('&offline=1', '');
|
||||
// Remove forcedownload when followed by another param.
|
||||
fixedUrl = fixedUrl.replace(/forcedownload=\d+&/, '');
|
||||
// Remove forcedownload when not followed by any param.
|
||||
fixedUrl = fixedUrl.replace(/[\?|\&]forcedownload=\d+/, '');
|
||||
|
||||
this.utils.openInBrowser(fixedUrl);
|
||||
|
||||
if (this.fileProvider.isAvailable()) {
|
||||
// Download the file if needed (file outdated or not downloaded).
|
||||
// Download will be in background, don't return the promise.
|
||||
this.downloadModule(module, courseId, component, componentId, files, siteId);
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
// Not online, get the offline file. It will fail if not found.
|
||||
return this.filepoolProvider.getInternalUrlByUrl(siteId, fileUrl).then((path) => {
|
||||
return this.utils.openFile(path);
|
||||
}).catch((error) => {
|
||||
return Promise.reject(this.translate.instant('core.networkerrormsg'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// File shouldn't be opened in browser. Download the module if it needs to be downloaded.
|
||||
return this.downloadModuleWithMainFileIfNeeded(module, courseId, component, componentId, files, siteId)
|
||||
.then((result) => {
|
||||
if (result.path.indexOf('http') === 0) {
|
||||
return this.utils.openOnlineFile(result.path).catch((error) => {
|
||||
// Error opening the file, some apps don't allow opening online files.
|
||||
if (!this.fileProvider.isAvailable()) {
|
||||
return Promise.reject(error);
|
||||
} else if (result.status === CoreConstants.DOWNLOADING) {
|
||||
return Promise.reject(this.translate.instant('core.erroropenfiledownloading'));
|
||||
}
|
||||
|
||||
let promise;
|
||||
if (result.status === CoreConstants.NOT_DOWNLOADED) {
|
||||
// Not downloaded, download it now and return the local file.
|
||||
promise = this.downloadModule(module, courseId, component, componentId, files, siteId).then(() => {
|
||||
return this.filepoolProvider.getInternalUrlByUrl(siteId, fileUrl);
|
||||
});
|
||||
} else {
|
||||
// File is outdated or stale and can't be opened in online, return the local URL.
|
||||
promise = this.filepoolProvider.getInternalUrlByUrl(siteId, fileUrl);
|
||||
}
|
||||
|
||||
return promise.then((path) => {
|
||||
return this.utils.openFile(path);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return this.utils.openFile(result.path);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to download a module that has a main file and return the local file's path and other info.
|
||||
* This is meant for modules like mod_resource.
|
||||
*
|
||||
* @param {any} module The module to download.
|
||||
* @param {number} courseId The course ID of the module.
|
||||
* @param {string} [component] The component to link the files to.
|
||||
* @param {string|number} [componentId] An ID to use in conjunction with the component.
|
||||
* @param {any[]} [files] List of files of the module. If not provided, use module.contents.
|
||||
* @param {string} [siteId] The site ID. If not defined, current site.
|
||||
* @return {Promise<{fixedUrl: string, path: string, status: string}>} Promise resolved when done.
|
||||
*/
|
||||
protected downloadModuleWithMainFileIfNeeded(module: any, courseId: number, component?: string, componentId?: string | number,
|
||||
files?: any[], siteId?: string): Promise<{fixedUrl: string, path: string, status: string}> {
|
||||
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
if (!files || !files.length) {
|
||||
// Module not valid, stop.
|
||||
return Promise.reject(null);
|
||||
}
|
||||
|
||||
const mainFile = files[0],
|
||||
fileUrl = this.fileHelper.getFileUrl(mainFile),
|
||||
timemodified = this.fileHelper.getFileTimemodified(mainFile),
|
||||
prefetchHandler = this.prefetchDelegate.getPrefetchHandlerFor(module),
|
||||
result = {
|
||||
fixedUrl: undefined,
|
||||
path: undefined,
|
||||
status: undefined
|
||||
};
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const fixedUrl = site.fixPluginfileURL(fileUrl);
|
||||
result.fixedUrl = fixedUrl;
|
||||
|
||||
if (this.fileProvider.isAvailable()) {
|
||||
// The file system is available.
|
||||
return this.filepoolProvider.getPackageStatus(siteId, component, componentId).then((status) => {
|
||||
result.status = status;
|
||||
|
||||
const isWifi = !this.appProvider.isNetworkAccessLimited(),
|
||||
isOnline = this.appProvider.isOnline();
|
||||
|
||||
if (status === CoreConstants.DOWNLOADED) {
|
||||
// Get the local file URL.
|
||||
return this.filepoolProvider.getInternalUrlByUrl(siteId, fileUrl);
|
||||
} else if (status === CoreConstants.DOWNLOADING && !this.appProvider.isDesktop()) {
|
||||
// Return the online URL.
|
||||
return fixedUrl;
|
||||
} else {
|
||||
if (!isOnline && status === CoreConstants.NOT_DOWNLOADED) {
|
||||
// Not downloaded and we're offline, reject.
|
||||
return Promise.reject(this.translate.instant('core.networkerrormsg'));
|
||||
}
|
||||
|
||||
return this.filepoolProvider.shouldDownloadBeforeOpen(fixedUrl, mainFile.filesize).then(() => {
|
||||
// Download and then return the local URL.
|
||||
return this.downloadModule(module, courseId, component, componentId, files, siteId).then(() => {
|
||||
return this.filepoolProvider.getInternalUrlByUrl(siteId, fileUrl);
|
||||
});
|
||||
}, () => {
|
||||
// Start the download if in wifi, but return the URL right away so the file is opened.
|
||||
if (isWifi && isOnline) {
|
||||
this.downloadModule(module, courseId, component, componentId, files, siteId);
|
||||
}
|
||||
|
||||
if (!this.fileHelper.isStateDownloaded(status) || isOnline) {
|
||||
// Not downloaded or online, return the online URL.
|
||||
return fixedUrl;
|
||||
} else {
|
||||
// Outdated but offline, so we return the local URL. Use getUrlByUrl so it's added to the queue.
|
||||
return this.filepoolProvider.getUrlByUrl(siteId, fileUrl, component, componentId, timemodified,
|
||||
false, false, mainFile);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).then((path) => {
|
||||
result.path = path;
|
||||
|
||||
return result;
|
||||
});
|
||||
} else {
|
||||
// We use the live URL.
|
||||
result.path = fixedUrl;
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to download a module.
|
||||
*
|
||||
* @param {any} module The module to download.
|
||||
* @param {number} courseId The course ID of the module.
|
||||
* @param {string} [component] The component to link the files to.
|
||||
* @param {string|number} [componentId] An ID to use in conjunction with the component.
|
||||
* @param {any[]} [files] List of files of the module. If not provided, use module.contents.
|
||||
* @param {string} [siteId] The site ID. If not defined, current site.
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
downloadModule(module: any, courseId: number, component?: string, componentId?: string | number, files?: any[], siteId?: string)
|
||||
: Promise<any> {
|
||||
|
||||
const prefetchHandler = this.prefetchDelegate.getPrefetchHandlerFor(module);
|
||||
|
||||
if (prefetchHandler) {
|
||||
// Use the prefetch handler to download the module.
|
||||
if (prefetchHandler.download) {
|
||||
return prefetchHandler.download(module, courseId);
|
||||
} else {
|
||||
return prefetchHandler.prefetch(module, courseId, true);
|
||||
}
|
||||
}
|
||||
|
||||
// There's no prefetch handler for the module, just download the files.
|
||||
files = files || module.contents;
|
||||
|
||||
return this.filepoolProvider.downloadOrPrefetchFiles(siteId, files, false, false, component, componentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the Context Menu for a certain module.
|
||||
*
|
||||
|
@ -605,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;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { NavController, NavOptions } from 'ionic-angular';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
|
@ -38,12 +38,14 @@ export interface CoreCourseModuleHandler extends CoreDelegateHandler {
|
|||
/**
|
||||
* Get the component to render the module. This is needed to support singleactivity course format.
|
||||
* The component returned must implement CoreCourseModuleMainComponent.
|
||||
* It's recommended to return the class of the component, but you can also return an instance of the component.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course object.
|
||||
* @param {any} module The module object.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {any|Promise<any>} The component (or promise resolved with component) to use, undefined if not found.
|
||||
*/
|
||||
getMainComponent(course: any, module: any): any;
|
||||
getMainComponent(injector: Injector, course: any, module: any): any | Promise<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,17 +178,17 @@ export class CoreCourseModuleDelegate extends CoreDelegate {
|
|||
/**
|
||||
* Get the component to render the module.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course object.
|
||||
* @param {any} module The module object.
|
||||
* @return {any} The component to use, undefined if not found.
|
||||
* @return {Promise<any>} Promise resolved with component to use, undefined if not found.
|
||||
*/
|
||||
getMainComponent?(course: any, module: any): any {
|
||||
getMainComponent(injector: Injector, course: any, module: any): Promise<any> {
|
||||
const handler = this.enabledHandlers[module.modname];
|
||||
if (handler && handler.getMainComponent) {
|
||||
const component = handler.getMainComponent(course, module);
|
||||
if (component) {
|
||||
return component;
|
||||
}
|
||||
return Promise.resolve(handler.getMainComponent(injector, course, module)).catch((err) => {
|
||||
this.logger.error('Error getting main component', err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -86,9 +86,20 @@ export interface CoreCourseModulePrefetchHandler extends CoreDelegateHandler {
|
|||
* @param {any} module Module.
|
||||
* @param {number} courseId Course ID the module belongs to.
|
||||
* @param {boolean} [single] True if we're downloading a single module, false if we're downloading a whole section.
|
||||
* @param {string} [dirPath] Path of the directory where to store all the content files.
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
prefetch(module: any, courseId?: number, single?: boolean): Promise<any>;
|
||||
prefetch(module: any, courseId?: number, single?: boolean, dirPath?: string): Promise<any>;
|
||||
|
||||
/**
|
||||
* Download the module.
|
||||
*
|
||||
* @param {any} module The module object returned by WS.
|
||||
* @param {number} courseId Course ID.
|
||||
* @param {string} [dirPath] Path of the directory where to store all the content files.
|
||||
* @return {Promise<any>} Promise resolved when all content is downloaded.
|
||||
*/
|
||||
download?(module: any, courseId: number, dirPath?: string): Promise<any>;
|
||||
|
||||
/**
|
||||
* Check if a certain module can use core_course_check_updates to check if it has updates.
|
||||
|
@ -141,8 +152,8 @@ export interface CoreCourseModulePrefetchHandler extends CoreDelegateHandler {
|
|||
hasUpdates?(module: any, courseId: number, moduleUpdates: any[]): boolean | Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Invalidate WS calls needed to determine module status. It doesn't need to invalidate check updates.
|
||||
* It should NOT invalidate files nor all the prefetched data.
|
||||
* Invalidate WS calls needed to determine module status (usually, to check if module is downloadable).
|
||||
* It doesn't need to invalidate check updates. It should NOT invalidate files nor all the prefetched data.
|
||||
*
|
||||
* @param {any} module Module.
|
||||
* @param {number} courseId Course ID the module belongs to.
|
||||
|
|
|
@ -12,13 +12,13 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreUtilsProvider, PromiseDefer } from '@providers/utils/utils';
|
||||
import { CoreCoursesProvider } from '../../courses/providers/courses';
|
||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
import { CoreCourseProvider } from './course';
|
||||
|
||||
/**
|
||||
|
@ -45,10 +45,11 @@ export interface CoreCourseOptionsHandler extends CoreDelegateHandler {
|
|||
/**
|
||||
* Returns the data needed to render the handler.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {number} courseId The course ID.
|
||||
* @return {CoreCourseOptionsHandlerData} Data.
|
||||
* @return {CoreCourseOptionsHandlerData|Promise<CoreCourseOptionsHandlerData>} Data or promise resolved with the data.
|
||||
*/
|
||||
getDisplayData?(courseId: number): CoreCourseOptionsHandlerData;
|
||||
getDisplayData?(injector: Injector, courseId: number): CoreCourseOptionsHandlerData | Promise<CoreCourseOptionsHandlerData>;
|
||||
|
||||
/**
|
||||
* Should invalidate the data to determine if the handler is enabled for a certain course.
|
||||
|
@ -90,6 +91,12 @@ export interface CoreCourseOptionsHandlerData {
|
|||
* When the component is created, it will receive the courseId as input.
|
||||
*/
|
||||
component: any;
|
||||
|
||||
/**
|
||||
* Data to pass to the component. All the properties in this object will be passed to the component as inputs.
|
||||
* @type {any}
|
||||
*/
|
||||
componentData?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,6 +244,7 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
|||
* Get the list of handlers that should be displayed for a course.
|
||||
* This function should be called only when the handlers need to be displayed, since it can call several WebServices.
|
||||
*
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {any} course The course object.
|
||||
* @param {boolean} [refresh] True if it should refresh the list.
|
||||
* @param {boolean} [isGuest] Whether it's guest.
|
||||
|
@ -244,7 +252,7 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
|||
* @param {any} [admOptions] Course admin options for current user. See CoreCoursesProvider.getUserAdministrationOptions.
|
||||
* @return {Promise<CoreCourseOptionsHandlerToDisplay[]>} Promise resolved with array of handlers.
|
||||
*/
|
||||
getHandlersToDisplay(course: any, refresh?: boolean, isGuest?: boolean, navOptions?: any, admOptions?: any):
|
||||
getHandlersToDisplay(injector: Injector, course: any, refresh?: boolean, isGuest?: boolean, navOptions?: any, admOptions?: any):
|
||||
Promise<CoreCourseOptionsHandlerToDisplay[]> {
|
||||
course.id = parseInt(course.id, 10);
|
||||
|
||||
|
@ -263,14 +271,19 @@ export class CoreCourseOptionsDelegate extends CoreDelegate {
|
|||
// Call getHandlersForAccess to make sure the handlers have been loaded.
|
||||
return this.getHandlersForAccess(course.id, refresh, accessData, course.navOptions, course.admOptions);
|
||||
}).then(() => {
|
||||
const handlersToDisplay: CoreCourseOptionsHandlerToDisplay[] = [];
|
||||
const handlersToDisplay: CoreCourseOptionsHandlerToDisplay[] = [],
|
||||
promises = [];
|
||||
|
||||
this.coursesHandlers[course.id].enabledHandlers.forEach((handler) => {
|
||||
handlersToDisplay.push({
|
||||
data: handler.getDisplayData(course),
|
||||
priority: handler.priority,
|
||||
prefetch: handler.prefetch
|
||||
});
|
||||
promises.push(Promise.resolve(handler.getDisplayData(injector, course)).then((data) => {
|
||||
handlersToDisplay.push({
|
||||
data: data,
|
||||
priority: handler.priority,
|
||||
prefetch: handler.prefetch
|
||||
});
|
||||
}).catch((err) => {
|
||||
this.logger.error('Error getting data for handler', handler.name, err);
|
||||
}));
|
||||
});
|
||||
|
||||
// Sort them by priority.
|
||||
|
|
|
@ -17,8 +17,8 @@ import { CommonModule } from '@angular/common';
|
|||
import { IonicModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CorePipesModule } from '@pipes';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CorePipesModule } from '@pipes/pipes.module';
|
||||
import { CoreCoursesCourseProgressComponent } from '../components/course-progress/course-progress';
|
||||
import { CoreCoursesCourseListItemComponent } from '../components/course-list-item/course-list-item';
|
||||
import { CoreCoursesOverviewEventsComponent } from '../components/overview-events/overview-events';
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Component, Input, OnInit, Optional } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreCoursesProvider } from '../../providers/courses';
|
||||
|
@ -31,7 +31,8 @@ import { CoreCoursesProvider } from '../../providers/courses';
|
|||
export class CoreCoursesCourseListItemComponent implements OnInit {
|
||||
@Input() course: any; // The course to render.
|
||||
|
||||
constructor(private navCtrl: NavController, private translate: TranslateService, private coursesProvider: CoreCoursesProvider) {
|
||||
constructor(@Optional() private navCtrl: NavController, private translate: TranslateService,
|
||||
private coursesProvider: CoreCoursesProvider) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Component, Input, OnInit, OnDestroy, Optional } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreCourseFormatDelegate } from '../../../course/providers/format-delegate';
|
||||
import { CoreCourseProvider } from '../../../course/providers/course';
|
||||
import { CoreCourseHelperProvider } from '../../../course/providers/helper';
|
||||
import { CoreCourseFormatDelegate } from '@core/course/providers/format-delegate';
|
||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||
|
||||
/**
|
||||
* This component is meant to display a course for a list of courses with progress.
|
||||
|
@ -44,7 +44,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
|
|||
protected isDestroyed = false;
|
||||
protected courseStatusObserver;
|
||||
|
||||
constructor(private navCtrl: NavController, private courseHelper: CoreCourseHelperProvider,
|
||||
constructor(@Optional() private navCtrl: NavController, private courseHelper: CoreCourseHelperProvider,
|
||||
private courseFormatDelegate: CoreCourseFormatDelegate, private domUtils: CoreDomUtilsProvider,
|
||||
private courseProvider: CoreCourseProvider, eventsProvider: CoreEventsProvider, sitesProvider: CoreSitesProvider) {
|
||||
// Listen for status change in course.
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, Input, Output, OnChanges, EventEmitter, SimpleChange } from '@angular/core';
|
||||
import { Component, Input, Output, OnChanges, EventEmitter, SimpleChange, Optional } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreCourseProvider } from '../../../course/providers/course';
|
||||
import { CoreContentLinksHelperProvider } from '../../../contentlinks/providers/helper';
|
||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
||||
import * as moment from 'moment';
|
||||
|
||||
/**
|
||||
|
@ -43,9 +43,10 @@ export class CoreCoursesOverviewEventsComponent implements OnChanges {
|
|||
next30Days: any[] = [];
|
||||
future: any[] = [];
|
||||
|
||||
constructor(private navCtrl: NavController, private utils: CoreUtilsProvider, private textUtils: CoreTextUtilsProvider,
|
||||
private domUtils: CoreDomUtilsProvider, private sitesProvider: CoreSitesProvider,
|
||||
private courseProvider: CoreCourseProvider, private contentLinksHelper: CoreContentLinksHelperProvider) {
|
||||
constructor(@Optional() private navCtrl: NavController, private utils: CoreUtilsProvider,
|
||||
private textUtils: CoreTextUtilsProvider, private domUtils: CoreDomUtilsProvider,
|
||||
private sitesProvider: CoreSitesProvider, private courseProvider: CoreCourseProvider,
|
||||
private contentLinksHelper: CoreContentLinksHelperProvider) {
|
||||
this.loadMore = new EventEmitter();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,21 +19,25 @@ import { CoreCoursesMyOverviewProvider } from './providers/my-overview';
|
|||
import { CoreCoursesCourseLinkHandler } from './providers/course-link-handler';
|
||||
import { CoreCoursesIndexLinkHandler } from './providers/courses-index-link-handler';
|
||||
import { CoreCoursesMyOverviewLinkHandler } from './providers/my-overview-link-handler';
|
||||
import { CoreMainMenuDelegate } from '../mainmenu/providers/delegate';
|
||||
import { CoreContentLinksDelegate } from '../contentlinks/providers/delegate';
|
||||
import { CoreMainMenuDelegate } from '@core/mainmenu/providers/delegate';
|
||||
import { CoreContentLinksDelegate } from '@core/contentlinks/providers/delegate';
|
||||
|
||||
// List of providers (without handlers).
|
||||
export const CORE_COURSES_PROVIDERS: any[] = [
|
||||
CoreCoursesProvider,
|
||||
CoreCoursesMyOverviewProvider
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [
|
||||
],
|
||||
providers: [
|
||||
CoreCoursesProvider,
|
||||
providers: CORE_COURSES_PROVIDERS.concat([
|
||||
CoreCoursesMainMenuHandler,
|
||||
CoreCoursesMyOverviewProvider,
|
||||
CoreCoursesCourseLinkHandler,
|
||||
CoreCoursesIndexLinkHandler,
|
||||
CoreCoursesMyOverviewLinkHandler
|
||||
],
|
||||
]),
|
||||
exports: []
|
||||
})
|
||||
export class CoreCoursesModule {
|
||||
|
|
|
@ -17,7 +17,7 @@ import { IonicPageModule } from 'ionic-angular';
|
|||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreCoursesCategoriesPage } from './categories';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CoreCoursesComponentsModule } from '../../components/components.module';
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -17,8 +17,8 @@ import { IonicPageModule } from 'ionic-angular';
|
|||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreCoursesCoursePreviewPage } from './course-preview';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CorePipesModule } from '@pipes';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CorePipesModule } from '@pipes/pipes.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -21,9 +21,9 @@ import { CoreSitesProvider } from '@providers/sites';
|
|||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreCoursesProvider } from '../../providers/courses';
|
||||
import { CoreCourseOptionsDelegate } from '../../../course/providers/options-delegate';
|
||||
import { CoreCourseProvider } from '../../../course/providers/course';
|
||||
import { CoreCourseHelperProvider } from '../../../course/providers/helper';
|
||||
import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate';
|
||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||
|
||||
/**
|
||||
* Page that allows "previewing" a course and enrolling in it if enabled and not enrolled.
|
||||
|
|
|
@ -18,8 +18,8 @@ import { CoreEventsProvider } from '@providers/events';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreCoursesProvider } from '../../providers/courses';
|
||||
import { CoreCourseHelperProvider } from '../../../course/providers/helper';
|
||||
import { CoreCourseOptionsDelegate } from '../../../course/providers/options-delegate';
|
||||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||
import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate';
|
||||
|
||||
/**
|
||||
* Page that displays the list of courses the user is enrolled in.
|
||||
|
|
|
@ -18,7 +18,7 @@ import { TranslateModule } from '@ngx-translate/core';
|
|||
import { CoreCoursesMyOverviewPage } from './my-overview';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreCoursesComponentsModule } from '../../components/components.module';
|
||||
import { CoreSiteHomeComponentsModule } from '../../../sitehome/components/components.module';
|
||||
import { CoreSiteHomeComponentsModule } from '@core/sitehome/components/components.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -18,9 +18,9 @@ import { CoreSitesProvider } from '@providers/sites';
|
|||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreCoursesProvider } from '../../providers/courses';
|
||||
import { CoreCoursesMyOverviewProvider } from '../../providers/my-overview';
|
||||
import { CoreCourseHelperProvider } from '../../../course/providers/helper';
|
||||
import { CoreCourseOptionsDelegate } from '../../../course/providers/options-delegate';
|
||||
import { CoreSiteHomeProvider } from '../../../sitehome/providers/sitehome';
|
||||
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
|
||||
import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate';
|
||||
import { CoreSiteHomeProvider } from '@core/sitehome/providers/sitehome';
|
||||
import * as moment from 'moment';
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,7 +17,7 @@ import { IonicPageModule } from 'ionic-angular';
|
|||
import { CoreCoursesSelfEnrolPasswordPage } from './self-enrol-password';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -16,10 +16,10 @@ import { Injectable } from '@angular/core';
|
|||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreContentLinksHandlerBase } from '../../contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '../../contentlinks/providers/delegate';
|
||||
import { CoreLoginHelperProvider } from '../../login/providers/helper';
|
||||
import { CoreCourseProvider } from '../../course/providers/course';
|
||||
import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
|
||||
import { CoreLoginHelperProvider } from '@core/login/providers/helper';
|
||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||
import { CoreCoursesProvider } from './courses';
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreContentLinksHandlerBase } from '../../contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '../../contentlinks/providers/delegate';
|
||||
import { CoreLoginHelperProvider } from '../../login/providers/helper';
|
||||
import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
|
||||
import { CoreLoginHelperProvider } from '@core/login/providers/helper';
|
||||
import { CoreCoursesProvider } from './courses';
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreCoursesProvider } from './courses';
|
||||
import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '../../mainmenu/providers/delegate';
|
||||
import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '@core/mainmenu/providers/delegate';
|
||||
import { CoreCoursesMyOverviewProvider } from '../providers/my-overview';
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreContentLinksHandlerBase } from '../../contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '../../contentlinks/providers/delegate';
|
||||
import { CoreLoginHelperProvider } from '../../login/providers/helper';
|
||||
import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
|
||||
import { CoreLoginHelperProvider } from '@core/login/providers/helper';
|
||||
|
||||
/**
|
||||
* Handler to treat links to my overview.
|
||||
|
|
|
@ -56,6 +56,24 @@ import { CoreUrlUtilsProvider } from '@providers/utils/url';
|
|||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreInitDelegate } from '@providers/init';
|
||||
|
||||
// List of Ionic Native providers.
|
||||
export const IONIC_NATIVE_PROVIDERS = [
|
||||
Camera,
|
||||
Clipboard,
|
||||
File,
|
||||
FileTransfer,
|
||||
Globalization,
|
||||
InAppBrowser,
|
||||
Keyboard,
|
||||
LocalNotifications,
|
||||
MediaCapture,
|
||||
Network,
|
||||
SplashScreen,
|
||||
StatusBar,
|
||||
SQLite,
|
||||
Zip
|
||||
];
|
||||
|
||||
/**
|
||||
* This module handles the emulation of Cordova plugins in browser and desktop.
|
||||
*
|
||||
|
|
|
@ -17,7 +17,7 @@ import { LocalNotifications, ILocalNotification } from '@ionic-native/local-noti
|
|||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { SQLiteDB } from '@classes/sqlitedb';
|
||||
import { CoreConstants } from '../../constants';
|
||||
import { CoreConstants } from '@core/constants';
|
||||
import { CoreConfigConstants } from '../../../configconstants';
|
||||
import * as moment from 'moment';
|
||||
|
||||
|
|
|
@ -22,21 +22,25 @@ import { CoreFileUploaderCameraHandler } from './providers/camera-handler';
|
|||
import { CoreFileUploaderFileHandler } from './providers/file-handler';
|
||||
import { CoreFileUploaderVideoHandler } from './providers/video-handler';
|
||||
|
||||
// List of providers (without handlers).
|
||||
export const CORE_FILEUPLOADER_PROVIDERS: any[] = [
|
||||
CoreFileUploaderProvider,
|
||||
CoreFileUploaderHelperProvider,
|
||||
CoreFileUploaderDelegate
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
],
|
||||
imports: [
|
||||
],
|
||||
providers: [
|
||||
CoreFileUploaderProvider,
|
||||
CoreFileUploaderHelperProvider,
|
||||
CoreFileUploaderDelegate,
|
||||
providers: CORE_FILEUPLOADER_PROVIDERS.concat([
|
||||
CoreFileUploaderAlbumHandler,
|
||||
CoreFileUploaderAudioHandler,
|
||||
CoreFileUploaderCameraHandler,
|
||||
CoreFileUploaderFileHandler,
|
||||
CoreFileUploaderVideoHandler
|
||||
]
|
||||
])
|
||||
})
|
||||
export class CoreFileUploaderModule {
|
||||
constructor(delegate: CoreFileUploaderDelegate, albumHandler: CoreFileUploaderAlbumHandler,
|
||||
|
|
|
@ -18,8 +18,8 @@ import { IonicModule } from 'ionic-angular';
|
|||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreGradesCourseComponent } from './course/course';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CorePipesModule } from '@pipes';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CorePipesModule } from '@pipes/pipes.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -39,8 +39,9 @@ export class CoreGradesCourseComponent {
|
|||
gradesTable: any;
|
||||
|
||||
constructor(private gradesProvider: CoreGradesProvider, private domUtils: CoreDomUtilsProvider, navParams: NavParams,
|
||||
private gradesHelper: CoreGradesHelperProvider, private sitesProvider: CoreSitesProvider, private navCtrl: NavController,
|
||||
private appProvider: CoreAppProvider, @Optional() private svComponent: CoreSplitViewComponent) {
|
||||
private gradesHelper: CoreGradesHelperProvider, private sitesProvider: CoreSitesProvider,
|
||||
@Optional() private navCtrl: NavController, private appProvider: CoreAppProvider,
|
||||
@Optional() private svComponent: CoreSplitViewComponent) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,19 +15,25 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CoreGradesProvider } from './providers/grades';
|
||||
import { CoreGradesHelperProvider } from './providers/helper';
|
||||
import { CoreMainMenuDelegate } from '../mainmenu/providers/delegate';
|
||||
import { CoreMainMenuDelegate } from '@core/mainmenu/providers/delegate';
|
||||
import { CoreGradesMainMenuHandler } from './providers/mainmenu-handler';
|
||||
import { CoreGradesCourseOptionHandler } from './providers/course-option-handler';
|
||||
import { CoreGradesComponentsModule } from './components/components.module';
|
||||
import { CoreCourseOptionsDelegate } from '../course/providers/options-delegate';
|
||||
import { CoreCourseOptionsDelegate } from '@core/course/providers/options-delegate';
|
||||
import { CoreGradesUserLinkHandler } from './providers/user-link-handler';
|
||||
import { CoreGradesOverviewLinkHandler } from './providers/overview-link-handler';
|
||||
import { CoreContentLinksDelegate } from '../contentlinks/providers/delegate';
|
||||
import { CoreContentLinksDelegate } from '@core/contentlinks/providers/delegate';
|
||||
import { CoreGradesUserHandler } from './providers/user-handler';
|
||||
import { CoreUserDelegate } from '../user/providers/user-delegate';
|
||||
import { CoreUserDelegate } from '@core/user/providers/user-delegate';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreUserProvider } from '../user/providers/user';
|
||||
import { CoreUserProvider } from '@core/user/providers/user';
|
||||
|
||||
// List of providers (without handlers).
|
||||
export const CORE_GRADES_PROVIDERS: any[] = [
|
||||
CoreGradesProvider,
|
||||
CoreGradesHelperProvider
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
@ -35,15 +41,13 @@ import { CoreUserProvider } from '../user/providers/user';
|
|||
imports: [
|
||||
CoreGradesComponentsModule
|
||||
],
|
||||
providers: [
|
||||
CoreGradesProvider,
|
||||
CoreGradesHelperProvider,
|
||||
providers: CORE_GRADES_PROVIDERS.concat([
|
||||
CoreGradesMainMenuHandler,
|
||||
CoreGradesCourseOptionHandler,
|
||||
CoreGradesUserLinkHandler,
|
||||
CoreGradesOverviewLinkHandler,
|
||||
CoreGradesUserHandler
|
||||
]
|
||||
])
|
||||
})
|
||||
export class CoreGradesModule {
|
||||
constructor(mainMenuDelegate: CoreMainMenuDelegate, gradesMenuHandler: CoreGradesMainMenuHandler,
|
||||
|
|
|
@ -17,7 +17,7 @@ import { IonicPageModule } from 'ionic-angular';
|
|||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreGradesCoursesPage } from './courses';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -17,7 +17,7 @@ import { IonicPageModule } from 'ionic-angular';
|
|||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreGradesGradePage } from './grade';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreCourseOptionsHandler, CoreCourseOptionsHandlerData } from '../../course/providers/options-delegate';
|
||||
import { CoreCourseProvider } from '../../course/providers/course';
|
||||
import { CoreCourseOptionsHandler, CoreCourseOptionsHandlerData } from '@core/course/providers/options-delegate';
|
||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||
import { CoreGradesProvider } from './grades';
|
||||
import { CoreCoursesProvider } from '../../courses/providers/courses';
|
||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
import { CoreGradesCourseComponent } from '../components/course/course';
|
||||
|
||||
/**
|
||||
|
@ -80,9 +80,11 @@ export class CoreGradesCourseOptionHandler implements CoreCourseOptionsHandler {
|
|||
/**
|
||||
* Returns the data needed to render the handler.
|
||||
*
|
||||
* @return {CoreCourseOptionsHandlerData} Data needed to render the handler.
|
||||
* @param {Injector} injector Injector.
|
||||
* @param {number} courseId The course ID.
|
||||
* @return {CoreCourseOptionsHandlerData|Promise<CoreCourseOptionsHandlerData>} Data or promise resolved with the data.
|
||||
*/
|
||||
getDisplayData(): CoreCourseOptionsHandlerData {
|
||||
getDisplayData(injector: Injector, courseId: number): CoreCourseOptionsHandlerData | Promise<CoreCourseOptionsHandlerData> {
|
||||
return {
|
||||
title: 'core.grades.grades',
|
||||
class: 'core-grades-course-handler',
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Injectable } from '@angular/core';
|
|||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreSite } from '@classes/site';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreCoursesProvider } from '../../courses/providers/courses';
|
||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
|
||||
/**
|
||||
* Service to provide grade functionalities.
|
||||
|
|
|
@ -16,8 +16,8 @@ import { Injectable } from '@angular/core';
|
|||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreCoursesProvider } from '../../courses/providers/courses';
|
||||
import { CoreCourseProvider } from '../../course/providers/course';
|
||||
import { CoreCoursesProvider } from '@core/courses/providers/courses';
|
||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||
import { CoreGradesProvider } from './grades';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreUrlUtilsProvider } from '@providers/utils/url';
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreGradesProvider } from './grades';
|
||||
import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '../../mainmenu/providers/delegate';
|
||||
import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '@core/mainmenu/providers/delegate';
|
||||
|
||||
/**
|
||||
* Handler to inject an option into main menu.
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreContentLinksHandlerBase } from '../../contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '../../contentlinks/providers/delegate';
|
||||
import { CoreContentLinksHelperProvider } from '../../contentlinks/providers/helper';
|
||||
import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
|
||||
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
||||
import { CoreGradesProvider } from './grades';
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreUserDelegate, CoreUserProfileHandler, CoreUserProfileHandlerData } from '../../user/providers/user-delegate';
|
||||
import { CoreUserDelegate, CoreUserProfileHandler, CoreUserProfileHandlerData } from '@core/user/providers/user-delegate';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreContentLinksHelperProvider } from '../../contentlinks/providers/helper';
|
||||
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
||||
import { CoreGradesProvider } from './grades';
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreContentLinksHandlerBase } from '../../contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '../../contentlinks/providers/delegate';
|
||||
import { CoreContentLinksHelperProvider } from '../../contentlinks/providers/helper';
|
||||
import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate';
|
||||
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
||||
import { CoreGradesProvider } from './grades';
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,13 +15,16 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CoreLoginHelperProvider } from './providers/helper';
|
||||
|
||||
// List of providers.
|
||||
export const CORE_LOGIN_PROVIDERS = [
|
||||
CoreLoginHelperProvider
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
],
|
||||
imports: [
|
||||
],
|
||||
providers: [
|
||||
CoreLoginHelperProvider
|
||||
]
|
||||
providers: CORE_LOGIN_PROVIDERS
|
||||
})
|
||||
export class CoreLoginModule {}
|
||||
|
|
|
@ -17,7 +17,7 @@ import { IonicPageModule } from 'ionic-angular';
|
|||
import { CoreLoginCredentialsPage } from './credentials';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -21,8 +21,8 @@ import { CoreSitesProvider } from '@providers/sites';
|
|||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreLoginHelperProvider } from '../../providers/helper';
|
||||
import { CoreContentLinksDelegate } from '../../../contentlinks/providers/delegate';
|
||||
import { CoreContentLinksHelperProvider } from '../../../contentlinks/providers/helper';
|
||||
import { CoreContentLinksDelegate } from '@core/contentlinks/providers/delegate';
|
||||
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,8 +17,8 @@ import { IonicPageModule } from 'ionic-angular';
|
|||
import { CoreLoginEmailSignupPage } from './email-signup';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives';
|
||||
import { CoreUserComponentsModule } from '../../../user/components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CoreUserComponentsModule } from '@core/user/components/components.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
|
|
@ -22,7 +22,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils';
|
|||
import { CoreWSProvider } from '@providers/ws';
|
||||
import { CoreLoginHelperProvider } from '../../providers/helper';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { CoreUserProfileFieldDelegate } from '../../../user/providers/user-profile-field-delegate';
|
||||
import { CoreUserProfileFieldDelegate } from '@core/user/providers/user-profile-field-delegate';
|
||||
|
||||
/**
|
||||
* Page to signup using email.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue