From 78626a9925bf3f1f24b7a8eab882898818a8dbf4 Mon Sep 17 00:00:00 2001 From: Ashutosh Chauhan Date: Mon, 28 Jun 2021 02:18:31 +0530 Subject: [PATCH] Remove angularjs from about page. (#13073) * wip * Add other files * Lint fix * done * Fix specs * nits * nits * nits * nit * nit * nit * nits * nit * nit * nit * nit * e2e fix * nit * change detection * nit * nit * Add angular version * nit * nit * nit * e2e fix * nit * nit * nit * Revert "nit" This reverts commit ebb7b64c4dbb8cf600a881e959671dc8c7ec63a6. * e2e fixed * nit * remove commented code * nit * more properties added mock angular object * nit * nir * fix * nit * type errors * nit Co-authored-by: Srijan Reddy --- .github/CODEOWNERS | 3 +- .../base-content.component.spec.ts | 5 ++ .../base-components/base-content.component.ts | 15 +++- .../i18n-language-selector.component.ts | 9 +- .../base-components/oppia-root.directive.ts | 24 +---- ...int-and-solution-buttons.component.spec.ts | 22 +++-- .../ck-editor-4-widgets.initializer.ts | 3 + .../oppia-angular-root.component.html | 3 + .../oppia-angular-root.component.spec.ts | 13 ++- .../oppia-angular-root.component.ts | 87 ++++++++++++++++++- .../components/shared-component.module.ts | 4 +- core/templates/pages/Base.ts | 80 ++--------------- .../about-page/about-page-root.component.html | 15 ++++ .../about-page/about-page-root.component.ts | 25 ++++++ .../pages/about-page/about-page.import.ts | 30 ++++--- .../pages/about-page/about-page.mainpage.html | 20 +---- .../pages/about-page/about-page.module.ts | 36 ++------ core/templates/pages/footer_js_libs.html | 10 +-- core/templates/pages/header_js_libs.html | 4 +- core/templates/pages/mock-ajs.ts | 54 ++++++++++++ .../preferences-page.component.ts | 5 +- .../services/i18n-language-code.service.ts | 3 +- core/tests/protractor.conf.js | 4 - scripts/run_mypy_checks.py | 4 + webpack.common.config.ts | 56 ++++++++++++ webpack.dev.config.ts | 3 +- webpack.prod.config.ts | 3 +- 27 files changed, 348 insertions(+), 192 deletions(-) create mode 100644 core/templates/components/oppia-angular-root.component.html create mode 100644 core/templates/pages/about-page/about-page-root.component.html create mode 100644 core/templates/pages/about-page/about-page-root.component.ts create mode 100644 core/templates/pages/mock-ajs.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 75d263e470e3..73683e21b3b5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -54,8 +54,9 @@ /core/templates/services/loader.service*.ts @srijanreddy98 @darksun27 /core/templates/components/code-mirror/ @srijanreddy98 @darksun27 /core/templates/components/material.module.ts @srijanreddy98 @darksun27 -/core/templates/components/oppia-angular-root.component.ts @srijanreddy98 @darksun27 +/core/templates/components/oppia-angular-root.component.* @srijanreddy98 @darksun27 /core/templates/pages/missing-translation-custom-handler*.ts @srijanreddy98 @darksun27 +/core/templates/pages/mock-ajs.ts @srijanreddy98 @darksun27 /core/templates/pages/translate-cache.factory*.ts @srijanreddy98 @darksun27 /core/templates/pages/translate-custom-parser*.ts @srijanreddy98 @darksun27 /core/templates/pages/translate-loader.factory*.ts @srijanreddy98 @darksun27 diff --git a/core/templates/base-components/base-content.component.spec.ts b/core/templates/base-components/base-content.component.spec.ts index 48e87ab0279c..bbc5523e1fb2 100644 --- a/core/templates/base-components/base-content.component.spec.ts +++ b/core/templates/base-components/base-content.component.spec.ts @@ -62,6 +62,11 @@ describe('Base Content Component', () => { pathname: pathname, search: search, hash: hash + }, + document: { + addEventListener(event: string, callback: () => void) { + callback(); + } } }; } diff --git a/core/templates/base-components/base-content.component.ts b/core/templates/base-components/base-content.component.ts index 4a0fc5e7b630..4f3dbdd88548 100644 --- a/core/templates/base-components/base-content.component.ts +++ b/core/templates/base-components/base-content.component.ts @@ -16,7 +16,7 @@ * @fileoverview Component for the Base Transclusion Component. */ -import { Component } from '@angular/core'; +import { Component, Directive } from '@angular/core'; import { downgradeComponent } from '@angular/upgrade/static'; import { AppConstants } from 'app.constants'; import { BottomNavbarStatusService } from 'services/bottom-navbar-status.service'; @@ -66,6 +66,11 @@ export class BaseContentComponent { (message: string) => this.loadingMessage = message ); this.keyboardShortcutService.bindNavigationShortcuts(); + + // TODO(sll): Use 'touchstart' for mobile. + this.windowRef.nativeWindow.document.addEventListener('click', () => { + this.sidebarStatusService.onDocumentClick(); + }); } getHeaderText(): string { @@ -114,6 +119,14 @@ export class BaseContentComponent { } } +/** + * This directive is used as selector for navbar breadcrumb transclusion. + */ +@Directive({ + selector: 'navbar-breadcrumb' +}) +export class BaseContentNavBarBreadCrumbDirective {} + angular.module('oppia').directive('oppiaBaseContent', downgradeComponent({ component: BaseContentComponent diff --git a/core/templates/base-components/i18n-language-selector.component.ts b/core/templates/base-components/i18n-language-selector.component.ts index be2770ffb845..013408f4c9bb 100755 --- a/core/templates/base-components/i18n-language-selector.component.ts +++ b/core/templates/base-components/i18n-language-selector.component.ts @@ -16,7 +16,7 @@ * @fileoverview Component for changing site language. */ -import { Component } from '@angular/core'; +import { ChangeDetectorRef, Component } from '@angular/core'; import { downgradeComponent } from '@angular/upgrade/static'; import { AppConstants } from 'app.constants'; import { I18nLanguageCodeService } from 'services/i18n-language-code.service'; @@ -38,6 +38,7 @@ export class I18nLanguageSelectorComponent { supportedSiteLanguages: readonly SiteLanguage[]; constructor( + private changeDetectorRef: ChangeDetectorRef, private i18nLanguageCodeService: I18nLanguageCodeService, private userService: UserService, private userBackendApiService: UserBackendApiService @@ -47,6 +48,12 @@ export class I18nLanguageSelectorComponent { this.currentLanguageCode = this.i18nLanguageCodeService .getCurrentI18nLanguageCode(); this.supportedSiteLanguages = AppConstants.SUPPORTED_SITE_LANGUAGES; + this.i18nLanguageCodeService.onI18nLanguageCodeChange.subscribe((code) => { + if (this.currentLanguageCode !== code) { + this.currentLanguageCode = code; + this.changeDetectorRef.detectChanges(); + } + }); } changeLanguage(): void { diff --git a/core/templates/base-components/oppia-root.directive.ts b/core/templates/base-components/oppia-root.directive.ts index 8e9162105f25..94584e72359d 100644 --- a/core/templates/base-components/oppia-root.directive.ts +++ b/core/templates/base-components/oppia-root.directive.ts @@ -115,28 +115,10 @@ angular.module('oppia').directive('oppiaRoot', [ ); } - // TODO(#12793): Remove the use of ( - // OppiaAngularRootComponent.ajsTranslate). - OppiaAngularRootComponent.ajsTranslate = $translate; - const translateService = ( - OppiaAngularRootComponent.translateService); - const translateCacheService = ( - OppiaAngularRootComponent.translateCacheService); - const i18nLanguageCodeService = ( - OppiaAngularRootComponent.i18nLanguageCodeService); - - i18nLanguageCodeService.onI18nLanguageCodeChange.subscribe( + OppiaAngularRootComponent.translateService.onLangChange.subscribe( (code) => { - translateService.use(code); - $translate.use(code); - } - ); - translateCacheService.init(); - - const cachedLanguage = translateCacheService.getCachedLanguage(); - if (cachedLanguage) { - i18nLanguageCodeService.setI18nLanguageCode(cachedLanguage); - } + $translate.use(code.lang); + }); // The next line allows the transcluded content to start executing. $scope.initialized = true; diff --git a/core/templates/components/button-directives/hint-and-solution-buttons.component.spec.ts b/core/templates/components/button-directives/hint-and-solution-buttons.component.spec.ts index 03873dca0249..5a2078c27fca 100644 --- a/core/templates/components/button-directives/hint-and-solution-buttons.component.spec.ts +++ b/core/templates/components/button-directives/hint-and-solution-buttons.component.spec.ts @@ -19,7 +19,8 @@ import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { InteractionObjectFactory } from 'domain/exploration/InteractionObjectFactory'; import { RecordedVoiceovers } from 'domain/exploration/recorded-voiceovers.model'; import { WrittenTranslationsObjectFactory } from 'domain/exploration/WrittenTranslationsObjectFactory'; -import { StateCard, StateCardObjectFactory } from 'domain/state_card/StateCardObjectFactory'; +import { StateCard } from 'domain/state_card/state-card.model'; +import { AudioTranslationLanguageService } from 'pages/exploration-player-page/services/audio-translation-language.service'; import { ExplorationPlayerStateService } from 'pages/exploration-player-page/services/exploration-player-state.service'; import { HintAndSolutionModalService } from 'pages/exploration-player-page/services/hint-and-solution-modal.service'; import { HintsAndSolutionManagerService } from 'pages/exploration-player-page/services/hints-and-solution-manager.service'; @@ -37,7 +38,6 @@ describe('HintAndSolutionButtonsComponent', () => { let fixture: ComponentFixture; let playerPositionService: PlayerPositionService; let hintsAndSolutionManagerService: HintsAndSolutionManagerService; - let stateCardObjectFactory: StateCardObjectFactory; let writtenTranslationsObjectFactory: WrittenTranslationsObjectFactory; let interactionObjectFactory: InteractionObjectFactory; let playerTranscriptService: PlayerTranscriptService; @@ -45,6 +45,7 @@ describe('HintAndSolutionButtonsComponent', () => { let explorationPlayerStateService: ExplorationPlayerStateService; let statsReportingService: StatsReportingService; let newCard: StateCard; + let audioTranslationLanguageService: AudioTranslationLanguageService; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ @@ -59,7 +60,6 @@ describe('HintAndSolutionButtonsComponent', () => { playerPositionService = TestBed.inject(PlayerPositionService); hintsAndSolutionManagerService = TestBed .inject(HintsAndSolutionManagerService); - stateCardObjectFactory = TestBed.inject(StateCardObjectFactory); writtenTranslationsObjectFactory = TestBed.inject( WrittenTranslationsObjectFactory); interactionObjectFactory = TestBed.inject(InteractionObjectFactory); @@ -68,6 +68,8 @@ describe('HintAndSolutionButtonsComponent', () => { explorationPlayerStateService = TestBed.inject( ExplorationPlayerStateService); statsReportingService = TestBed.inject(StatsReportingService); + audioTranslationLanguageService = ( + TestBed.inject(AudioTranslationLanguageService)); spyOn(playerPositionService, 'onNewCardOpened').and.returnValue( new EventEmitter()); @@ -79,7 +81,7 @@ describe('HintAndSolutionButtonsComponent', () => { .and.returnValue(new EventEmitter()); // A StateCard which supports hints. - newCard = stateCardObjectFactory.createNewCard( + newCard = StateCard.createNewCard( 'State 2', '

Content

', '', interactionObjectFactory.createFromBackendDict({ id: 'TextInput', @@ -133,7 +135,7 @@ describe('HintAndSolutionButtonsComponent', () => { }), RecordedVoiceovers.createEmpty(), writtenTranslationsObjectFactory.createEmpty(), - 'content'); + 'content', audioTranslationLanguageService); }); it('should subscribe to events on initialization', () => { @@ -157,10 +159,11 @@ describe('HintAndSolutionButtonsComponent', () => { it('should reset hints and solutions when new' + ' card is opened', fakeAsync(() => { - let oldCard: StateCard = stateCardObjectFactory.createNewCard( + let oldCard: StateCard = StateCard.createNewCard( 'State 1', '

Content

', '', null, RecordedVoiceovers.createEmpty(), - writtenTranslationsObjectFactory.createEmpty(), 'content'); + writtenTranslationsObjectFactory.createEmpty(), 'content', + audioTranslationLanguageService); spyOn(hintsAndSolutionManagerService, 'getNumHints').and.returnValue(1); component.displayedCard = oldCard; @@ -236,7 +239,7 @@ describe('HintAndSolutionButtonsComponent', () => { expect(component.isHintButtonVisible(0)).toBe(false); // StateCard with EndExploration interaction, which does not supports hints. - component.displayedCard = stateCardObjectFactory.createNewCard( + component.displayedCard = StateCard.createNewCard( 'State 1', '

Content

', '', interactionObjectFactory.createFromBackendDict({ id: 'EndExploration', @@ -247,7 +250,8 @@ describe('HintAndSolutionButtonsComponent', () => { hints: [], solution: null, }), RecordedVoiceovers.createEmpty(), - writtenTranslationsObjectFactory.createEmpty(), 'content'); + writtenTranslationsObjectFactory.createEmpty(), 'content', + audioTranslationLanguageService); expect(component.isHintButtonVisible(0)).toBe(false); diff --git a/core/templates/components/ck-editor-helpers/ck-editor-4-widgets.initializer.ts b/core/templates/components/ck-editor-helpers/ck-editor-4-widgets.initializer.ts index c812fdb4f650..faef3eb8889a 100644 --- a/core/templates/components/ck-editor-helpers/ck-editor-4-widgets.initializer.ts +++ b/core/templates/components/ck-editor-helpers/ck-editor-4-widgets.initializer.ts @@ -54,6 +54,9 @@ export class CkEditorInitializerService { rteHelperService: RteHelperService, htmlEscaperService: HtmlEscaperService, contextService: ContextService, ngZone: NgZone): void { + if (rteHelperService === undefined) { + return; + } ngZone.runOutsideAngular(() => { var _RICH_TEXT_COMPONENTS = rteHelperService.getRichTextComponents(); _RICH_TEXT_COMPONENTS.forEach(function(componentDefn) { diff --git a/core/templates/components/oppia-angular-root.component.html b/core/templates/components/oppia-angular-root.component.html new file mode 100644 index 000000000000..07f6041c5020 --- /dev/null +++ b/core/templates/components/oppia-angular-root.component.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/core/templates/components/oppia-angular-root.component.spec.ts b/core/templates/components/oppia-angular-root.component.spec.ts index cb960f3a29c4..d50b8afed968 100644 --- a/core/templates/components/oppia-angular-root.component.spec.ts +++ b/core/templates/components/oppia-angular-root.component.spec.ts @@ -25,6 +25,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { AngularFireAuth } from '@angular/fire/auth'; import { OppiaAngularRootComponent } from './oppia-angular-root.component'; +import { I18nLanguageCodeService } from 'services/i18n-language-code.service'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { RichTextComponentsModule } from 'rich_text_components/rich-text-components.module'; import { CkEditorInitializerService } from './ck-editor-helpers/ck-editor-4-widgets.initializer'; @@ -46,11 +47,18 @@ describe('OppiaAngularRootComponent', function() { }, { provide: TranslateCacheService, - useValue: null + useValue: { + init: () => {}, + getCachedLanguage: () => { + return 'en'; + } + } }, { provide: TranslateService, - useValue: null + useValue: { + use: () => {} + } } ], schemas: [NO_ERRORS_SCHEMA] @@ -66,6 +74,7 @@ describe('OppiaAngularRootComponent', function() { spyOn(CkEditorInitializerService, 'ckEditorInitializer').and.callFake( () => {}); component.ngAfterViewInit(); + TestBed.inject(I18nLanguageCodeService).setI18nLanguageCode('en'); expect(emitSpy).toHaveBeenCalled(); }); diff --git a/core/templates/components/oppia-angular-root.component.ts b/core/templates/components/oppia-angular-root.component.ts index abf53ac3dff7..f9bd81a537d6 100644 --- a/core/templates/components/oppia-angular-root.component.ts +++ b/core/templates/components/oppia-angular-root.component.ts @@ -61,7 +61,7 @@ * loading */ -import { Component, Output, AfterViewInit, EventEmitter, Injector, NgZone } from '@angular/core'; +import { Component, Output, AfterViewInit, EventEmitter, Injector, NgZone, ChangeDetectorRef } from '@angular/core'; import { createCustomElement } from '@angular/elements'; import { TranslateService } from '@ngx-translate/core'; import { TranslateCacheService } from 'ngx-translate-cache'; @@ -91,6 +91,11 @@ import { NoninteractiveTabs } from 'rich_text_components/Tabs/directives/oppia-n import { NoninteractiveVideo } from 'rich_text_components/Video/directives/oppia-noninteractive-video.component'; import { CkEditorInitializerService } from './ck-editor-helpers/ck-editor-4-widgets.initializer'; import { HtmlEscaperService } from 'services/html-escaper.service'; +import { MetaTagCustomizationService } from 'services/contextual/meta-tag-customization.service'; +import { AppConstants } from 'app.constants'; +import { UrlInterpolationService } from 'domain/utilities/url-interpolation.service'; +import { UrlService } from 'services/contextual/url.service'; +import { DocumentAttributeCustomizationService } from 'services/contextual/document-attribute-customization.service'; const componentMap = { Collapsible: { @@ -120,12 +125,13 @@ const componentMap = { }; @Component({ selector: 'oppia-angular-root', - template: '' + templateUrl: './oppia-angular-root.component.html' }) export class OppiaAngularRootComponent implements AfterViewInit { @Output() public initialized: EventEmitter = new EventEmitter(); - static ajsTranslate; + direction: string = 'ltr'; + static classroomBackendApiService: ClassroomBackendApiService; static contextService: ContextService; static i18nLanguageCodeService: I18nLanguageCodeService; @@ -142,9 +148,13 @@ export class OppiaAngularRootComponent implements AfterViewInit { static injector: Injector; constructor( + private changeDetectorRef: ChangeDetectorRef, private classroomBackendApiService: ClassroomBackendApiService, + private documentAttributeCustomizationService: + DocumentAttributeCustomizationService, private i18nLanguageCodeService: I18nLanguageCodeService, private htmlEscaperService: HtmlEscaperService, + private metaTagCustomizationService: MetaTagCustomizationService, private ngZone: NgZone, private pageTitleService: PageTitleService, private profilePageBackendApiService: ProfilePageBackendApiService, @@ -153,6 +163,8 @@ export class OppiaAngularRootComponent implements AfterViewInit { private storyViewerBackendApiService: StoryViewerBackendApiService, private translateService: TranslateService, private translateCacheService: TranslateCacheService, + private urlInterpolationService: UrlInterpolationService, + private urlService: UrlService, private injector: Injector ) { for (const rteKey of Object.keys(ServicesConstants.RTE_COMPONENT_SPECS)) { @@ -195,7 +207,76 @@ export class OppiaAngularRootComponent implements AfterViewInit { this.translateCacheService); OppiaAngularRootComponent.injector = this.injector; + // Initialize dynamic meta tags. + this.metaTagCustomizationService.addMetaTags([ + { + propertyType: 'name', + propertyValue: 'application-name', + content: AppConstants.SITE_NAME + }, + { + propertyType: 'name', + propertyValue: 'msapplication-square310x310logo', + content: this.getAssetUrl( + '/assets/images/logo/msapplication-large.png') + }, + { + propertyType: 'name', + propertyValue: 'msapplication-wide310x150logo', + content: this.getAssetUrl( + '/assets/images/logo/msapplication-wide.png') + }, + { + propertyType: 'name', + propertyValue: 'msapplication-square150x150logo', + content: this.getAssetUrl( + '/assets/images/logo/msapplication-square.png') + }, + { + propertyType: 'name', + propertyValue: 'msapplication-square70x70logo', + content: this.getAssetUrl( + '/assets/images/logo/msapplication-tiny.png') + }, + { + propertyType: 'property', + propertyValue: 'og:url', + content: this.urlService.getCurrentLocation().href + }, + { + propertyType: 'property', + propertyValue: 'og:image', + content: this.urlInterpolationService.getStaticImageUrl( + '/logo/288x288_logo_mint.webp') + } + ]); + + // Initialize translations. + this.i18nLanguageCodeService.onI18nLanguageCodeChange.subscribe( + (code) => { + this.translateService.use(code); + for (var i = 0; i < AppConstants.SUPPORTED_SITE_LANGUAGES.length; i++) { + if (AppConstants.SUPPORTED_SITE_LANGUAGES[i].id === code) { + this.direction = AppConstants.SUPPORTED_SITE_LANGUAGES[i].direction; + break; + } + } + this.documentAttributeCustomizationService.addAttribute('lang', code); + this.changeDetectorRef.detectChanges(); + } + ); + this.translateCacheService.init(); + + const cachedLanguage = this.translateCacheService.getCachedLanguage(); + if (cachedLanguage) { + this.i18nLanguageCodeService.setI18nLanguageCode(cachedLanguage); + } + // This emit triggers ajs to start its app. this.initialized.emit(); } + + getAssetUrl(path: string): string { + return this.urlInterpolationService.getFullStaticAssetUrl(path); + } } diff --git a/core/templates/components/shared-component.module.ts b/core/templates/components/shared-component.module.ts index b1aa290d6fe9..301d12e94e5c 100644 --- a/core/templates/components/shared-component.module.ts +++ b/core/templates/components/shared-component.module.ts @@ -84,8 +84,8 @@ import { EditThumbnailModalComponent } from './forms/custom-forms-directives/edi import { TopNavigationBarComponent } from './common-layout-directives/navigation-bars/top-navigation-bar.component'; import { CorrectnessFooterComponent } from 'pages/exploration-player-page/layout-directives/correctness-footer.component'; import { ContinueButtonComponent } from 'pages/exploration-player-page/learner-experience/continue-button.component'; +import { BaseContentComponent, BaseContentNavBarBreadCrumbDirective } from '../base-components/base-content.component'; import { QuestionDifficultySelectorComponent } from './question-difficulty-selector/question-difficulty-selector.component'; -import { BaseContentComponent } from '../base-components/base-content.component'; import { PreviewThumbnailComponent } from 'pages/topic-editor-page/modal-templates/preview-thumbnail.component'; import { InputResponsePairComponent } from 'pages/exploration-player-page/learner-experience/input-response-pair.component'; import { I18nLanguageSelectorComponent } from '../base-components/i18n-language-selector.component'; @@ -235,6 +235,7 @@ const toastrConfig = { AttributionGuideComponent, BackgroundBannerComponent, BaseContentComponent, + BaseContentNavBarBreadCrumbDirective, CorrectnessFooterComponent, ContinueButtonComponent, CreateNewSkillModalComponent, @@ -372,6 +373,7 @@ const toastrConfig = { AlertMessageComponent, BackgroundBannerComponent, BaseContentComponent, + BaseContentNavBarBreadCrumbDirective, CorrectnessFooterComponent, ContinueButtonComponent, CreateNewSkillModalComponent, diff --git a/core/templates/pages/Base.ts b/core/templates/pages/Base.ts index 1037444aae01..db70fbbadb13 100644 --- a/core/templates/pages/Base.ts +++ b/core/templates/pages/Base.ts @@ -28,91 +28,25 @@ require('app.constants.ajs.ts'); */ angular.module('oppia').controller('Base', [ - '$document', '$rootScope', '$scope', 'AlertsService', 'BackgroundMaskService', + '$rootScope', '$scope', 'CsrfTokenService', 'DocumentAttributeCustomizationService', 'LoaderService', - 'MetaTagCustomizationService', 'SidebarStatusService', - 'UrlInterpolationService', 'UrlService', 'DEV_MODE', - 'SITE_FEEDBACK_FORM_URL', 'SITE_NAME', 'SUPPORTED_SITE_LANGUAGES', + 'UrlInterpolationService', 'SUPPORTED_SITE_LANGUAGES', function( - $document, $rootScope, $scope, AlertsService, BackgroundMaskService, + $rootScope, $scope, CsrfTokenService, DocumentAttributeCustomizationService, LoaderService, - MetaTagCustomizationService, SidebarStatusService, - UrlInterpolationService, UrlService, DEV_MODE, - SITE_FEEDBACK_FORM_URL, SITE_NAME, SUPPORTED_SITE_LANGUAGES) { + UrlInterpolationService, SUPPORTED_SITE_LANGUAGES) { var ctrl = this; $scope.getAssetUrl = function(path) { return UrlInterpolationService.getFullStaticAssetUrl(path); }; - $scope.isBackgroundMaskActive = () => BackgroundMaskService.isMaskActive(); - $scope.isSidebarShown = () => SidebarStatusService.isSidebarShown(); - $scope.closeSidebarOnSwipe = () => SidebarStatusService.closeSidebar(); - - $scope.skipToMainContent = function() { - var mainContentElement = document.getElementById( - 'oppia-main-content'); - - if (!mainContentElement) { - throw new Error('Variable mainContentElement is undefined.'); - } - mainContentElement.tabIndex = -1; - mainContentElement.scrollIntoView(); - mainContentElement.focus(); - }; ctrl.$onInit = function() { - $scope.siteName = SITE_NAME; $scope.currentLang = 'en'; $scope.direction = 'ltr'; - $scope.pageUrl = UrlService.getCurrentLocation().href; - $scope.iframed = UrlService.isIframed(); - $scope.AlertsService = AlertsService; - $rootScope.DEV_MODE = DEV_MODE; // If this is nonempty, the whole page goes into 'Loading...' mode. LoaderService.hideLoadingScreen(); CsrfTokenService.initializeToken(); - MetaTagCustomizationService.addMetaTags([ - { - propertyType: 'name', - propertyValue: 'application-name', - content: SITE_NAME - }, - { - propertyType: 'name', - propertyValue: 'msapplication-square310x310logo', - content: $scope.getAssetUrl( - '/assets/images/logo/msapplication-large.png') - }, - { - propertyType: 'name', - propertyValue: 'msapplication-wide310x150logo', - content: $scope.getAssetUrl( - '/assets/images/logo/msapplication-wide.png') - }, - { - propertyType: 'name', - propertyValue: 'msapplication-square150x150logo', - content: $scope.getAssetUrl( - '/assets/images/logo/msapplication-square.png') - }, - { - propertyType: 'name', - propertyValue: 'msapplication-square70x70logo', - content: $scope.getAssetUrl( - '/assets/images/logo/msapplication-tiny.png') - }, - { - propertyType: 'property', - propertyValue: 'og:url', - content: $scope.pageUrl - }, - { - propertyType: 'property', - propertyValue: 'og:image', - content: UrlInterpolationService.getStaticImageUrl( - '/logo/288x288_logo_mint.webp') - } - ]); // Listener function to catch the change in language preference. $rootScope.$on('$translateChangeSuccess', function(evt, response) { @@ -124,13 +58,9 @@ angular.module('oppia').controller('Base', [ } } }); - $scope.siteFeedbackFormUrl = SITE_FEEDBACK_FORM_URL; + DocumentAttributeCustomizationService.addAttribute( 'lang', $scope.currentLang); - // TODO(sll): Use 'touchstart' for mobile. - $document.on('click', function() { - SidebarStatusService.onDocumentClick(); - }); }; } ]); diff --git a/core/templates/pages/about-page/about-page-root.component.html b/core/templates/pages/about-page/about-page-root.component.html new file mode 100644 index 000000000000..16b78a115e16 --- /dev/null +++ b/core/templates/pages/about-page/about-page-root.component.html @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/core/templates/pages/about-page/about-page-root.component.ts b/core/templates/pages/about-page/about-page-root.component.ts new file mode 100644 index 000000000000..0bff1150ef62 --- /dev/null +++ b/core/templates/pages/about-page/about-page-root.component.ts @@ -0,0 +1,25 @@ +// Copyright 2020 The Oppia Authors. All Rights Reserved. +// +// 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. + +/** + * @fileoverview About-page-root component. + */ + +import { Component } from '@angular/core'; + +@Component({ + selector: 'oppia-about-page-root', + templateUrl: './about-page-root.component.html' +}) +export class AboutPageRootComponent {} diff --git a/core/templates/pages/about-page/about-page.import.ts b/core/templates/pages/about-page/about-page.import.ts index 81408d1e57cf..a03fb9d2a016 100644 --- a/core/templates/pages/about-page/about-page.import.ts +++ b/core/templates/pages/about-page/about-page.import.ts @@ -19,18 +19,24 @@ import 'core-js/es7/reflect'; import 'zone.js'; -angular.module('oppia', [ - require('angular-cookies'), 'headroom', 'ngAnimate', - 'ngMaterial', 'ngSanitize', 'ngTouch', 'pascalprecht.translate', - 'toastr', 'ui.bootstrap' -]); +// TODO(#13080): Remove the mock-ajs.ts file after the migration is complete. +import 'pages/mock-ajs'; +import 'Polyfills.ts'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { AboutPageModule } from './about-page.module'; +import { AppConstants } from 'app.constants'; +import { enableProdMode } from '@angular/core'; -require('Polyfills.ts'); +if (!AppConstants.DEV_MODE) { + enableProdMode(); +} -// The module needs to be loaded directly after jquery since it defines the -// main module the elements are attached to. -require('pages/about-page/about-page.module.ts'); -require('App.ts'); -require('base-components/oppia-root.directive.ts'); +platformBrowserDynamic().bootstrapModule(AboutPageModule).catch( + // eslint-disable-next-line no-console + (err) => console.error(err) +); -require('base-components/base-content.component.ts'); +// This prevents angular pages to cause side effects to hybrid pages. +// TODO(#13080): Remove window.name statement from import.ts files +// after migration is complete. +window.name = ''; diff --git a/core/templates/pages/about-page/about-page.mainpage.html b/core/templates/pages/about-page/about-page.mainpage.html index c285c6abd290..3cda1318fa35 100644 --- a/core/templates/pages/about-page/about-page.mainpage.html +++ b/core/templates/pages/about-page/about-page.mainpage.html @@ -1,26 +1,10 @@ - + @load('base-components/header.template.html', {"title": "About | Oppia"}) - -
- - - - - - - - -
-
+ @load('pages/footer_js_libs.html') diff --git a/core/templates/pages/about-page/about-page.module.ts b/core/templates/pages/about-page/about-page.module.ts index 9a37c1d6f159..40286c21be09 100644 --- a/core/templates/pages/about-page/about-page.module.ts +++ b/core/templates/pages/about-page/about-page.module.ts @@ -16,9 +16,8 @@ * @fileoverview Module for the about page. */ -import { APP_INITIALIZER, NgModule, StaticProvider } from '@angular/core'; +import { APP_INITIALIZER, NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; -import { downgradeComponent } from '@angular/upgrade/static'; import { HttpClientModule } from '@angular/common/http'; import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { AboutPageComponent } from './about-page.component'; @@ -28,6 +27,7 @@ import { OppiaAngularRootComponent } from 'components/oppia-angular-root.component'; import { platformFeatureInitFactory, PlatformFeatureService } from 'services/platform-feature.service'; +import { AboutPageRootComponent } from './about-page-root.component'; @NgModule({ imports: [ @@ -37,10 +37,12 @@ import { platformFeatureInitFactory, PlatformFeatureService } from ], declarations: [ AboutPageComponent, + AboutPageRootComponent, OppiaAngularRootComponent ], entryComponents: [ AboutPageComponent, + AboutPageRootComponent, OppiaAngularRootComponent ], providers: [ @@ -55,31 +57,7 @@ import { platformFeatureInitFactory, PlatformFeatureService } from deps: [PlatformFeatureService], multi: true } - ] + ], + bootstrap: [AboutPageRootComponent] }) -class AboutPageModule { - // Empty placeholder method to satisfy the `Compiler`. - ngDoBootstrap() {} -} - -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import { downgradeModule } from '@angular/upgrade/static'; - -const bootstrapFnAsync = async(extraProviders: StaticProvider[]) => { - const platformRef = platformBrowserDynamic(extraProviders); - return platformRef.bootstrapModule(AboutPageModule); -}; - -const downgradedModule = downgradeModule(bootstrapFnAsync); - -declare var angular: ng.IAngularStatic; - -angular.module('oppia').requires.push(downgradedModule); - -angular.module('oppia').directive( - // This directive is the downgraded version of the Angular component to - // bootstrap the Angular 8. - 'oppiaAngularRoot', - downgradeComponent({ - component: OppiaAngularRootComponent - }) as angular.IDirectiveFactory); +export class AboutPageModule {} diff --git a/core/templates/pages/footer_js_libs.html b/core/templates/pages/footer_js_libs.html index 4082dac2d1fc..251ca4e9e905 100644 --- a/core/templates/pages/footer_js_libs.html +++ b/core/templates/pages/footer_js_libs.html @@ -3,15 +3,11 @@ <% for (var chunk in htmlWebpackPlugin.files.js) { %> - <% if (webpackConfig.mode == 'production') { %> - - <% } else { %> - - <% } %> + <% } %> -<% if (webpackConfig.mode == 'production') { %> +<% if (htmlWebpackPlugin.options.hybrid && webpackConfig.mode == 'production') { %> -<% } else { %> +<% } else if (htmlWebpackPlugin.options.hybrid) { %> <% } %> diff --git a/core/templates/pages/header_js_libs.html b/core/templates/pages/header_js_libs.html index b00ea9155230..a4e0d8a606e0 100644 --- a/core/templates/pages/header_js_libs.html +++ b/core/templates/pages/header_js_libs.html @@ -3,8 +3,8 @@ -<% if (webpackConfig.mode == 'production') { %> +<% if (htmlWebpackPlugin.options.hybrid && webpackConfig.mode == 'production') { %> -<% } else { %> +<% } else if (htmlWebpackPlugin.options.hybrid) { %> <% } %> diff --git a/core/templates/pages/mock-ajs.ts b/core/templates/pages/mock-ajs.ts new file mode 100644 index 000000000000..fe9801b54f09 --- /dev/null +++ b/core/templates/pages/mock-ajs.ts @@ -0,0 +1,54 @@ +// Copyright 2021 The Oppia Authors. All Rights Reserved. +// +// 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. + +/** + * @fileoverview Mock angular object for pages that don't use AngularJS. + */ + +/** + * We are at a stage where we can have some pages in Angular. But we share + * component in between pages. So we can't remove the code that downgrades + * components and services. This code is found in most Angular components and + * services (towards the end of the file). In order to not have to create a + * separate file for each service and component just for the sake of downgrading + * , we have created this mock AngularJS object that will be used in the pages + * that don't use AngularJS. + */ + +// TODO(#13080): Remove the mock-ajs.ts file after the migration is complete. + +import { VERSION } from '@angular/core'; + +let mockAngular = { + $$minErr: () => mockAngular, + component: () => mockAngular, + config: () => mockAngular, + constant: () => mockAngular, + controller: () => mockAngular, + directive: () => mockAngular, + factory: () => mockAngular, + filter: () => mockAngular, + info: () => mockAngular, + module: () => mockAngular, + provider: () => mockAngular, + requires: () => [], + run: () => mockAngular, + service: () => mockAngular, + value: () => mockAngular, + version: VERSION +}; + +// This throws "Property 'angular' does not exist on type 'Window & typeof +// globalThis'." when the `as unknown as ...` is not used. +(window as unknown as {angular: typeof mockAngular}).angular = mockAngular; diff --git a/core/templates/pages/preferences-page/preferences-page.component.ts b/core/templates/pages/preferences-page/preferences-page.component.ts index 0acc7074bd2e..1e5c1d87aa5b 100644 --- a/core/templates/pages/preferences-page/preferences-page.component.ts +++ b/core/templates/pages/preferences-page/preferences-page.component.ts @@ -46,14 +46,14 @@ angular.module('oppia').component('preferencesPage', { }, template: require('./preferences-page.component.html'), controller: [ - '$http', '$q', '$rootScope', '$timeout', '$translate', '$uibModal', + '$http', '$q', '$rootScope', '$timeout', '$uibModal', '$window', 'AlertsService', 'I18nLanguageCodeService', 'LanguageUtilService', 'LoaderService', 'PreventPageUnloadEventService', 'UrlInterpolationService', 'UserService', 'BULK_EMAIL_SERVICE_SIGNUP_URL', 'DASHBOARD_TYPE_CREATOR', 'DASHBOARD_TYPE_LEARNER', 'ENABLE_ACCOUNT_DELETION', 'ENABLE_ACCOUNT_EXPORT', 'SUPPORTED_AUDIO_LANGUAGES', 'SUPPORTED_SITE_LANGUAGES', function( - $http, $q, $rootScope, $timeout, $translate, $uibModal, + $http, $q, $rootScope, $timeout, $uibModal, $window, AlertsService, I18nLanguageCodeService, LanguageUtilService, LoaderService, PreventPageUnloadEventService, UrlInterpolationService, UserService, BULK_EMAIL_SERVICE_SIGNUP_URL, @@ -109,7 +109,6 @@ angular.module('oppia').component('preferencesPage', { ctrl.savePreferredSiteLanguageCodes = function( preferredSiteLanguageCode) { - $translate.use(preferredSiteLanguageCode); I18nLanguageCodeService.setI18nLanguageCode( preferredSiteLanguageCode); _forceSelect2Refresh(); diff --git a/core/templates/services/i18n-language-code.service.ts b/core/templates/services/i18n-language-code.service.ts index d6aec187b61b..5f1af976a1ab 100644 --- a/core/templates/services/i18n-language-code.service.ts +++ b/core/templates/services/i18n-language-code.service.ts @@ -18,6 +18,7 @@ import { downgradeInjectable } from '@angular/upgrade/static'; import { Injectable, EventEmitter } from '@angular/core'; +import { AppConstants } from 'app.constants'; @Injectable({ providedIn: 'root' @@ -33,7 +34,7 @@ export class I18nLanguageCodeService { * complete. */ static languageCodeChangeEventEmitter = new EventEmitter (); - static languageCode = 'en'; + static languageCode: string = AppConstants.DEFAULT_LANGUAGE_CODE; private _preferredLanguageCodesLoadedEventEmitter = new EventEmitter(); diff --git a/core/tests/protractor.conf.js b/core/tests/protractor.conf.js index eb12ab0a78fa..47981d2187f1 100755 --- a/core/tests/protractor.conf.js +++ b/core/tests/protractor.conf.js @@ -309,10 +309,6 @@ exports.config = { // with relative paths will be prepended with this. baseUrl: 'http://localhost:9001', - // Selector for the element housing the angular app - this defaults to - // body, but is necessary if ng-app is on a descendant of . - rootElement: 'body', - // A callback function called once protractor is ready and available, and // before the specs are executed // You can specify a file containing code to run by setting onPrepare to diff --git a/scripts/run_mypy_checks.py b/scripts/run_mypy_checks.py index 5b131e9a254c..4f2b923536e6 100644 --- a/scripts/run_mypy_checks.py +++ b/scripts/run_mypy_checks.py @@ -264,6 +264,10 @@ 'core/domain/interaction_registry_test.py', 'core/domain/job_validators.py', 'core/domain/job_validators_test.py', + 'core/domain/learner_goals_services.py', + 'core/domain/learner_goals_services_test.py', + 'core/controllers/learner_goals.py', + 'core/controllers/learner_goals_test.py', 'core/domain/learner_playlist_services.py', 'core/domain/learner_playlist_services_test.py', 'core/domain/learner_progress_domain.py', diff --git a/webpack.common.config.ts b/webpack.common.config.ts index 26dfaa596cf0..0f023a9e511d 100644 --- a/webpack.common.config.ts +++ b/webpack.common.config.ts @@ -153,6 +153,11 @@ module.exports = { topic_viewer: commonPrefix + '/pages/topic-viewer-page/topic-viewer-page.import.ts', }, + + /** + * TODO(#13079): Remove the hybrid field from the html webpack plugin options + * once angularjs is removed from corresponding pages. + */ plugins: [ new HtmlWebpackPlugin({ chunks: ['about'], @@ -172,6 +177,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['admin'], filename: 'admin-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'With Oppia, you can access free lessons on ' + @@ -187,6 +193,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['classroom'], filename: 'classroom-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Learn and practice all major math topics, functions, ' + @@ -201,6 +208,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['collection_editor'], filename: 'collection-editor-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Contact the Oppia team, submit feedback, and learn ' + @@ -215,6 +223,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['collection_player'], filename: 'collection-player-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Contact the Oppia team, submit feedback, and learn ' + @@ -229,6 +238,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['console_errors'], filename: 'console_errors.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Contact the Oppia team, submit feedback, and learn ' + @@ -241,6 +251,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['contact'], filename: 'contact-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Contact the Oppia team, submit feedback, and learn ' + @@ -253,6 +264,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['creator_dashboard'], filename: 'creator-dashboard-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/creator-dashboard-page/' + @@ -263,6 +275,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['contributor_dashboard'], filename: 'contributor-dashboard-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/contributor-dashboard-page/' + @@ -273,6 +286,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['delete_account'], filename: 'delete-account-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/delete-account-page/' + @@ -283,6 +297,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['donate'], filename: 'donate-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Donate to The Oppia Foundation to enable more ' + @@ -295,6 +310,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['email_dashboard'], filename: 'email-dashboard-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: ( commonPrefix + @@ -305,6 +321,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['email_dashboard_result'], filename: 'email-dashboard-result.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + @@ -315,6 +332,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['error'], filename: 'error-iframed.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/error-pages/error-iframed.mainpage.html', minify: htmlMinifyConfig, @@ -323,6 +341,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['error'], filename: 'error-page-400.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/error-pages/error-page.mainpage.html', minify: htmlMinifyConfig, @@ -332,6 +351,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['error'], filename: 'error-page-401.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/error-pages/error-page.mainpage.html', minify: htmlMinifyConfig, @@ -341,6 +361,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['error'], filename: 'error-page-404.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/error-pages/error-page.mainpage.html', minify: htmlMinifyConfig, @@ -350,6 +371,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['error'], filename: 'error-page-500.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/error-pages/error-page.mainpage.html', minify: htmlMinifyConfig, @@ -359,6 +381,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['error'], filename: 'error-iframed.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/error-pages/error-iframed.mainpage.html', minify: htmlMinifyConfig, @@ -367,6 +390,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['exploration_editor'], filename: 'exploration-editor-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Help others learn new things. Create lessons through ' + @@ -381,6 +405,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['exploration_player'], filename: 'exploration-player-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/exploration-player-page/' + @@ -391,6 +416,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['get_started'], filename: 'get-started-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Learn how to get started using Oppia.' @@ -403,6 +429,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['landing'], filename: 'topic-landing-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/landing-pages/topic-landing-page/' + @@ -413,6 +440,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['learner_dashboard'], filename: 'learner-dashboard-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/learner-dashboard-page/' + @@ -423,6 +451,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['library'], filename: 'library-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Looking to learn something new? Learn any subject ' + @@ -437,6 +466,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['license'], filename: 'license.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'License terms that Oppia is attributed under.' @@ -449,6 +479,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['login'], filename: 'login-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/login-page/login-page.mainpage.html', minify: htmlMinifyConfig, @@ -457,6 +488,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['logout'], filename: 'logout-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/logout-page/logout-page.mainpage.html', minify: htmlMinifyConfig, @@ -465,6 +497,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['maintenance'], filename: 'maintenance-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/maintenance-page/maintenance-page.mainpage.html', @@ -474,6 +507,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['moderator'], filename: 'moderator-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/moderator-page/moderator-page.mainpage.html', @@ -483,6 +517,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['notifications_dashboard'], filename: 'notifications-dashboard-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Keep track of the lessons you have created, as well ' + @@ -499,6 +534,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['pending_account_deletion'], filename: 'pending-account-deletion-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/pending-account-deletion-page/' + @@ -509,6 +545,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['playbook'], filename: 'playbook.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'The Oppia library is full of user-created lessons ' + @@ -523,6 +560,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['practice_session'], filename: 'practice-session-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/practice-session-page/' + @@ -533,6 +571,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['preferences'], filename: 'preferences-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Change your Oppia profile settings and preferences' @@ -545,6 +584,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['privacy'], filename: 'privacy-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/privacy-page/privacy-page.mainpage.html', minify: htmlMinifyConfig, @@ -553,6 +593,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['profile'], filename: 'profile-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/profile-page/profile-page.mainpage.html', minify: htmlMinifyConfig, @@ -561,6 +602,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['release_coordinator'], filename: 'release-coordinator-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'With Oppia, you can access free lessons on ' + @@ -579,6 +621,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['review_test'], filename: 'review-test-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/review-test-page/review-test-page.mainpage.html', @@ -588,6 +631,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['signup'], filename: 'signup-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Sign up for Oppia and begin exploring a new subject.' @@ -599,6 +643,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['skill_editor'], filename: 'skill-editor-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/skill-editor-page/' + @@ -609,6 +654,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['splash'], filename: 'splash-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'With Oppia, you can access free lessons on math, ' + @@ -623,6 +669,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['stewards'], filename: 'stewards-landing-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + @@ -634,6 +681,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['story_editor'], filename: 'story-editor-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/story-editor-page/' + @@ -644,6 +692,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['story_viewer'], filename: 'story-viewer-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/story-viewer-page/' + @@ -654,6 +703,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['subtopic_viewer'], filename: 'subtopic-viewer-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/subtopic-viewer-page/' + @@ -664,6 +714,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['teach'], filename: 'teach-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'The Oppia library is full of user-created lessons ' + @@ -677,6 +728,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['terms'], filename: 'terms-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Oppia is a 501(c)(3) registered non-profit open-source' + @@ -690,6 +742,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['thanks'], filename: 'thanks-page.mainpage.html', + hybrid: true, meta: { name: defaultMeta.name, description: 'Thank you for donating to The Oppia Foundation!' @@ -701,6 +754,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['topic_editor'], filename: 'topic-editor-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/topic-editor-page/' + @@ -711,6 +765,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['topics_and_skills_dashboard'], filename: 'topics-and-skills-dashboard-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: ( commonPrefix + @@ -723,6 +778,7 @@ module.exports = { new HtmlWebpackPlugin({ chunks: ['topic_viewer'], filename: 'topic-viewer-page.mainpage.html', + hybrid: true, meta: defaultMeta, template: commonPrefix + '/pages/topic-viewer-page/' + diff --git a/webpack.dev.config.ts b/webpack.dev.config.ts index 2a63821a1f88..6669e33fb582 100644 --- a/webpack.dev.config.ts +++ b/webpack.dev.config.ts @@ -24,7 +24,8 @@ module.exports = merge(common, { mode: 'development', output: { filename: '[name].bundle.js', - path: path.resolve(__dirname, 'webpack_bundles') + path: path.resolve(__dirname, 'webpack_bundles'), + publicPath: '/webpack_bundles/' }, devtool: 'eval', watchOptions: { diff --git a/webpack.prod.config.ts b/webpack.prod.config.ts index a33c1c6052b8..3728073c03e1 100644 --- a/webpack.prod.config.ts +++ b/webpack.prod.config.ts @@ -24,6 +24,7 @@ module.exports = merge(common, { mode: 'production', output: { filename: '[name].[contenthash].bundle.js', - path: path.resolve(__dirname, 'backend_prod_files/webpack_bundles') + path: path.resolve(__dirname, 'backend_prod_files/webpack_bundles'), + publicPath: '/build/webpack_bundles/' } });