diff --git a/src/addons/badges/badges.module.ts b/src/addons/badges/badges.module.ts index fecca7062..de0fd76b9 100644 --- a/src/addons/badges/badges.module.ts +++ b/src/addons/badges/badges.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { AddonBadgesMyBadgesLinkHandler } from './services/handlers/mybadges-link'; @@ -23,6 +23,11 @@ import { AddonBadgesUserHandler } from './services/handlers/user'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; import { AddonBadgesPushClickHandler } from './services/handlers/push-click'; +import { AddonBadgesProvider } from './services/badges'; + +export const ADDON_BADGES_SERVICES: Type[] = [ + AddonBadgesProvider, +]; const mainMenuRoutes: Routes = [ { diff --git a/src/addons/calendar/calendar.module.ts b/src/addons/calendar/calendar.module.ts index 8cb2dcd45..0017176f0 100644 --- a/src/addons/calendar/calendar.module.ts +++ b/src/addons/calendar/calendar.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreMainMenuRoutingModule } from '@features/mainmenu/mainmenu-routing.module'; @@ -27,8 +27,18 @@ import { CORE_SITE_SCHEMAS } from '@services/sites'; import { CALENDAR_SITE_SCHEMA } from './services/database/calendar'; import { CALENDAR_OFFLINE_SITE_SCHEMA } from './services/database/calendar-offline'; import { AddonCalendarComponentsModule } from './components/components.module'; -import { AddonCalendar } from './services/calendar'; +import { AddonCalendar, AddonCalendarProvider } from './services/calendar'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; +import { AddonCalendarOfflineProvider } from './services/calendar-offline'; +import { AddonCalendarHelperProvider } from './services/calendar-helper'; +import { AddonCalendarSyncProvider } from './services/calendar-sync'; + +export const ADDON_CALENDAR_SERVICES: Type[] = [ + AddonCalendarProvider, + AddonCalendarOfflineProvider, + AddonCalendarHelperProvider, + AddonCalendarSyncProvider, +]; const mainMenuChildrenRoutes: Routes = [ { diff --git a/src/addons/messageoutput/messageoutput.module.ts b/src/addons/messageoutput/messageoutput.module.ts index c12500d44..ac418e76b 100644 --- a/src/addons/messageoutput/messageoutput.module.ts +++ b/src/addons/messageoutput/messageoutput.module.ts @@ -12,9 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { NgModule } from '@angular/core'; +import { NgModule, Type } from '@angular/core'; import { AddonMessageOutputAirnotifierModule } from './airnotifier/airnotifier.module'; +import { AddonMessageOutputDelegateService } from './services/messageoutput-delegate'; + +export const ADDON_MESSAGEOUTPUT_SERVICES: Type[] = [ + AddonMessageOutputDelegateService, +]; @NgModule({ declarations: [ diff --git a/src/addons/messages/messages.module.ts b/src/addons/messages/messages.module.ts index d097a4363..251b053e9 100644 --- a/src/addons/messages/messages.module.ts +++ b/src/addons/messages/messages.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreMainMenuRoutingModule } from '@features/mainmenu/mainmenu-routing.module'; @@ -33,9 +33,17 @@ import { AddonMessagesPushClickHandler } from './services/handlers/push-click'; import { CoreUserDelegate } from '@features/user/services/user-delegate'; import { AddonMessagesSendMessageUserHandler } from './services/handlers/user-send-message'; import { Network, NgZone } from '@singletons'; -import { AddonMessagesSync } from './services/messages-sync'; +import { AddonMessagesSync, AddonMessagesSyncProvider } from './services/messages-sync'; import { AddonMessagesSyncCronHandler } from './services/handlers/sync-cron'; import { CoreSitePreferencesRoutingModule } from '@features/settings/pages/site/site-routing'; +import { AddonMessagesProvider } from './services/messages'; +import { AddonMessagesOfflineProvider } from './services/messages-offline'; + +export const ADDON_MESSAGES_SERVICES: Type[] = [ + AddonMessagesProvider, + AddonMessagesOfflineProvider, + AddonMessagesSyncProvider, +]; const mainMenuChildrenRoutes: Routes = [ { diff --git a/src/addons/mod/assign/assign.module.ts b/src/addons/mod/assign/assign.module.ts index c7b8f32fb..46bd253e9 100644 --- a/src/addons/mod/assign/assign.module.ts +++ b/src/addons/mod/assign/assign.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; @@ -23,15 +23,30 @@ import { CoreCronDelegate } from '@services/cron'; import { CORE_SITE_SCHEMAS } from '@services/sites'; import { AddonModAssignComponentsModule } from './components/components.module'; import { AddonModAssignFeedbackModule } from './feedback/feedback.module'; +import { AddonModAssignProvider } from './services/assign'; +import { AddonModAssignHelperProvider } from './services/assign-helper'; +import { AddonModAssignOfflineProvider } from './services/assign-offline'; +import { AddonModAssignSyncProvider } from './services/assign-sync'; import { OFFLINE_SITE_SCHEMA } from './services/database/assign'; +import { AddonModAssignFeedbackDelegateService } from './services/feedback-delegate'; import { AddonModAssignIndexLinkHandler } from './services/handlers/index-link'; import { AddonModAssignListLinkHandler } from './services/handlers/list-link'; import { AddonModAssignModuleHandler, AddonModAssignModuleHandlerService } from './services/handlers/module'; import { AddonModAssignPrefetchHandler } from './services/handlers/prefetch'; import { AddonModAssignPushClickHandler } from './services/handlers/push-click'; import { AddonModAssignSyncCronHandler } from './services/handlers/sync-cron'; +import { AddonModAssignSubmissionDelegateService } from './services/submission-delegate'; import { AddonModAssignSubmissionModule } from './submission/submission.module'; +export const ADDON_MOD_ASSIGN_SERVICES: Type[] = [ + AddonModAssignProvider, + AddonModAssignOfflineProvider, + AddonModAssignSyncProvider, + AddonModAssignHelperProvider, + AddonModAssignFeedbackDelegateService, + AddonModAssignSubmissionDelegateService, +]; + const routes: Routes = [ { path: AddonModAssignModuleHandlerService.PAGE_NAME, diff --git a/src/addons/mod/book/book.module.ts b/src/addons/mod/book/book.module.ts index d5b2b5f3a..3123cf6b6 100644 --- a/src/addons/mod/book/book.module.ts +++ b/src/addons/mod/book/book.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; @@ -25,6 +25,11 @@ import { AddonModBookIndexLinkHandler } from './services/handlers/index-link'; import { AddonModBookListLinkHandler } from './services/handlers/list-link'; import { AddonModBookPrefetchHandler } from './services/handlers/prefetch'; import { AddonModBookTagAreaHandler } from './services/handlers/tag-area'; +import { AddonModBookProvider } from './services/book'; + +export const ADDON_MOD_BOOK_SERVICES: Type[] = [ + AddonModBookProvider, +]; const routes: Routes = [ { diff --git a/src/addons/mod/folder/folder.module.ts b/src/addons/mod/folder/folder.module.ts index fb5395403..77aa6c9cd 100644 --- a/src/addons/mod/folder/folder.module.ts +++ b/src/addons/mod/folder/folder.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; @@ -20,12 +20,19 @@ import { CoreCourseModulePrefetchDelegate } from '@features/course/services/modu import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; import { CorePluginFileDelegate } from '@services/plugin-file-delegate'; import { AddonModFolderComponentsModule } from './components/components.module'; +import { AddonModFolderProvider } from './services/folder'; +import { AddonModFolderHelperProvider } from './services/folder-helper'; import { AddonModFolderIndexLinkHandler } from './services/handlers/index-link'; import { AddonModFolderListLinkHandler } from './services/handlers/list-link'; import { AddonModFolderModuleHandler, AddonModFolderModuleHandlerService } from './services/handlers/module'; import { AddonModFolderPluginFileHandler } from './services/handlers/pluginfile'; import { AddonModFolderPrefetchHandler } from './services/handlers/prefetch'; +export const ADDON_MOD_FOLDER_SERVICES: Type[] = [ + AddonModFolderProvider, + AddonModFolderHelperProvider, +]; + const routes: Routes = [ { path: AddonModFolderModuleHandlerService.PAGE_NAME, diff --git a/src/addons/mod/forum/forum.module.ts b/src/addons/mod/forum/forum.module.ts index d5ca65ae1..62acfa715 100644 --- a/src/addons/mod/forum/forum.module.ts +++ b/src/addons/mod/forum/forum.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { conditionalRoutes } from '@/app/app-routing.module'; @@ -38,6 +38,17 @@ import { CoreTagAreaDelegate } from '@features/tag/services/tag-area-delegate'; import { AddonModForumTagAreaHandler } from './services/handlers/tag-area'; import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; import { AddonModForumPushClickHandler } from './services/handlers/push-click'; +import { AddonModForumProvider } from './services/forum'; +import { AddonModForumOfflineProvider } from './services/offline'; +import { AddonModForumHelperProvider } from './services/helper'; +import { AddonModForumSyncProvider } from './services/sync'; + +export const ADDON_MOD_FORUM_SERVICES: Type[] = [ + AddonModForumProvider, + AddonModForumOfflineProvider, + AddonModForumHelperProvider, + AddonModForumSyncProvider, +]; const mainMenuRoutes: Routes = [ { diff --git a/src/addons/mod/imscp/imscp.module.ts b/src/addons/mod/imscp/imscp.module.ts index 8b3d2ff08..8684244f8 100644 --- a/src/addons/mod/imscp/imscp.module.ts +++ b/src/addons/mod/imscp/imscp.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; @@ -25,6 +25,11 @@ import { AddonModImscpListLinkHandler } from './services/handlers/list-link'; import { AddonModImscpModuleHandler, AddonModImscpModuleHandlerService } from './services/handlers/module'; import { AddonModImscpPluginFileHandler } from './services/handlers/pluginfile'; import { AddonModImscpPrefetchHandler } from './services/handlers/prefetch'; +import { AddonModImscpProvider } from './services/imscp'; + +export const ADDON_MOD_IMSCP_SERVICES: Type[] = [ + AddonModImscpProvider, +]; const routes: Routes = [ { diff --git a/src/addons/mod/lesson/lesson.module.ts b/src/addons/mod/lesson/lesson.module.ts index ac90cef84..6ec9fd6e7 100644 --- a/src/addons/mod/lesson/lesson.module.ts +++ b/src/addons/mod/lesson/lesson.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; @@ -32,6 +32,17 @@ import { AddonModLessonPrefetchHandler } from './services/handlers/prefetch'; import { AddonModLessonPushClickHandler } from './services/handlers/push-click'; import { AddonModLessonReportLinkHandler } from './services/handlers/report-link'; import { AddonModLessonSyncCronHandler } from './services/handlers/sync-cron'; +import { AddonModLessonProvider } from './services/lesson'; +import { AddonModLessonHelperProvider } from './services/lesson-helper'; +import { AddonModLessonOfflineProvider } from './services/lesson-offline'; +import { AddonModLessonSyncProvider } from './services/lesson-sync'; + +export const ADDON_MOD_LESSON_SERVICES: Type[] = [ + AddonModLessonProvider, + AddonModLessonOfflineProvider, + AddonModLessonSyncProvider, + AddonModLessonHelperProvider, +]; const routes: Routes = [ { diff --git a/src/addons/mod/page/page.module.ts b/src/addons/mod/page/page.module.ts index ffeb2558f..10bf39c71 100644 --- a/src/addons/mod/page/page.module.ts +++ b/src/addons/mod/page/page.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; @@ -25,6 +25,13 @@ import { AddonModPageListLinkHandler } from './services/handlers/list-link'; import { AddonModPageModuleHandler, AddonModPageModuleHandlerService } from './services/handlers/module'; import { AddonModPagePluginFileHandler } from './services/handlers/pluginfile'; import { AddonModPagePrefetchHandler } from './services/handlers/prefetch'; +import { AddonModPageProvider } from './services/page'; +import { AddonModPageHelperProvider } from './services/page-helper'; + +export const ADDON_MOD_PAGE_SERVICES: Type[] = [ + AddonModPageProvider, + AddonModPageHelperProvider, +]; const routes: Routes = [ { diff --git a/src/addons/mod/quiz/quiz.module.ts b/src/addons/mod/quiz/quiz.module.ts index b1e7f6401..11ecdf0ec 100644 --- a/src/addons/mod/quiz/quiz.module.ts +++ b/src/addons/mod/quiz/quiz.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; @@ -24,6 +24,7 @@ import { CoreCronDelegate } from '@services/cron'; import { CORE_SITE_SCHEMAS } from '@services/sites'; import { AddonModQuizAccessRulesModule } from './accessrules/accessrules.module'; import { AddonModQuizComponentsModule } from './components/components.module'; +import { AddonModQuizAccessRuleDelegateService } from './services/access-rules-delegate'; import { SITE_SCHEMA } from './services/database/quiz'; import { AddonModQuizGradeLinkHandler } from './services/handlers/grade-link'; import { AddonModQuizIndexLinkHandler } from './services/handlers/index-link'; @@ -33,6 +34,18 @@ import { AddonModQuizPrefetchHandler } from './services/handlers/prefetch'; import { AddonModQuizPushClickHandler } from './services/handlers/push-click'; import { AddonModQuizReviewLinkHandler } from './services/handlers/review-link'; import { AddonModQuizSyncCronHandler } from './services/handlers/sync-cron'; +import { AddonModQuizProvider } from './services/quiz'; +import { AddonModQuizHelperProvider } from './services/quiz-helper'; +import { AddonModQuizOfflineProvider } from './services/quiz-offline'; +import { AddonModQuizSyncProvider } from './services/quiz-sync'; + +export const ADDON_MOD_QUIZ_SERVICES: Type[] = [ + AddonModQuizAccessRuleDelegateService, + AddonModQuizProvider, + AddonModQuizOfflineProvider, + AddonModQuizHelperProvider, + AddonModQuizSyncProvider, +]; const routes: Routes = [ { diff --git a/src/addons/mod/resource/resource.module.ts b/src/addons/mod/resource/resource.module.ts index a546a08f6..3cecc5ec1 100644 --- a/src/addons/mod/resource/resource.module.ts +++ b/src/addons/mod/resource/resource.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; @@ -25,6 +25,11 @@ import { AddonModResourceListLinkHandler } from './services/handlers/list-link'; import { AddonModResourceModuleHandlerService, AddonModResourceModuleHandler } from './services/handlers/module'; import { AddonModResourcePluginFileHandler } from './services/handlers/pluginfile'; import { AddonModResourcePrefetchHandler } from './services/handlers/prefetch'; +import { AddonModResourceProvider } from './services/resource'; + +export const ADDON_MOD_RESOURCE_SERVICES: Type[] = [ + AddonModResourceProvider, +]; const routes: Routes = [ { diff --git a/src/addons/mod/url/url.module.ts b/src/addons/mod/url/url.module.ts index 072753931..7a30d7856 100644 --- a/src/addons/mod/url/url.module.ts +++ b/src/addons/mod/url/url.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; @@ -23,6 +23,13 @@ import { AddonModUrlIndexLinkHandler } from './services/handlers/index-link'; import { AddonModUrlListLinkHandler } from './services/handlers/list-link'; import { AddonModUrlModuleHandler, AddonModUrlModuleHandlerService } from './services/handlers/module'; import { AddonModUrlPrefetchHandler } from './services/handlers/prefetch'; +import { AddonModUrlProvider } from './services/url'; +import { AddonModUrlHelperProvider } from './services/url-helper'; + +export const ADDON_MOD_URL_SERVICES: Type[] = [ + AddonModUrlProvider, + AddonModUrlHelperProvider, +]; const routes: Routes = [ { diff --git a/src/addons/notifications/notifications.module.ts b/src/addons/notifications/notifications.module.ts index 01abc8f39..c81f9813b 100644 --- a/src/addons/notifications/notifications.module.ts +++ b/src/addons/notifications/notifications.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreCronDelegate } from '@services/cron'; @@ -26,6 +26,13 @@ import { AddonNotificationsCronHandler } from './services/handlers/cron'; import { AddonNotificationsPushClickHandler } from './services/handlers/push-click'; import { AddonNotificationsSettingsHandler, AddonNotificationsSettingsHandlerService } from './services/handlers/settings'; import { CoreSitePreferencesRoutingModule } from '@features/settings/pages/site/site-routing'; +import { AddonNotificationsProvider } from './services/notifications'; +import { AddonNotificationsHelperProvider } from './services/notifications-helper'; + +export const ADDON_NOTIFICATIONS_SERVICES: Type[] = [ + AddonNotificationsProvider, + AddonNotificationsHelperProvider, +]; const routes: Routes = [ { diff --git a/src/addons/privatefiles/privatefiles.module.ts b/src/addons/privatefiles/privatefiles.module.ts index b329899ea..48806c006 100644 --- a/src/addons/privatefiles/privatefiles.module.ts +++ b/src/addons/privatefiles/privatefiles.module.ts @@ -12,13 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreMainMenuDelegate } from '@features/mainmenu/services/mainmenu-delegate'; import { CoreMainMenuRoutingModule } from '@features/mainmenu/mainmenu-routing.module'; import { AddonPrivateFilesMainMenuHandler, AddonPrivateFilesMainMenuHandlerService } from './services/handlers/mainmenu'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; +import { AddonPrivateFilesProvider } from './services/privatefiles'; +import { AddonPrivateFilesHelperProvider } from './services/privatefiles-helper'; + +export const ADDON_PRIVATEFILES_SERVICES: Type[] = [ + AddonPrivateFilesProvider, + AddonPrivateFilesHelperProvider, +]; const routes: Routes = [ { diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b21e7da51..6a1b4a0e8 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { NgModule } from '@angular/core'; +import { COMPILER_OPTIONS, NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { RouteReuseStrategy } from '@angular/router'; @@ -28,6 +28,7 @@ import { AddonsModule } from '@/addons/addons.module'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app-routing.module'; +import { JitCompilerFactory } from '@angular/platform-browser-dynamic'; // For translate loader. AoT requires an exported function for factories. export function createTranslateLoader(http: HttpClient): TranslateHttpLoader { @@ -55,6 +56,8 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader { ], providers: [ { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, + { provide: COMPILER_OPTIONS, useValue: {}, multi: true }, + { provide: JitCompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] }, ], bootstrap: [AppComponent], }) diff --git a/src/core/core.module.ts b/src/core/core.module.ts index 55dd2b93d..ec8c88235 100644 --- a/src/core/core.module.ts +++ b/src/core/core.module.ts @@ -13,7 +13,7 @@ // limitations under the License. import { HTTP_INTERCEPTORS } from '@angular/common/http'; -import { ApplicationInitStatus, Injector, NgModule } from '@angular/core'; +import { ApplicationInitStatus, Injector, NgModule, Type } from '@angular/core'; import { CoreApplicationInitStatus } from './classes/application-init-status'; import { CoreFeaturesModule } from './features/features.module'; @@ -21,6 +21,63 @@ import { CoreInterceptor } from './classes/interceptor'; import { getDatabaseProviders } from './services/database'; import { getInitializerProviders } from './initializers'; +import { CoreDbProvider } from '@services/db'; +import { CoreAppProvider } from '@services/app'; +import { CoreConfigProvider } from '@services/config'; +import { CoreLangProvider } from '@services/lang'; +import { CoreTextUtilsProvider } from '@services/utils/text'; +import { CoreDomUtilsProvider } from '@services/utils/dom'; +import { CoreIframeUtilsProvider } from '@services/utils/iframe'; +import { CoreTimeUtilsProvider } from '@services/utils/time'; +import { CoreUrlUtilsProvider } from '@services/utils/url'; +import { CoreUtilsProvider } from '@services/utils/utils'; +import { CoreMimetypeUtilsProvider } from '@services/utils/mimetype'; +import { CoreFileProvider } from '@services/file'; +import { CoreWSProvider } from '@services/ws'; +import { CoreSitesProvider } from '@services/sites'; +import { CoreLocalNotificationsProvider } from '@services/local-notifications'; +import { CoreGroupsProvider } from '@services/groups'; +import { CoreCronDelegateService } from '@services/cron'; +import { CoreFileSessionProvider } from '@services/file-session'; +import { CoreFilepoolProvider } from '@services/filepool'; +import { CoreUpdateManagerProvider } from '@services/update-manager'; +import { CorePluginFileDelegateService } from '@services/plugin-file-delegate'; +import { CoreSyncProvider } from '@services/sync'; +import { CoreFileHelperProvider } from '@services/file-helper'; +import { CoreGeolocationProvider } from '@services/geolocation'; +import { CoreNavigatorService } from '@services/navigator'; +import { CoreScreenService } from '@services/screen'; + +export const CORE_SERVICES: Type[] = [ + CoreAppProvider, + CoreConfigProvider, + CoreCronDelegateService, + // @todo CoreCustomURLSchemesProvider, + CoreDbProvider, + CoreFileHelperProvider, + CoreFileSessionProvider, + CoreFileProvider, + CoreFilepoolProvider, + CoreGeolocationProvider, + CoreGroupsProvider, + CoreLangProvider, + CoreLocalNotificationsProvider, + CoreNavigatorService, + CorePluginFileDelegateService, + CoreScreenService, + CoreSitesProvider, + CoreSyncProvider, + CoreUpdateManagerProvider, + CoreDomUtilsProvider, + CoreIframeUtilsProvider, + CoreMimetypeUtilsProvider, + CoreTextUtilsProvider, + CoreTimeUtilsProvider, + CoreUrlUtilsProvider, + CoreUtilsProvider, + CoreWSProvider, +]; + @NgModule({ imports: [ CoreFeaturesModule, diff --git a/src/core/features/block/block.module.ts b/src/core/features/block/block.module.ts index 8092c0dbe..27a447f09 100644 --- a/src/core/features/block/block.module.ts +++ b/src/core/features/block/block.module.ts @@ -12,13 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { NgModule } from '@angular/core'; -import { CoreBlockDefaultHandler } from './services/handlers/default-block'; +import { NgModule, Type } from '@angular/core'; + +import { CoreBlockDelegateService } from './services/block-delegate'; +import { CoreBlockHelperProvider } from './services/block-helper'; + +export const CORE_BLOCK_SERVICES: Type[] = [ + CoreBlockDelegateService, + CoreBlockHelperProvider, +]; @NgModule({ - providers: [ - CoreBlockDefaultHandler, - ], + providers: [], }) -export class CoreBlockModule { -} +export class CoreBlockModule {} diff --git a/src/core/features/block/services/handlers/default-block.ts b/src/core/features/block/services/handlers/default-block.ts index f4cb57d9d..f37059a52 100644 --- a/src/core/features/block/services/handlers/default-block.ts +++ b/src/core/features/block/services/handlers/default-block.ts @@ -18,7 +18,7 @@ import { CoreBlockBaseHandler } from '../../classes/base-block-handler'; /** * Default handler used when a block type doesn't have a specific implementation. */ -@Injectable() +@Injectable({ providedIn: 'root' }) export class CoreBlockDefaultHandler extends CoreBlockBaseHandler { name = 'CoreBlockDefault'; diff --git a/src/core/features/comments/comments.module.ts b/src/core/features/comments/comments.module.ts index 491918ac8..a8b1e754c 100644 --- a/src/core/features/comments/comments.module.ts +++ b/src/core/features/comments/comments.module.ts @@ -12,16 +12,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; import { CoreCronDelegate } from '@services/cron'; import { CORE_SITE_SCHEMAS } from '@services/sites'; import { CoreCommentsComponentsModule } from './components/components.module'; -import { CoreComments } from './services/comments'; +import { CoreComments, CoreCommentsProvider } from './services/comments'; +import { CoreCommentsOfflineProvider } from './services/comments-offline'; +import { CoreCommentsSyncProvider } from './services/comments-sync'; import { COMMENTS_OFFLINE_SITE_SCHEMA } from './services/database/comments'; import { CoreCommentsSyncCronHandler } from './services/handlers/sync-cron'; +export const CORE_COMMENTS_SERVICES: Type[] = [ + CoreCommentsOfflineProvider, + CoreCommentsSyncProvider, + CoreCommentsProvider, +]; + const routes: Routes = [ { path: 'comments', diff --git a/src/core/features/compile/components/compile-html/compile-html.module.ts b/src/core/features/compile/components/compile-html/compile-html.module.ts new file mode 100644 index 000000000..be8ae045d --- /dev/null +++ b/src/core/features/compile/components/compile-html/compile-html.module.ts @@ -0,0 +1,30 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { CoreCompileHtmlComponent } from './compile-html'; +import { CoreSharedModule } from '@/core/shared.module'; + +@NgModule({ + declarations: [ + CoreCompileHtmlComponent, + ], + imports: [ + CoreSharedModule, + ], + exports: [ + CoreCompileHtmlComponent, + ], +}) +export class CoreCompileHtmlComponentModule {} diff --git a/src/core/features/compile/components/compile-html/compile-html.ts b/src/core/features/compile/components/compile-html/compile-html.ts new file mode 100644 index 000000000..a2e5ba06c --- /dev/null +++ b/src/core/features/compile/components/compile-html/compile-html.ts @@ -0,0 +1,291 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { + Component, + Input, + OnInit, + OnChanges, + OnDestroy, + ViewContainerRef, + ViewChild, + ComponentRef, + SimpleChange, + ChangeDetectorRef, + ElementRef, + Output, + EventEmitter, + DoCheck, + KeyValueDiffers, + AfterContentInit, + AfterViewInit, + Type, + KeyValueDiffer, +} from '@angular/core'; + +import { CoreCompile } from '@features/compile/services/compile'; +import { CoreDomUtils } from '@services/utils/dom'; +import { CoreUtils } from '@services/utils/utils'; + +/** + * 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: '', +}) +// eslint-disable-next-line @angular-eslint/no-conflicting-lifecycle +export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck { + + @Input() text!: string; // The HTML text to display. + @Input() javascript?: string; // The Javascript to execute in the component. + @Input() jsData?: Record; // Data to pass to the fake component. + @Input() extraImports: unknown[] = []; // Extra import modules. + @Input() extraProviders: Type[] = []; // Extra providers. + @Input() forceCompile?: boolean; // Set it to true to force compile even if the text/javascript hasn't changed. + @Output() created = new EventEmitter(); // Will emit an event when the component is instantiated. + @Output() compiling = new EventEmitter(); // Event that indicates whether the template is being compiled. + + // Get the container where to put the content. + @ViewChild('dynamicComponent', { read: ViewContainerRef }) container?: ViewContainerRef; + + loaded?: boolean; + componentInstance?: any; // eslint-disable-line @typescript-eslint/no-explicit-any + + protected componentRef?: ComponentRef; + protected element: HTMLElement; + protected differ: KeyValueDiffer; // To detect changes in the jsData input. + protected creatingComponent = false; + protected pendingCalls = {}; + + constructor( + protected changeDetector: ChangeDetectorRef, + element: ElementRef, + differs: KeyValueDiffers, + ) { + this.element = element.nativeElement; + this.differ = differs.find([]).create(); + } + + /** + * Detect and act upon changes that Angular can’t or won’t detect on its own (objects and arrays). + */ + // eslint-disable-next-line @angular-eslint/no-conflicting-lifecycle + ngDoCheck(): void { + if (!this.componentInstance || this.creatingComponent) { + return; + } + + // Check if there's any change in the jsData object. + const changes = this.differ.diff(this.jsData || {}); + if (changes) { + this.setInputData(); + + if (this.componentInstance.ngOnChanges) { + this.componentInstance.ngOnChanges(CoreDomUtils.createChangesFromKeyValueDiff(changes)); + } + } + } + + /** + * Detect changes on input properties. + */ + // eslint-disable-next-line @angular-eslint/no-conflicting-lifecycle + async ngOnChanges(changes: Record): Promise { + // Only compile if text/javascript has changed or the forceCompile flag has been set to true. + if (this.text && (changes.text || changes.javascript || + (changes.forceCompile && CoreUtils.isTrueOrOne(this.forceCompile)))) { + + // Create a new component and a new module. + this.creatingComponent = true; + this.compiling.emit(true); + + try { + const factory = await CoreCompile.createAndCompileComponent( + this.text, + this.getComponentClass(), + this.extraImports, + ); + + // Destroy previous components. + this.componentRef?.destroy(); + + if (factory) { + // Create the component. + this.componentRef = this.container?.createComponent(factory); + this.componentRef && this.created.emit(this.componentRef.instance); + } + + this.loaded = true; + } catch (error) { + CoreDomUtils.showErrorModal(error); + + this.loaded = true; + } finally { + this.creatingComponent = false; + this.compiling.emit(false); + } + } + } + + /** + * Component destroyed. + */ + // eslint-disable-next-line @angular-eslint/no-conflicting-lifecycle + ngOnDestroy(): void { + this.componentRef?.destroy(); + } + + /** + * Get a class that defines the dynamic component. + * + * @return The component class. + */ + protected getComponentClass(): Type { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const compileInstance = this; + + // Create the component, using the text as the template. + return class CoreCompileHtmlFakeComponent implements OnInit, AfterContentInit, AfterViewInit, OnDestroy { + + constructor() { + // Store this instance so it can be accessed by the outer component. + compileInstance.componentInstance = this; + + // Create 2 empty properties that can be used by the template to store data. + this['dataObject'] = {}; + this['dataArray'] = []; + + // Inject the libraries. + CoreCompile.injectLibraries(this, compileInstance.extraProviders); + + // Always add these elements, they could be needed on component init (componentObservable). + this['ChangeDetectorRef'] = compileInstance.changeDetector; + this['componentContainer'] = compileInstance.element; + + // Add the data passed to the component. + compileInstance.setInputData(); + } + + /** + * Component being initialized. + */ + ngOnInit(): void { + // If there is some javascript to run, do it now. + if (compileInstance.javascript) { + CoreCompile.executeJavascript(this, compileInstance.javascript); + } + + // Call the pending functions. + for (const name in compileInstance.pendingCalls) { + const pendingCall = compileInstance.pendingCalls[name]; + + if (typeof this[name] == 'function') { + // Call the function. + Promise.resolve(this[name].apply(this, pendingCall.params)).then(pendingCall.defer.resolve) + .catch(pendingCall.defer.reject); + } else { + // Function not defined, resolve the promise. + pendingCall.defer.resolve(); + } + } + + compileInstance.pendingCalls = {}; + } + + /** + * Content has been initialized. + */ + ngAfterContentInit(): void { + // To be overridden. + } + + /** + * View has been initialized. + */ + ngAfterViewInit(): void { + // To be overridden. + } + + /** + * Component destroyed. + */ + ngOnDestroy(): void { + // To be overridden. + } + + }; + } + + /** + * Set the JS data as input data of the component instance. + */ + protected setInputData(): void { + if (!this.componentInstance) { + return; + } + + for (const name in this.jsData) { + this.componentInstance[name] = this.jsData[name]; + } + } + + /** + * Call a certain function on the component instance. + * + * @param name Name of the function to call. + * @param params List of params to send to the function. + * @param callWhenCreated If this param is true and the component hasn't been created yet, call the function + * once the component has been created. + * @return Result of the call. Undefined if no component instance or the function doesn't exist. + */ + callComponentFunction(name: string, params?: unknown[], callWhenCreated: boolean = true): unknown { + if (this.componentInstance) { + if (typeof this.componentInstance[name] == 'function') { + return this.componentInstance[name].apply(this.componentInstance, params); + } + } else if (callWhenCreated) { + // Call it when the component is created. + + if (this.pendingCalls[name]) { + // Call already pending, just update the params (allow only 1 call per function until it's initialized). + this.pendingCalls[name].params = params; + + return this.pendingCalls[name].defer.promise; + } + + const defer = CoreUtils.promiseDefer(); + + this.pendingCalls[name] = { + params, + defer, + }; + + return defer.promise; + } + } + +} diff --git a/src/core/features/compile/services/compile.ts b/src/core/features/compile/services/compile.ts new file mode 100644 index 000000000..704968c10 --- /dev/null +++ b/src/core/features/compile/services/compile.ts @@ -0,0 +1,390 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { + Injectable, + Injector, + Component, + NgModule, + Compiler, + ComponentFactory, + ComponentRef, + NgModuleRef, + NO_ERRORS_SCHEMA, + Type, +} from '@angular/core'; +import { JitCompilerFactory } from '@angular/platform-browser-dynamic'; +import { + Platform, + ActionSheetController, + AlertController, + LoadingController, + ModalController, + PopoverController, + ToastController, +} from '@ionic/angular'; +import { TranslateService } from '@ngx-translate/core'; + +import { CoreLogger } from '@singletons/logger'; +import { CoreEvents } from '@singletons/events'; +import { makeSingleton } from '@singletons'; + +// Import core services. +import { CORE_SERVICES } from '@/core/core.module'; +import { CORE_BLOCK_SERVICES } from '@features/block/block.module'; +import { CORE_COMMENTS_SERVICES } from '@features/comments/comments.module'; +import { CORE_CONTENTLINKS_SERVICES } from '@features/contentlinks/contentlinks.module'; +import { CORE_COURSE_SERVICES } from '@features/course/course.module'; +import { CORE_COURSES_SERVICES } from '@features/courses/courses.module'; +import { CORE_EDITOR_SERVICES } from '@features/editor/editor.module'; +import { IONIC_NATIVE_SERVICES } from '@features/emulator/emulator.module'; +import { CORE_FILEUPLOADER_SERVICES } from '@features/fileuploader/fileuploader.module'; +import { CORE_FILTER_SERVICES } from '@features/filter/filter.module'; +import { CORE_GRADES_SERVICES } from '@features/grades/grades.module'; +import { CORE_H5P_SERVICES } from '@features/h5p/h5p.module'; +import { CORE_LOGIN_SERVICES } from '@features/login/login.module'; +import { CORE_MAINMENU_SERVICES } from '@features/mainmenu/mainmenu.module'; +import { CORE_PUSHNOTIFICATIONS_SERVICES } from '@features/pushnotifications/pushnotifications.module'; +import { CORE_QUESTION_SERVICES } from '@features/question/question.module'; +// @todo import { CORE_SHAREDFILES_SERVICES } from '@features/sharedfiles/sharedfiles.module'; +import { CORE_SEARCH_SERVICES } from '@features/search/search.module'; +import { CORE_SETTINGS_SERVICES } from '@features/settings/settings.module'; +import { CORE_SITEHOME_SERVICES } from '@features/sitehome/sitehome.module'; +import { CORE_TAG_SERVICES } from '@features/tag/tag.module'; +import { CORE_USER_SERVICES } from '@features/user/user.module'; +import { CORE_XAPI_SERVICES } from '@features/xapi/xapi.module'; +// @todo import { CoreSitePluginsProvider } from '@features/siteplugins/services/siteplugins'; + +// Import other libraries and providers. +import { DomSanitizer } from '@angular/platform-browser'; +import { FormBuilder, Validators } from '@angular/forms'; +import { HttpClient } from '@angular/common/http'; +import { CoreConstants } from '@/core/constants'; +import 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 { CoreArray } from '@singletons/array'; +import { CoreUrl } from '@singletons/url'; +import { CoreWindow } from '@singletons/window'; +import { CoreCache } from '@classes/cache'; +import { CoreDelegate } from '@classes/delegate'; +import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler'; +import { CoreContentLinksModuleGradeHandler } from '@features/contentlinks/classes/module-grade-handler'; +import { CoreContentLinksModuleIndexHandler } from '@features/contentlinks/classes/module-index-handler'; +import { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/activity-prefetch-handler'; +import { CoreCourseResourcePrefetchHandlerBase } from '@features/course/classes/resource-prefetch-handler'; +import { CoreGeolocationError, CoreGeolocationErrorReason } from '@services/geolocation'; + +// Import all core modules that define components, directives and pipes. +import { CoreSharedModule } from '@/core/shared.module'; +import { CoreCourseComponentsModule } from '@features/course/components/components.module'; +import { CoreCourseDirectivesModule } from '@features/course/directives/directives.module'; +import { CoreCoursesComponentsModule } from '@features/courses/components/components.module'; +// @todo import { CoreSitePluginsDirectivesModule } from '@features/siteplugins/directives/directives.module'; +import { CoreUserComponentsModule } from '@features/user/components/components.module'; +import { CoreQuestionComponentsModule } from '@features/question/components/components.module'; +import { CoreBlockComponentsModule } from '@features/block/components/components.module'; +import { CoreEditorComponentsModule } from '@features/editor/components/components.module'; +import { CoreSearchComponentsModule } from '@features/search/components/components.module'; + +// Import some components so they can be injected dynamically. +import { CoreCourseUnsupportedModuleComponent } from '@features/course/components/unsupported-module/unsupported-module'; +import { CoreCourseFormatSingleActivityComponent } from '@features/course/format/singleactivity/components/singleactivity'; +// @todo +// import { CoreSitePluginsModuleIndexComponent } from '@features/siteplugins/components/module-index/module-index'; +// import { CoreSitePluginsBlockComponent } from '@features/siteplugins/components/block/block'; +// import { CoreSitePluginsCourseOptionComponent } from '@features/siteplugins/components/course-option/course-option'; +// import { CoreSitePluginsCourseFormatComponent } from '@features/siteplugins/components/course-format/course-format'; +// import { CoreSitePluginsQuestionComponent } from '@features/siteplugins/components/question/question'; +// import { CoreSitePluginsQuestionBehaviourComponent } from '@features/siteplugins/components/question-behaviour/question-behaviour'; +// import { CoreSitePluginsUserProfileFieldComponent } from '@features/siteplugins/components/user-profile-field/user-profile-field'; +// import { CoreSitePluginsQuizAccessRuleComponent } from '@features/siteplugins/components/quiz-access-rule/quiz-access-rule'; +// import { CoreSitePluginsAssignFeedbackComponent } from '@features/siteplugins/components/assign-feedback/assign-feedback'; +// import { CoreSitePluginsAssignSubmissionComponent } from '@features/siteplugins/components/assign-submission/assign-submission'; + +// Import addon providers. Do not import database module because it causes circular dependencies. +import { ADDON_BADGES_SERVICES } from '@addons/badges/badges.module'; +import { ADDON_CALENDAR_SERVICES } from '@addons/calendar/calendar.module'; +// @todo import { ADDON_COMPETENCY_SERVICES } from '@addons/competency/competency.module'; +import { ADDON_MESSAGEOUTPUT_SERVICES } from '@addons/messageoutput/messageoutput.module'; +import { ADDON_MESSAGES_SERVICES } from '@addons/messages/messages.module'; +import { ADDON_MOD_ASSIGN_SERVICES } from '@addons/mod/assign/assign.module'; +import { ADDON_MOD_BOOK_SERVICES } from '@addons/mod/book/book.module'; +// @todo import { ADDON_MOD_CHAT_SERVICES } from '@addons/mod/chat/chat.module'; +// @todo import { ADDON_MOD_CHOICE_SERVICES } from '@addons/mod/choice/choice.module'; +// @todo import { ADDON_MOD_FEEDBACK_SERVICES } from '@addons/mod/feedback/feedback.module'; +import { ADDON_MOD_FOLDER_SERVICES } from '@addons/mod/folder/folder.module'; +import { ADDON_MOD_FORUM_SERVICES } from '@addons/mod/forum/forum.module'; +// @todo import { ADDON_MOD_GLOSSARY_SERVICES } from '@addons/mod/glossary/glossary.module'; +// @todo import { ADDON_MOD_H5P_ACTIVITY_SERVICES } from '@addons/mod/h5pactivity/h5pactivity.module'; +import { ADDON_MOD_IMSCP_SERVICES } from '@addons/mod/imscp/imscp.module'; +import { ADDON_MOD_LESSON_SERVICES } from '@addons/mod/lesson/lesson.module'; +// @todo import { ADDON_MOD_LTI_SERVICES } from '@addons/mod/lti/lti.module'; +import { ADDON_MOD_PAGE_SERVICES } from '@addons/mod/page/page.module'; +import { ADDON_MOD_QUIZ_SERVICES } from '@addons/mod/quiz/quiz.module'; +import { ADDON_MOD_RESOURCE_SERVICES } from '@addons/mod/resource/resource.module'; +// @todo import { ADDON_MOD_SCORM_SERVICES } from '@addons/mod/scorm/scorm.module'; +// @todo import { ADDON_MOD_SURVEY_SERVICES } from '@addons/mod/survey/survey.module'; +import { ADDON_MOD_URL_SERVICES } from '@addons/mod/url/url.module'; +// @todo import { ADDON_MOD_WIKI_SERVICES } from '@addons/mod/wiki/wiki.module'; +// @todo import { ADDON_MOD_WORKSHOP_SERVICES } from '@addons/mod/workshop/workshop.module'; +// @todo import { ADDON_NOTES_SERVICES } from '@addons/notes/notes.module'; +import { ADDON_NOTIFICATIONS_SERVICES } from '@addons/notifications/notifications.module'; +import { ADDON_PRIVATEFILES_SERVICES } from '@addons/privatefiles/privatefiles.module'; +// @todo import { ADDON_REMOTETHEMES_SERVICES } from '@addons/remotethemes/remotethemes.module'; + +// Import some addon modules that define components, directives and pipes. Only import the important ones. +import { AddonModAssignComponentsModule } from '@addons/mod/assign/components/components.module'; +// @todo import { AddonModWorkshopComponentsModule } from '@addons/mod/workshop/components/components.module'; + +/** + * Service to provide functionalities regarding compiling dynamic HTML and Javascript. + */ +@Injectable({ providedIn: 'root' }) +export class CoreCompileProvider { + + protected logger: CoreLogger; + protected compiler: Compiler; + + // Other Ionic/Angular providers that don't depend on where they are injected. + protected readonly OTHER_SERVICES: unknown[] = [ + TranslateService, 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 readonly IMPORTS = [ + CoreSharedModule, CoreCourseComponentsModule, CoreCoursesComponentsModule, CoreUserComponentsModule, + CoreCourseDirectivesModule, CoreQuestionComponentsModule, AddonModAssignComponentsModule, + CoreBlockComponentsModule, CoreEditorComponentsModule, CoreSearchComponentsModule, + // @todo AddonModWorkshopComponentsModule, CoreSitePluginsDirectivesModule, + ]; + + constructor(protected injector: Injector, compilerFactory: JitCompilerFactory) { + this.logger = CoreLogger.getInstance('CoreCompileProvider'); + + this.compiler = compilerFactory.createCompiler(); + } + + /** + * Create and compile a dynamic component. + * + * @param template The template of the component. + * @param componentClass The JS class of the component. + * @param extraImports Extra imported modules if needed and not imported by this class. + * @return Promise resolved with the factory to instantiate the component. + */ + async createAndCompileComponent( + template: string, + componentClass: Type, + extraImports: any[] = [], // eslint-disable-line @typescript-eslint/no-explicit-any + ): Promise | undefined> { + // Create the component using the template and the class. + const component = Component({ template })(componentClass); + + const imports = [ + ...this.IMPORTS, + ...extraImports, + ]; + + // Now create the module containing the component. + const module = NgModule({ imports, declarations: [component], schemas: [NO_ERRORS_SCHEMA] })(class {}); + + try { + // Compile the module and the component. + const factories = await this.compiler.compileModuleAndAllComponentsAsync(module); + + // Search and return the factory of the component we just created. + return factories.componentFactories.find(factory => factory.componentType == component); + } catch (error) { + this.logger.error('Error compiling template', template); + this.logger.error(error); + error.message = 'Template has some errors and cannot be displayed.'; + + throw error; + } + } + + /** + * Eval some javascript using the context of the function. + * + * @param javascript The javascript to eval. + * @return Result of the eval. + */ + protected evalInContext(javascript: string): unknown { + // eslint-disable-next-line no-eval + return eval(javascript); + } + + /** + * Execute some javascript code, using a certain instance as the context. + * + * @param instance Instance to use as the context. In the JS code, "this" will be this instance. + * @param javascript The javascript code to eval. + * @return Result of the javascript execution. + */ + executeJavascript(instance: unknown, javascript: string): unknown { + 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 instance The instance where to inject the libraries. + * @param extraProviders Extra imported providers if needed and not imported by this class. + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + injectLibraries(instance: any, extraProviders: Type[] = []): void { + const providers = [ + ...CORE_SERVICES, + ...CORE_BLOCK_SERVICES, + ...CORE_COMMENTS_SERVICES, + ...CORE_CONTENTLINKS_SERVICES, + ...CORE_COURSE_SERVICES, + ...CORE_COURSES_SERVICES, + ...CORE_EDITOR_SERVICES, + ...CORE_FILEUPLOADER_SERVICES, + ...CORE_FILTER_SERVICES, + ...CORE_GRADES_SERVICES, + ...CORE_H5P_SERVICES, + ...CORE_MAINMENU_SERVICES, + ...CORE_LOGIN_SERVICES, + ...CORE_QUESTION_SERVICES, + ...CORE_PUSHNOTIFICATIONS_SERVICES, + ...CORE_SEARCH_SERVICES, + ...CORE_SETTINGS_SERVICES, + // @todo ...CORE_SHAREDFILES_SERVICES, + ...CORE_SITEHOME_SERVICES, + // @todo ...CoreSitePluginsProvider, + ...CORE_TAG_SERVICES, + ...CORE_USER_SERVICES, + ...CORE_XAPI_SERVICES, + ...IONIC_NATIVE_SERVICES, + ...this.OTHER_SERVICES, + ...extraProviders, + ...ADDON_BADGES_SERVICES, + ...ADDON_CALENDAR_SERVICES, + // @todo ...ADDON_COMPETENCY_SERVICES, + ...ADDON_MESSAGEOUTPUT_SERVICES, + ...ADDON_MESSAGES_SERVICES, + ...ADDON_MOD_ASSIGN_SERVICES, + ...ADDON_MOD_BOOK_SERVICES, + // @todo ...ADDON_MOD_CHAT_SERVICES, + // @todo ...ADDON_MOD_CHOICE_SERVICES, + // @todo ...ADDON_MOD_FEEDBACK_SERVICES, + ...ADDON_MOD_FOLDER_SERVICES, + ...ADDON_MOD_FORUM_SERVICES, + // @todo ...ADDON_MOD_GLOSSARY_SERVICES, + // @todo ...ADDON_MOD_H5P_ACTIVITY_SERVICES, + ...ADDON_MOD_IMSCP_SERVICES, + ...ADDON_MOD_LESSON_SERVICES, + // @todo ...ADDON_MOD_LTI_SERVICES, + ...ADDON_MOD_PAGE_SERVICES, + ...ADDON_MOD_QUIZ_SERVICES, + ...ADDON_MOD_RESOURCE_SERVICES, + // @todo ...ADDON_MOD_SCORM_SERVICES, + // @todo ...ADDON_MOD_SURVEY_SERVICES, + ...ADDON_MOD_URL_SERVICES, + // @todo ...ADDON_MOD_WIKI_SERVICES, + // @todo ...ADDON_MOD_WORKSHOP_SERVICES, + // @todo ...ADDON_NOTES_SERVICES, + ...ADDON_NOTIFICATIONS_SERVICES, + ...ADDON_PRIVATEFILES_SERVICES, + // @todo ...ADDON_REMOTETHEMES_SERVICES, + ]; + + // 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.replace(/DelegateService$/, 'Delegate')] = 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['CoreConstants'] = CoreConstants; + instance['CoreConfigConstants'] = CoreConstants.CONFIG; + instance['CoreEventsProvider'] = CoreEvents; + instance['CoreLoggerProvider'] = CoreLogger; + instance['moment'] = moment; + instance['Md5'] = Md5; + instance['CoreSyncBaseProvider'] = CoreSyncBaseProvider; + instance['CoreArray'] = CoreArray; + instance['CoreUrl'] = CoreUrl; + instance['CoreWindow'] = CoreWindow; + instance['CoreCache'] = CoreCache; + instance['CoreDelegate'] = CoreDelegate; + instance['CoreContentLinksHandlerBase'] = CoreContentLinksHandlerBase; + instance['CoreContentLinksModuleGradeHandler'] = CoreContentLinksModuleGradeHandler; + instance['CoreContentLinksModuleIndexHandler'] = CoreContentLinksModuleIndexHandler; + instance['CoreCourseActivityPrefetchHandlerBase'] = CoreCourseActivityPrefetchHandlerBase; + instance['CoreCourseResourcePrefetchHandlerBase'] = CoreCourseResourcePrefetchHandlerBase; + instance['CoreCourseUnsupportedModuleComponent'] = CoreCourseUnsupportedModuleComponent; + instance['CoreCourseFormatSingleActivityComponent'] = CoreCourseFormatSingleActivityComponent; + // @todo instance['CoreSitePluginsModuleIndexComponent'] = CoreSitePluginsModuleIndexComponent; + // instance['CoreSitePluginsBlockComponent'] = CoreSitePluginsBlockComponent; + // instance['CoreSitePluginsCourseOptionComponent'] = CoreSitePluginsCourseOptionComponent; + // instance['CoreSitePluginsCourseFormatComponent'] = CoreSitePluginsCourseFormatComponent; + // instance['CoreSitePluginsQuestionComponent'] = CoreSitePluginsQuestionComponent; + // instance['CoreSitePluginsQuestionBehaviourComponent'] = CoreSitePluginsQuestionBehaviourComponent; + // instance['CoreSitePluginsUserProfileFieldComponent'] = CoreSitePluginsUserProfileFieldComponent; + // instance['CoreSitePluginsQuizAccessRuleComponent'] = CoreSitePluginsQuizAccessRuleComponent; + // instance['CoreSitePluginsAssignFeedbackComponent'] = CoreSitePluginsAssignFeedbackComponent; + // instance['CoreSitePluginsAssignSubmissionComponent'] = CoreSitePluginsAssignSubmissionComponent; + instance['CoreGeolocationError'] = CoreGeolocationError; + instance['CoreGeolocationErrorReason'] = CoreGeolocationErrorReason; + } + + /** + * Instantiate a dynamic component. + * + * @param template The template of the component. + * @param componentClass The JS class of the component. + * @param injector The injector to use. It's recommended to pass it so NavController and similar can be injected. + * @return Promise resolved with the component instance. + */ + async instantiateDynamicComponent( + template: string, + componentClass: Type, + injector?: Injector, + ): Promise | undefined> { + injector = injector || this.injector; + + const factory = await this.createAndCompileComponent(template, componentClass); + + if (factory) { + // Create and return the component. + return factory.create(injector, undefined, undefined, injector.get(NgModuleRef)); + } + } + +} + +export const CoreCompile = makeSingleton(CoreCompileProvider); diff --git a/src/core/features/contentlinks/contentlinks.module.ts b/src/core/features/contentlinks/contentlinks.module.ts new file mode 100644 index 000000000..c7d9d1210 --- /dev/null +++ b/src/core/features/contentlinks/contentlinks.module.ts @@ -0,0 +1,31 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule, Type } from '@angular/core'; + +import { CoreContentLinksDelegateService } from './services/contentlinks-delegate'; +import { CoreContentLinksHelperProvider } from './services/contentlinks-helper'; + +export const CORE_CONTENTLINKS_SERVICES: Type[] = [ + CoreContentLinksDelegateService, + CoreContentLinksHelperProvider, +]; + +@NgModule({ + declarations: [], + imports: [], + providers: [], + exports: [], +}) +export class CoreContentLinksModule {} diff --git a/src/core/features/course/course.module.ts b/src/core/features/course/course.module.ts index 8c921270f..b795315c4 100644 --- a/src/core/features/course/course.module.ts +++ b/src/core/features/course/course.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; @@ -24,14 +24,33 @@ import { SITE_SCHEMA, OFFLINE_SITE_SCHEMA } from './services/database/course'; import { SITE_SCHEMA as LOG_SITE_SCHEMA } from './services/database/log'; import { SITE_SCHEMA as PREFETCH_SITE_SCHEMA } from './services/database/module-prefetch'; import { CoreCourseIndexRoutingModule } from './pages/index/index-routing.module'; -import { CoreCourseModulePrefetchDelegate } from './services/module-prefetch-delegate'; +import { CoreCourseModulePrefetchDelegate, CoreCourseModulePrefetchDelegateService } from './services/module-prefetch-delegate'; import { CoreCronDelegate } from '@services/cron'; import { CoreCourseLogCronHandler } from './services/handlers/log-cron'; import { CoreCourseSyncCronHandler } from './services/handlers/sync-cron'; import { CoreTagAreaDelegate } from '@features/tag/services/tag-area-delegate'; import { CoreCourseTagAreaHandler } from './services/handlers/course-tag-area'; import { CoreCourseModulesTagAreaHandler } from './services/handlers/modules-tag-area'; -import { CoreCourse } from './services/course'; +import { CoreCourse, CoreCourseProvider } from './services/course'; +import { CoreCourseHelperProvider } from './services/course-helper'; +import { CoreCourseLogHelperProvider } from './services/log-helper'; +import { CoreCourseFormatDelegateService } from './services/format-delegate'; +import { CoreCourseModuleDelegateService } from './services/module-delegate'; +import { CoreCourseOptionsDelegateService } from './services/course-options-delegate'; +import { CoreCourseOfflineProvider } from './services/course-offline'; +import { CoreCourseSyncProvider } from './services/sync'; + +export const CORE_COURSE_SERVICES: Type[] = [ + CoreCourseProvider, + CoreCourseHelperProvider, + CoreCourseLogHelperProvider, + CoreCourseFormatDelegateService, + CoreCourseModuleDelegateService, + CoreCourseModulePrefetchDelegateService, + CoreCourseOptionsDelegateService, + CoreCourseOfflineProvider, + CoreCourseSyncProvider, +]; const routes: Routes = [ { diff --git a/src/core/features/courses/courses.module.ts b/src/core/features/courses/courses.module.ts index 46221b207..611ca2132 100644 --- a/src/core/features/courses/courses.module.ts +++ b/src/core/features/courses/courses.module.ts @@ -12,13 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreMainMenuHomeRoutingModule } from '@features/mainmenu/pages/home/home-routing.module'; import { CoreMainMenuHomeDelegate } from '@features/mainmenu/services/home-delegate'; import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; +import { CoreCoursesProvider } from './services/courses'; +import { CoreCoursesHelperProvider } from './services/courses-helper'; +import { CoreCoursesDashboardProvider } from './services/dashboard'; import { CoreCoursesCourseLinkHandler } from './services/handlers/course-link'; import { CoreCoursesIndexLinkHandler } from './services/handlers/courses-index-link'; @@ -28,6 +31,12 @@ import { CoreCoursesEnrolPushClickHandler } from './services/handlers/enrol-push import { CoreCoursesMyCoursesHomeHandler, CoreCoursesMyCoursesHomeHandlerService } from './services/handlers/my-courses-home'; import { CoreCoursesRequestPushClickHandler } from './services/handlers/request-push-click'; +export const CORE_COURSES_SERVICES: Type[] = [ + CoreCoursesProvider, + CoreCoursesDashboardProvider, + CoreCoursesHelperProvider, +]; + const mainMenuHomeChildrenRoutes: Routes = [ { path: '', diff --git a/src/core/features/editor/editor.module.ts b/src/core/features/editor/editor.module.ts index 012860b7c..49cf85887 100644 --- a/src/core/features/editor/editor.module.ts +++ b/src/core/features/editor/editor.module.ts @@ -12,11 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { NgModule } from '@angular/core'; +import { NgModule, Type } from '@angular/core'; import { CORE_SITE_SCHEMAS } from '@services/sites'; import { CoreEditorComponentsModule } from './components/components.module'; import { SITE_SCHEMA } from './services/database/editor'; +import { CoreEditorOfflineProvider } from './services/editor-offline'; + +export const CORE_EDITOR_SERVICES: Type[] = [ + CoreEditorOfflineProvider, +]; @NgModule({ declarations: [ diff --git a/src/core/features/emulator/emulator.module.ts b/src/core/features/emulator/emulator.module.ts index 9322dd5b8..03d2e211f 100644 --- a/src/core/features/emulator/emulator.module.ts +++ b/src/core/features/emulator/emulator.module.ts @@ -45,6 +45,33 @@ import { StatusBar } from '@ionic-native/status-bar/ngx'; import { WebIntent } from '@ionic-native/web-intent/ngx'; import { Zip } from '@ionic-native/zip/ngx'; +export const IONIC_NATIVE_SERVICES = [ + Badge, + Camera, + Chooser, + Clipboard, + Device, + Diagnostic, + File, + FileOpener, + FileTransfer, + Geolocation, + HTTP, + InAppBrowser, + Keyboard, + LocalNotifications, + Media, + MediaCapture, + Network, + Push, + QRScanner, + SplashScreen, + StatusBar, + SQLite, + WebIntent, + WebView, + Zip, +]; // Mock services. import { CameraMock } from './services/camera'; import { ClipboardMock } from './services/clipboard'; diff --git a/src/core/features/fileuploader/fileuploader.module.ts b/src/core/features/fileuploader/fileuploader.module.ts index 092e8e1a9..52b8d91da 100644 --- a/src/core/features/fileuploader/fileuploader.module.ts +++ b/src/core/features/fileuploader/fileuploader.module.ts @@ -12,15 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; -import { CoreFileUploaderDelegate } from './services/fileuploader-delegate'; +import { CoreFileUploaderProvider } from './services/fileuploader'; +import { CoreFileUploaderDelegate, CoreFileUploaderDelegateService } from './services/fileuploader-delegate'; +import { CoreFileUploaderHelperProvider } from './services/fileuploader-helper'; import { CoreFileUploaderAlbumHandler } from './services/handlers/album'; import { CoreFileUploaderAudioHandler } from './services/handlers/audio'; import { CoreFileUploaderCameraHandler } from './services/handlers/camera'; import { CoreFileUploaderFileHandler } from './services/handlers/file'; import { CoreFileUploaderVideoHandler } from './services/handlers/video'; +export const CORE_FILEUPLOADER_SERVICES: Type[] = [ + CoreFileUploaderProvider, + CoreFileUploaderHelperProvider, + CoreFileUploaderDelegateService, +]; @NgModule({ imports: [], diff --git a/src/core/features/filter/filter.module.ts b/src/core/features/filter/filter.module.ts new file mode 100644 index 000000000..23ddcd933 --- /dev/null +++ b/src/core/features/filter/filter.module.ts @@ -0,0 +1,31 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule, Type } from '@angular/core'; +import { CoreFilterProvider } from './services/filter'; +import { CoreFilterDelegateService } from './services/filter-delegate'; +import { CoreFilterHelperProvider } from './services/filter-helper'; + +export const CORE_FILTER_SERVICES: Type[] = [ + CoreFilterProvider, + CoreFilterDelegateService, + CoreFilterHelperProvider, +]; + +@NgModule({ + declarations: [], + imports: [], + providers: [], +}) +export class CoreFilterModule { } diff --git a/src/core/features/grades/grades.module.ts b/src/core/features/grades/grades.module.ts index 05da84659..3a3a3d23f 100644 --- a/src/core/features/grades/grades.module.ts +++ b/src/core/features/grades/grades.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreCourseIndexRoutingModule } from '@features/course/pages/index/index-routing.module'; @@ -21,12 +21,19 @@ import { CoreMainMenuRoutingModule } from '@features/mainmenu/mainmenu-routing.m import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; import { CoreMainMenuDelegate } from '@features/mainmenu/services/mainmenu-delegate'; import { CoreUserDelegate } from '@features/user/services/user-delegate'; +import { CoreGradesProvider } from './services/grades'; +import { CoreGradesHelperProvider } from './services/grades-helper'; import { CoreGradesCourseOptionHandler } from './services/handlers/course-option'; import { CoreGradesMainMenuHandler, CoreGradesMainMenuHandlerService } from './services/handlers/mainmenu'; import { CoreGradesOverviewLinkHandler } from './services/handlers/overview-link'; import { CoreGradesUserHandler } from './services/handlers/user'; import { CoreGradesUserLinkHandler } from './services/handlers/user-link'; +export const CORE_GRADES_SERVICES: Type[] = [ + CoreGradesProvider, + CoreGradesHelperProvider, +]; + const routes: Routes = [ { path: CoreGradesMainMenuHandlerService.PAGE_NAME, diff --git a/src/core/features/h5p/h5p.module.ts b/src/core/features/h5p/h5p.module.ts index cd988c458..e8be04d82 100644 --- a/src/core/features/h5p/h5p.module.ts +++ b/src/core/features/h5p/h5p.module.ts @@ -12,14 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { CorePluginFileDelegate } from '@services/plugin-file-delegate'; import { CORE_SITE_SCHEMAS } from '@services/sites'; import { CoreH5PComponentsModule } from './components/components.module'; import { SITE_SCHEMA } from './services/database/h5p'; +import { CoreH5PProvider } from './services/h5p'; import { CoreH5PPluginFileHandler } from './services/handlers/pluginfile'; +export const CORE_H5P_SERVICES: Type[] = [ + CoreH5PProvider, +]; + @NgModule({ imports: [ CoreH5PComponentsModule, diff --git a/src/core/features/login/login.module.ts b/src/core/features/login/login.module.ts index f17cb2bbe..8525d25b7 100644 --- a/src/core/features/login/login.module.ts +++ b/src/core/features/login/login.module.ts @@ -16,6 +16,11 @@ import { NgModule } from '@angular/core'; import { Routes } from '@angular/router'; import { AppRoutingModule } from '@/app/app-routing.module'; +import { CoreLoginHelperProvider } from './services/login-helper'; + +export const CORE_LOGIN_SERVICES = [ + CoreLoginHelperProvider, +]; const appRoutes: Routes = [ { diff --git a/src/core/features/mainmenu/mainmenu.module.ts b/src/core/features/mainmenu/mainmenu.module.ts index a6d3b9cf8..0c871de7d 100644 --- a/src/core/features/mainmenu/mainmenu.module.ts +++ b/src/core/features/mainmenu/mainmenu.module.ts @@ -18,8 +18,16 @@ import { CoreMainMenuAuthGuard } from '@features/mainmenu/guards/auth'; import { AppRoutingModule } from '@/app/app-routing.module'; -import { CoreMainMenuDelegate } from './services/mainmenu-delegate'; +import { CoreMainMenuDelegate, CoreMainMenuDelegateService } from './services/mainmenu-delegate'; import { CoreMainMenuHomeHandler } from './services/handlers/mainmenu'; +import { CoreMainMenuProvider } from './services/mainmenu'; +import { CoreMainMenuHomeDelegateService } from './services/home-delegate'; + +export const CORE_MAINMENU_SERVICES = [ + CoreMainMenuHomeDelegateService, + CoreMainMenuDelegateService, + CoreMainMenuProvider, +]; const appRoutes: Routes = [ { diff --git a/src/core/features/pushnotifications/pushnotifications.module.ts b/src/core/features/pushnotifications/pushnotifications.module.ts index 797698106..fac638aa2 100644 --- a/src/core/features/pushnotifications/pushnotifications.module.ts +++ b/src/core/features/pushnotifications/pushnotifications.module.ts @@ -12,14 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { CoreCronDelegate } from '@services/cron'; import { CORE_SITE_SCHEMAS } from '@services/sites'; import { SITE_SCHEMA } from './services/database/pushnotifications'; import { CorePushNotificationsRegisterCronHandler } from './services/handlers/register-cron'; import { CorePushNotificationsUnregisterCronHandler } from './services/handlers/unregister-cron'; -import { CorePushNotifications } from './services/pushnotifications'; +import { CorePushNotificationsDelegateService } from './services/push-delegate'; +import { CorePushNotifications, CorePushNotificationsProvider } from './services/pushnotifications'; + +export const CORE_PUSHNOTIFICATIONS_SERVICES: Type[] = [ + CorePushNotificationsProvider, + CorePushNotificationsDelegateService, +]; @NgModule({ declarations: [ diff --git a/src/core/features/question/question.module.ts b/src/core/features/question/question.module.ts new file mode 100644 index 000000000..321fe2106 --- /dev/null +++ b/src/core/features/question/question.module.ts @@ -0,0 +1,34 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule, Type } from '@angular/core'; +import { CoreQuestionBehaviourDelegateService } from './services/behaviour-delegate'; +import { CoreQuestionProvider } from './services/question'; +import { CoreQuestionDelegateService } from './services/question-delegate'; +import { CoreQuestionHelperProvider } from './services/question-helper'; + +export const CORE_QUESTION_SERVICES: Type[] = [ + CoreQuestionProvider, + CoreQuestionDelegateService, + CoreQuestionBehaviourDelegateService, + CoreQuestionHelperProvider, +]; + +@NgModule({ + declarations: [], + imports: [], + providers: [], + exports: [], +}) +export class CoreQuestionModule {} diff --git a/src/core/features/search/search.module.ts b/src/core/features/search/search.module.ts index 89ba8527e..b60effb9c 100644 --- a/src/core/features/search/search.module.ts +++ b/src/core/features/search/search.module.ts @@ -12,12 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { NgModule } from '@angular/core'; +import { NgModule, Type } from '@angular/core'; import { CORE_SITE_SCHEMAS } from '@services/sites'; import { CoreSearchComponentsModule } from './components/components.module'; import { SITE_SCHEMA } from './services/search-history-db'; +import { CoreSearchHistoryProvider } from './services/search-history.service'; + +export const CORE_SEARCH_SERVICES: Type[] = [ + CoreSearchHistoryProvider, +]; @NgModule({ imports: [ diff --git a/src/core/features/settings/settings.module.ts b/src/core/features/settings/settings.module.ts index cbafdfd34..28db5b75b 100644 --- a/src/core/features/settings/settings.module.ts +++ b/src/core/features/settings/settings.module.ts @@ -12,13 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { AppRoutingModule } from '@/app/app-routing.module'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; - import { CoreSettingsHelperProvider } from './services/settings-helper'; +import { CoreSettingsDelegateService } from './services/settings-delegate'; + +export const CORE_SETTINGS_SERVICES: Type[] = [ + CoreSettingsDelegateService, + CoreSettingsHelperProvider, +]; const appRoutes: Routes = [ { diff --git a/src/core/features/sitehome/sitehome.module.ts b/src/core/features/sitehome/sitehome.module.ts index 0b80ab422..d77faecd2 100644 --- a/src/core/features/sitehome/sitehome.module.ts +++ b/src/core/features/sitehome/sitehome.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreSiteHomeIndexLinkHandler } from './services/handlers/index-link'; @@ -20,6 +20,11 @@ import { CoreContentLinksDelegate } from '@features/contentlinks/services/conten import { CoreSiteHomeHomeHandler, CoreSiteHomeHomeHandlerService } from './services/handlers/sitehome-home'; import { CoreMainMenuHomeDelegate } from '@features/mainmenu/services/home-delegate'; import { CoreMainMenuHomeRoutingModule } from '@features/mainmenu/pages/home/home-routing.module'; +import { CoreSiteHomeProvider } from './services/sitehome'; + +export const CORE_SITEHOME_SERVICES: Type[] = [ + CoreSiteHomeProvider, +]; const mainMenuHomeRoutes: Routes = [ { diff --git a/src/core/features/tag/tag.module.ts b/src/core/features/tag/tag.module.ts index 13b957682..939c204f8 100644 --- a/src/core/features/tag/tag.module.ts +++ b/src/core/features/tag/tag.module.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreMainMenuDelegate } from '@features/mainmenu/services/mainmenu-delegate'; import { CoreMainMenuRoutingModule } from '../mainmenu/mainmenu-routing.module'; @@ -22,6 +22,15 @@ import { CoreTagIndexLinkHandler } from './services/handlers/index-link'; import { CoreTagSearchLinkHandler } from './services/handlers/search-link'; import { CoreTagComponentsModule } from './components/components.module'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; +import { CoreTagAreaDelegateService } from './services/tag-area-delegate'; +import { CoreTagHelperProvider } from './services/tag-helper'; +import { CoreTagProvider } from './services/tag'; + +export const CORE_TAG_SERVICES: Type[] = [ + CoreTagAreaDelegateService, + CoreTagHelperProvider, + CoreTagProvider, +]; const routes: Routes = [ { diff --git a/src/core/features/user/user.module.ts b/src/core/features/user/user.module.ts index 7eac3eea3..52c1e87ef 100644 --- a/src/core/features/user/user.module.ts +++ b/src/core/features/user/user.module.ts @@ -12,14 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { APP_INITIALIZER, NgModule, Type } from '@angular/core'; import { Routes } from '@angular/router'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; import { CORE_SITE_SCHEMAS } from '@services/sites'; import { SITE_SCHEMA, OFFLINE_SITE_SCHEMA } from './services/database/user'; import { CoreUserComponentsModule } from './components/components.module'; -import { CoreUserDelegate } from './services/user-delegate'; +import { CoreUserDelegate, CoreUserDelegateService } from './services/user-delegate'; import { CoreUserProfileMailHandler } from './services/handlers/profile-mail'; import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreUserProfileLinkHandler } from './services/handlers/profile-link'; @@ -30,6 +30,20 @@ import { CoreTagAreaDelegate } from '@features/tag/services/tag-area-delegate'; import { CoreCourseIndexRoutingModule } from '@features/course/pages/index/index-routing.module'; import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate'; import { CoreUserCourseOptionHandler } from './services/handlers/course-option'; +import { CoreUserProfileFieldDelegateService } from './services/user-profile-field-delegate'; +import { CoreUserProvider } from './services/user'; +import { CoreUserHelperProvider } from './services/user-helper'; +import { CoreUserOfflineProvider } from './services/user-offline'; +import { CoreUserSyncProvider } from './services/user-sync'; + +export const CORE_USER_SERVICES: Type[] = [ + CoreUserDelegateService, + CoreUserProfileFieldDelegateService, + CoreUserProvider, + CoreUserHelperProvider, + CoreUserOfflineProvider, + CoreUserSyncProvider, +]; const routes: Routes = [ { diff --git a/src/core/features/xapi/xapi.module.ts b/src/core/features/xapi/xapi.module.ts index 23f76b909..6ee1d9f8a 100644 --- a/src/core/features/xapi/xapi.module.ts +++ b/src/core/features/xapi/xapi.module.ts @@ -12,10 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { NgModule } from '@angular/core'; +import { NgModule, Type } from '@angular/core'; import { CORE_SITE_SCHEMAS } from '@services/sites'; import { SITE_SCHEMA } from './services/database/xapi'; +import { CoreXAPIOfflineProvider } from './services/offline'; +import { CoreXAPIProvider } from './services/xapi'; + +export const CORE_XAPI_SERVICES: Type[] = [ + CoreXAPIProvider, + CoreXAPIOfflineProvider, +]; @NgModule({ imports: [],