profile
viewpoint
Srijan Reddy srijanreddy98 @RBCDSAI - IIT Madras Bokaro Steel City/ Bangalore https://srijanreddy.com RL enthusiast and a die hard JS/TS fan.
PullRequestReviewEvent

Pull request review commentoppia/oppia

Migrating directives to angular components

 // limitations under the License.  /**- * @fileoverview Directive for the activities tab in the admin panel when Oppia+ * @fileoverview Component for the activities tab in the admin panel when Oppia  * is in production mode.  */ -require('domain/utilities/url-interpolation.service.ts');+import { Component } from '@angular/core';+import { downgradeComponent } from '@angular/upgrade/static';+++@Component({+  selector: 'admin-prod-mode-activities-tab',+  templateUrl: './admin-prod-mode-activities-tab.component.html',+  styleUrls: []+})++export class AdminProdModeActivitiesTabComponent {

Yes, class names should have a suffix depicting what they are for. When we are in the file we can see the decorator, but when this class is imported in the module (or any other component, inca ase of component lazy loading), the class name should depict what is the class for. This is in mentioned in the angular style guide (https://angular.io/guide/styleguide#symbols-and-file-names)

krishita30j

comment created time in 4 hours

PullRequestReviewEvent

issue commentoppia/oppia

Migrate directives/controllers to Angular components

can I work on continue-button.directive.ts?

Hi @mridul-netizen, it is already being migrated by a contributor at the moment, can try for another file?

bansalnitish

comment created time in a day

Pull request review commentoppia/oppia

Fix part of #10474: Add strict checks to files

 export class Fraction {   }    convertToSimplestForm(): Fraction {-    var gcd = (x: number, y: number) => {+    var gcd = (x: number, y: number): number => {

Can you change this const?

Rijuta-s

comment created time in a day

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

 export const angularServices: [string, unknown][] = [   ['WrittenTranslationObjectFactory', WrittenTranslationObjectFactory],   ['WrittenTranslationsObjectFactory', WrittenTranslationsObjectFactory],   ['baseInteractionValidationService', baseInteractionValidationService],+  ['SuggestionModalForCreatorDashboardBackendApiService',+    SuggestionModalForCreatorDashboardBackendApiService],

Can you place this in the array where it will be lexicographically appropriate?

biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

 require('components/ck-editor-helpers/ck-editor-4-rte.directive.ts'); require('components/ck-editor-helpers/ck-editor-4-widgets.initializer.ts'); -require('domain/utilities/url-interpolation.service.ts');-require('services/suggestion-modal.service.ts'); require(   'pages/creator-dashboard-page/suggestion-modal-for-creator-view/' +-  'suggestion-modal-for-creator-view.controller');+'suggestion-modal-for-creator-dashboard-backend-api.service.ts');+require(+  'pages/creator-dashboard-page/suggestion-modal-for-creator-view/' ++'suggestion-modal-for-creator-view.controller');+require('services/suggestion-modal.service.ts');+require('domain/utilities/url-interpolation.service.ts');  angular.module('oppia').factory('SuggestionModalForCreatorDashboardService', [-  '$http', '$log', '$uibModal', 'UrlInterpolationService',+  '$log', '$uibModal', 'SuggestionModalForCreatorDashboardBackendApiService',

I see changes to this file (additions to the dependencies) but no changes to the spec file of this file. I think you maybe need to change some lines in the spec file. Can you check once?

biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

 import { SubtopicPageObjectFactory } from   'domain/topic/SubtopicPageObjectFactory'; import { SubtopicViewerBackendApiService } from   'domain/subtopic_viewer/subtopic-viewer-backend-api.service';+import { SuggestionModalForCreatorDashboardBackendApiService } from+  'pages/creator-dashboard-page/suggestion-modal-for-creator-view/suggestion-modal-for-creator-dashboard-backend-api.service';

We don't add services here anymore. Can you undo the changes in this file?

biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

 require('components/ck-editor-helpers/ck-editor-4-rte.directive.ts'); require('components/ck-editor-helpers/ck-editor-4-widgets.initializer.ts'); -require('domain/utilities/url-interpolation.service.ts');-require('services/suggestion-modal.service.ts'); require(   'pages/creator-dashboard-page/suggestion-modal-for-creator-view/' +-  'suggestion-modal-for-creator-view.controller');+'suggestion-modal-for-creator-dashboard-backend-api.service.ts');+require(+  'pages/creator-dashboard-page/suggestion-modal-for-creator-view/' ++'suggestion-modal-for-creator-view.controller');

Indent by two spaces.

  'suggestion-modal-for-creator-view.controller');
biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

+// 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 Service to update suggestion in creator view+ */++import { downgradeInjectable } from '@angular/upgrade/static';+import { Injectable } from '@angular/core';+import { HttpClient } from '@angular/common/http';++import { UrlInterpolationService } from 'domain/utilities/url-interpolation.service';+import { Suggestion, SuggestionBackendDict, SuggestionObjectFactory } from 'domain/suggestion/SuggestionObjectFactory';++export interface SuggestionData {+  action: string,+  commitMessage: string,+  reviewMessage: string+}++export interface UrlDetails {+  targetType: string,+  targetId: number,+  suggestionId: number+}++export interface UpdateSuggestionBackendResponse {+  suggestion: SuggestionBackendDict;+}++@Injectable({+  providedIn: 'root'+})+export class SuggestionModalForCreatorDashboardBackendApiService {+  constructor(+    private http: HttpClient,+    private urlInterpolationService: UrlInterpolationService,+    private suggestionObjectFactory: SuggestionObjectFactory) { }++  _updateSuggestion(+      urlDetails: UrlDetails,+      data: SuggestionData): Promise<Suggestion> {+    return new Promise((resolve, reject) => {+      var HANDLE_SUGGESTION_URL_TEMPLATE = (+        '/suggestionactionhandler/<target_type>/<target_id>/<suggestion_id>');+      const url = this.urlInterpolationService.interpolateUrl(+        HANDLE_SUGGESTION_URL_TEMPLATE, {+          target_type: urlDetails.targetType,+          target_id: urlDetails.targetId.toString(),+          suggestion_id: urlDetails.suggestionId.toString()+        }+      );++      this.http.put<UpdateSuggestionBackendResponse>(url, data).toPromise()+        .then(response => {+          resolve(+            this.suggestionObjectFactory+              .createFromBackendDict(response.suggestion));+        }, errorResponse => {+          reject(errorResponse.error.error);+        });+    });+  }+}++angular.module('oppia').factory(+  'SuggestionModalForCreatorDashboardBackendApiService',+  downgradeInjectable(SuggestionModalForCreatorDashboardBackendApiService));+  

Make sure you end your files with a new line. The ⊖ symbol indicates no newline at the end of file.

biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

+// 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 Service to update suggestion in creator view+ */++import { downgradeInjectable } from '@angular/upgrade/static';+import { Injectable } from '@angular/core';+import { HttpClient } from '@angular/common/http';++import { UrlInterpolationService } from 'domain/utilities/url-interpolation.service';+import { Suggestion, SuggestionBackendDict, SuggestionObjectFactory } from 'domain/suggestion/SuggestionObjectFactory';++export interface SuggestionData {+  action: string,+  commitMessage: string,+  reviewMessage: string+}++export interface UrlDetails {+  targetType: string,+  targetId: number,+  suggestionId: number+}++export interface UpdateSuggestionBackendResponse {+  suggestion: SuggestionBackendDict;+}++@Injectable({+  providedIn: 'root'+})+export class SuggestionModalForCreatorDashboardBackendApiService {+  constructor(+    private http: HttpClient,+    private urlInterpolationService: UrlInterpolationService,+    private suggestionObjectFactory: SuggestionObjectFactory) { }++  _updateSuggestion(+      urlDetails: UrlDetails,+      data: SuggestionData): Promise<Suggestion> {
  _updateSuggestion(
      urlDetails: UrlDetails, data: SuggestionData): Promise<Suggestion> {
biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

 require('components/ck-editor-helpers/ck-editor-4-rte.directive.ts'); require('components/ck-editor-helpers/ck-editor-4-widgets.initializer.ts'); -require('domain/utilities/url-interpolation.service.ts');-require('services/suggestion-modal.service.ts'); require(   'pages/creator-dashboard-page/suggestion-modal-for-creator-view/' +-  'suggestion-modal-for-creator-view.controller');+'suggestion-modal-for-creator-dashboard-backend-api.service.ts');

Indent this line by two spaces.

  'suggestion-modal-for-creator-dashboard-backend-api.service.ts');
biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

+// 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 Service to update suggestion in creator view+ */++import { downgradeInjectable } from '@angular/upgrade/static';+import { Injectable } from '@angular/core';+import { HttpClient } from '@angular/common/http';++import { UrlInterpolationService } from 'domain/utilities/url-interpolation.service';+import { Suggestion, SuggestionBackendDict, SuggestionObjectFactory } from 'domain/suggestion/SuggestionObjectFactory';++export interface SuggestionData {+  action: string,+  commitMessage: string,+  reviewMessage: string+}++export interface UrlDetails {+  targetType: string,+  targetId: number,+  suggestionId: number+}++export interface UpdateSuggestionBackendResponse {+  suggestion: SuggestionBackendDict;+}++@Injectable({+  providedIn: 'root'+})+export class SuggestionModalForCreatorDashboardBackendApiService {+  constructor(+    private http: HttpClient,+    private urlInterpolationService: UrlInterpolationService,+    private suggestionObjectFactory: SuggestionObjectFactory) { }++  _updateSuggestion(+      urlDetails: UrlDetails,+      data: SuggestionData): Promise<Suggestion> {+    return new Promise((resolve, reject) => {+      var HANDLE_SUGGESTION_URL_TEMPLATE = (

Change this to const.

biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

+// 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 Unit tests for+ * * SuggestionModalForCreatorDashboardBackendApiService.+ */+import { HttpClientTestingModule, HttpTestingController } from+  '@angular/common/http/testing';+import { TestBed, fakeAsync, flushMicrotasks } from '@angular/core/testing';++import { SuggestionModalForCreatorDashboardBackendApiService } from+  './suggestion-modal-for-creator-dashboard-backend-api.service';+import { SuggestionObjectFactory } from+  'domain/suggestion/SuggestionObjectFactory';++describe('SuggestionModalForCreatorDashboardBackendApiService', () => {+  let sugBackendApiService: SuggestionModalForCreatorDashboardBackendApiService;+  let httpTestingController: HttpTestingController;+  let suggestionObjectFactory: SuggestionObjectFactory;+  let suggestionBackendDict = {+    suggestion_id: '1',+    suggestion_type: 'edit_exploration_state_content',+    target_type: 'exploration',+    target_id: '2',+    target_version_at_submission: 1,+    status: 'accepted',+    author_name: 'author',+    change: {+      cmd: 'edit_state_property',+      property_name: 'content',+      state_name: 'state_1',+      new_value: {+        html: 'new suggestion content'+      },+      old_value: {+        html: 'old suggestion content'+      }+    },+    last_updated_msecs: 1000+  };++  beforeEach(() => {+    TestBed.configureTestingModule({+      imports: [HttpClientTestingModule],+      providers: [SuggestionModalForCreatorDashboardBackendApiService]+    });++    httpTestingController = TestBed.get(HttpTestingController);+    suggestionObjectFactory = TestBed.get(SuggestionObjectFactory);+    sugBackendApiService = TestBed+      .get(SuggestionModalForCreatorDashboardBackendApiService);+  });++  afterEach(() => {+    httpTestingController.verify();+  });++  it('should make a request to update the suggestion in the backend',+    fakeAsync(() => {+      const suggestion = suggestionObjectFactory+        .createFromBackendDict(suggestionBackendDict);+      const backendResponse = {+        suggestion: suggestionBackendDict+      };++      let urlDetails = {+        targetType: 'exploration',+        targetId: 0,+        suggestionId: 0+      };++      let updateData = {+        action: 'accept',+        commitMessage: 'commit message',+        reviewMessage: 'review message'+      };++      sugBackendApiService._updateSuggestion(urlDetails, updateData)+        .then(response => {+          expect(response).toEqual(suggestion);+        });

While this is perfectly valid, it would be better if you could follow this:

  1. Setup - this is where you prepare any inputs/environment needed for the test.
  2. Baseline verification - check the values without performing any action. This step is only needed if your action is state-changing (i.e., if the same assert statement would lead to one result at baseline, and a different result at endline). Use the same assertion here that you would use at endline.
  3. Action - perform the action or function call that leads to the expected change.
  4. Endline verification - check that the values in the baseline verification have changed accordingly.

Instead of putting the expect inside .then, can you create a spy as you have done in the test below? That way you can pass the success and failure spies to the .then and expect success to have been called with suggestion and failure to not have been called at the end of the test after flushMicrotasks().

biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

+// 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 Service to update suggestion in creator view+ */++import { downgradeInjectable } from '@angular/upgrade/static';+import { Injectable } from '@angular/core';+import { HttpClient } from '@angular/common/http';++import { UrlInterpolationService } from 'domain/utilities/url-interpolation.service';+import { Suggestion, SuggestionBackendDict, SuggestionObjectFactory } from 'domain/suggestion/SuggestionObjectFactory';++export interface SuggestionData {+  action: string,+  commitMessage: string,+  reviewMessage: string+}++export interface UrlDetails {+  targetType: string,+  targetId: number,+  suggestionId: number+}++export interface UpdateSuggestionBackendResponse {+  suggestion: SuggestionBackendDict;+}++@Injectable({+  providedIn: 'root'+})+export class SuggestionModalForCreatorDashboardBackendApiService {+  constructor(+    private http: HttpClient,+    private urlInterpolationService: UrlInterpolationService,+    private suggestionObjectFactory: SuggestionObjectFactory) { }++  _updateSuggestion(

We use _ to indicate private functions in the codebase. Can you remove the underscore?

biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

+// 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 Unit tests for+ * * SuggestionModalForCreatorDashboardBackendApiService.+ */+import { HttpClientTestingModule, HttpTestingController } from+  '@angular/common/http/testing';+import { TestBed, fakeAsync, flushMicrotasks } from '@angular/core/testing';++import { SuggestionModalForCreatorDashboardBackendApiService } from+  './suggestion-modal-for-creator-dashboard-backend-api.service';+import { SuggestionObjectFactory } from+  'domain/suggestion/SuggestionObjectFactory';++describe('SuggestionModalForCreatorDashboardBackendApiService', () => {+  let sugBackendApiService: SuggestionModalForCreatorDashboardBackendApiService;+  let httpTestingController: HttpTestingController;+  let suggestionObjectFactory: SuggestionObjectFactory;+  let suggestionBackendDict = {+    suggestion_id: '1',+    suggestion_type: 'edit_exploration_state_content',+    target_type: 'exploration',+    target_id: '2',+    target_version_at_submission: 1,+    status: 'accepted',+    author_name: 'author',+    change: {+      cmd: 'edit_state_property',+      property_name: 'content',+      state_name: 'state_1',+      new_value: {+        html: 'new suggestion content'+      },+      old_value: {+        html: 'old suggestion content'+      }+    },+    last_updated_msecs: 1000+  };++  beforeEach(() => {+    TestBed.configureTestingModule({+      imports: [HttpClientTestingModule],+      providers: [SuggestionModalForCreatorDashboardBackendApiService]+    });++    httpTestingController = TestBed.get(HttpTestingController);+    suggestionObjectFactory = TestBed.get(SuggestionObjectFactory);+    sugBackendApiService = TestBed+      .get(SuggestionModalForCreatorDashboardBackendApiService);+  });++  afterEach(() => {+    httpTestingController.verify();+  });++  it('should make a request to update the suggestion in the backend',+    fakeAsync(() => {+      const suggestion = suggestionObjectFactory+        .createFromBackendDict(suggestionBackendDict);

Break after parens.

      const suggestion = suggestionObjectFactory.createFromBackendDict(
        suggestionBackendDict);
biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

 import { SubtopicPageObjectFactory } from   'domain/topic/SubtopicPageObjectFactory'; import { SubtopicViewerBackendApiService } from   'domain/subtopic_viewer/subtopic-viewer-backend-api.service';+import { SuggestionModalForCreatorDashboardBackendApiService } from

You no longer need to add migrated services here. Please remove it.

biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

+// 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 Unit tests for+ * * SuggestionModalForCreatorDashboardBackendApiService.+ */+import { HttpClientTestingModule, HttpTestingController } from+  '@angular/common/http/testing';+import { TestBed, fakeAsync, flushMicrotasks } from '@angular/core/testing';++import { SuggestionModalForCreatorDashboardBackendApiService } from+  './suggestion-modal-for-creator-dashboard-backend-api.service';+import { SuggestionObjectFactory } from+  'domain/suggestion/SuggestionObjectFactory';++describe('SuggestionModalForCreatorDashboardBackendApiService', () => {+  let sugBackendApiService: SuggestionModalForCreatorDashboardBackendApiService;+  let httpTestingController: HttpTestingController;+  let suggestionObjectFactory: SuggestionObjectFactory;+  let suggestionBackendDict = {+    suggestion_id: '1',+    suggestion_type: 'edit_exploration_state_content',+    target_type: 'exploration',+    target_id: '2',+    target_version_at_submission: 1,+    status: 'accepted',+    author_name: 'author',+    change: {+      cmd: 'edit_state_property',+      property_name: 'content',+      state_name: 'state_1',+      new_value: {+        html: 'new suggestion content'+      },+      old_value: {+        html: 'old suggestion content'+      }+    },+    last_updated_msecs: 1000+  };++  beforeEach(() => {+    TestBed.configureTestingModule({+      imports: [HttpClientTestingModule],+      providers: [SuggestionModalForCreatorDashboardBackendApiService]+    });++    httpTestingController = TestBed.get(HttpTestingController);+    suggestionObjectFactory = TestBed.get(SuggestionObjectFactory);+    sugBackendApiService = TestBed+      .get(SuggestionModalForCreatorDashboardBackendApiService);+  });++  afterEach(() => {+    httpTestingController.verify();+  });++  it('should make a request to update the suggestion in the backend',+    fakeAsync(() => {

We usually break a line after a parenthesis, i.e., (. Can you shift fakeAsync( to the previous line?

biaba

comment created time in 2 days

Pull request review commentoppia/oppia

Fix #8038: http calls moved from suggestion-modal-for-creator-view.service.ts to *backend.api.service v2

 angular.module('oppia').config([       'StoryObjectFactory', 'StorySummaryObjectFactory',       'StoryViewerBackendApiService', 'SubtopicObjectFactory',       'SubtopicPageContentsObjectFactory', 'SubtopicPageObjectFactory',-      'SubtopicViewerBackendApiService', 'SuggestionThreadObjectFactory',+      'SubtopicViewerBackendApiService',+      'SuggestionModalForCreatorDashboardBackendApiService',

Adding services is not required here anymore. Can you please remove it?

biaba

comment created time in 2 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentoppia/oppia

Fix part of #8668 Add JSDocs to window-ref.service.ts

 import { Injectable } from '@angular/core';   providedIn: 'root' }) export class WindowRef {+  /**+  * @returns the global native browser window object

@larakhdavies The comments should start with capital letters and end with a period(.) Can you do this here and below as well?

  * @returns The global native browser window object.
larakhdavies

comment created time in 3 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentoppia/oppia

Fix part of #8472: Migrate topic-rights-backend-api.service & question-validation.service to Angular 8

 import { ProfilePageBackendApiService } from import { PythonProgramTokenizer } from 'classifiers/python-program.tokenizer'; import { QuestionBackendApiService } from   'domain/question/question-backend-api.service.ts';+import { QuestionValidationService } from+  'services/question-validation.service.ts';+import { QuestionObjectFactory } from+  'domain/question/QuestionObjectFactory';

Additions to UpgradedServices are not required anymore. Can you remove these additions?

nadintamer

comment created time in 3 days

Pull request review commentoppia/oppia

Fix part of #8472: Migrate topic-rights-backend-api.service & question-validation.service to Angular 8

  * @fileoverview Unit tests for TopicRightsBackendApiService.  */ -// TODO(#7222): Remove the following block of unnnecessary imports once-// the code corresponding to the spec is upgraded to Angular 8.-import { UpgradedServices } from 'services/UpgradedServices';-// ^^^ This block is to be removed.--import { TranslatorProviderForTests } from 'tests/test.extras';--require('domain/topic/topic-rights-backend-api.service.ts');-require('services/csrf-token.service.ts');--describe('Topic rights backend API service', function() {-  var TopicRightsBackendApiService = null;-  var $rootScope = null;-  var $httpBackend = null;-  var CsrfService = null;-  var topicId = '0';--  beforeEach(angular.mock.module('oppia'));-  beforeEach(-    angular.mock.module('oppia', TranslatorProviderForTests));-  beforeEach(angular.mock.module('oppia', function($provide) {-    var ugs = new UpgradedServices();-    for (let [key, value] of Object.entries(ugs.getUpgradedServices())) {-      $provide.value(key, value);-    }-  }));--  beforeEach(angular.mock.inject(function($injector, $q) {-    TopicRightsBackendApiService = $injector.get(-      'TopicRightsBackendApiService');-    CsrfService = $injector.get('CsrfTokenService');-    $rootScope = $injector.get('$rootScope');-    $httpBackend = $injector.get('$httpBackend');--    spyOn(CsrfService, 'getTokenAsync').and.callFake(function() {-      var deferred = $q.defer();-      deferred.resolve('sample-csrf-token');-      return deferred.promise;+import { HttpClientTestingModule, HttpTestingController } from+  '@angular/common/http/testing';+import { TestBed, fakeAsync, flushMicrotasks } from '@angular/core/testing';++import { TopicRightsBackendApiService } from+  'domain/topic/topic-rights-backend-api.service';+import { TopicRights } from 'domain/topic/topic-rights.model.ts';++describe('Topic rights backend API service', () => {+  let topicRightsBackendApiService: TopicRightsBackendApiService = null;+  let httpTestingController: HttpTestingController;+  let topicId = '0';+  let topicName = '';+  let topicRightsDict = {+    can_edit_topic: false,+    can_publish_topic: true,+    published: true+  };+  let topicRightsObject = null;++  beforeEach(() => {+    TestBed.configureTestingModule({+      imports: [HttpClientTestingModule],+      providers: [TopicRightsBackendApiService]     });-  }));++    topicRightsBackendApiService = TestBed.get(TopicRightsBackendApiService);+    httpTestingController = TestBed.get(HttpTestingController);++    topicRightsObject = TopicRights.createFromBackendDict(topicRightsDict);+  });    afterEach(function() {-    $httpBackend.verifyNoOutstandingExpectation();-    $httpBackend.verifyNoOutstandingRequest();+    httpTestingController.verify();   }); -  it('should fetch a topic rights', function() {-    var successHandler = jasmine.createSpy('success');-    var failHandler = jasmine.createSpy('fail');+  it('should fetch a topic rights', fakeAsync(() => {+    let successHandler = jasmine.createSpy('success');+    let failHandler = jasmine.createSpy('fail'); -    $httpBackend.expect('GET', '/rightshandler/get_topic_rights/' + topicId)-      .respond(200);-    TopicRightsBackendApiService.fetchTopicRights(topicId).then(+    topicRightsBackendApiService.fetchTopicRights(topicId).then(       successHandler, failHandler);-    $httpBackend.flush();+    var req = httpTestingController.expectOne(+      '/rightshandler/get_topic_rights/' + topicId);+    expect(req.request.method).toEqual('GET');+    req.flush(200);++    flushMicrotasks();      expect(successHandler).toHaveBeenCalled();     expect(failHandler).not.toHaveBeenCalled();-  });+  })); -  it('should not fetch a topic rights', function() {-    var successHandler = jasmine.createSpy('success');-    var failHandler = jasmine.createSpy('fail');+  it('should not fetch a topic rights', fakeAsync(() => {+    let successHandler = jasmine.createSpy('success');+    let failHandler = jasmine.createSpy('fail');

const. Can you check for this sort of changes everywhere in the PR once?

nadintamer

comment created time in 3 days

Pull request review commentoppia/oppia

Fix part of #8472: Migrate topic-rights-backend-api.service & question-validation.service to Angular 8

  * @fileoverview Service to change the rights of topic in the backend.  */ -require('domain/utilities/url-interpolation.service.ts');+import { downgradeInjectable } from '@angular/upgrade/static';+import { Injectable } from '@angular/core';+import { HttpClient } from '@angular/common/http';++import cloneDeep from 'lodash/cloneDeep';++import { UrlInterpolationService } from+  'domain/utilities/url-interpolation.service.ts';+import { TopicDomainConstants } from+  'domain/topic/topic-domain.constants';+import { TopicRightsBackendDict, TopicRights }+  from 'domain/topic/topic-rights.model.ts';++@Injectable({+  providedIn: 'root'+})+export class TopicRightsBackendApiService {+  constructor(+    private http: HttpClient,+    private urlInterpolation: UrlInterpolationService) {} -require('domain/topic/topic-domain.constants.ajs.ts');--angular.module('oppia').factory('TopicRightsBackendApiService', [-  '$http', '$q', 'UrlInterpolationService',-  'TOPIC_RIGHTS_URL_TEMPLATE',-  function(-      $http, $q, UrlInterpolationService, TOPIC_RIGHTS_URL_TEMPLATE) {     // Maps previously loaded topic rights to their IDs.-    var topicRightsCache = {};--    var _fetchTopicRights = function(-        topicId, successCallback, errorCallback) {-      var topicRightsUrl = UrlInterpolationService.interpolateUrl(-        TOPIC_RIGHTS_URL_TEMPLATE, {+    private _topicRightsCache = {};++    private _fetchTopicRights(+        topicId: string,+        successCallback: (value?: Object | PromiseLike<Object>) => void,

Can you change this from PromiseLike to Promise and change the type from Object to the actual type we are using (I think the type is TopicRight, check once). Can you also do that in _setTopicStatus function?

        successCallback: (value?: Object | Promise<TopicRights>) => void,
nadintamer

comment created time in 3 days

Pull request review commentoppia/oppia

Fix part of #8472: Migrate topic-rights-backend-api.service & question-validation.service to Angular 8

 export interface QuestionBackendDict {   'inapplicable_skill_misconception_ids': string[]; } -angular.module('oppia').factory('QuestionObjectFactory', [-  'StateObjectFactory', 'DEFAULT_LANGUAGE_CODE', 'INTERACTION_SPECS',-  function(StateObjectFactory, DEFAULT_LANGUAGE_CODE, INTERACTION_SPECS) {-    var Question = function(-        id, stateData, languageCode, version, linkedSkillIds,-        inapplicableSkillMisconceptionIds) {-      this._id = id;-      this._stateData = stateData;-      this._languageCode = languageCode;-      this._version = version;-      this._linkedSkillIds = linkedSkillIds;-      this._inapplicableSkillMisconceptionIds = (-        inapplicableSkillMisconceptionIds);-    };--    // ---- Instance methods ----+export class Question {+  _id: string;+  _stateData: State;+  _stateDataSchemaVersion: number;+  _languageCode: string;+  _version: number;+  _linkedSkillIds: string[];+  _inapplicableSkillMisconceptionIds: string[];++  constructor(+      id: string, stateData: State, stateDataSchemaVersion: number,+      languageCode: string, version: number, linkedSkillIds: string[],+      inapplicableSkillMisconceptionIds: string[]) {+    this._id = id;+    this._stateData = stateData;+    this._stateDataSchemaVersion = stateDataSchemaVersion;+    this._languageCode = languageCode;+    this._version = version;+    this._linkedSkillIds = linkedSkillIds;+    this._inapplicableSkillMisconceptionIds = (+      inapplicableSkillMisconceptionIds);+  }

I think initializing this way would be better.

  constructor(
      private _id: string, 
      private _stateData: State, 
      private _stateDataSchemaVersion: number,
      private _languageCode: string, 
      private _version: number,
      private _linkedSkillIds: string[],
      private _inapplicableSkillMisconceptionIds: string[]) {}
nadintamer

comment created time in 3 days

Pull request review commentoppia/oppia

Fix part of #8472: Migrate topic-rights-backend-api.service & question-validation.service to Angular 8

 export interface QuestionBackendDict {   'inapplicable_skill_misconception_ids': string[]; } -angular.module('oppia').factory('QuestionObjectFactory', [-  'StateObjectFactory', 'DEFAULT_LANGUAGE_CODE', 'INTERACTION_SPECS',-  function(StateObjectFactory, DEFAULT_LANGUAGE_CODE, INTERACTION_SPECS) {-    var Question = function(-        id, stateData, languageCode, version, linkedSkillIds,-        inapplicableSkillMisconceptionIds) {-      this._id = id;-      this._stateData = stateData;-      this._languageCode = languageCode;-      this._version = version;-      this._linkedSkillIds = linkedSkillIds;-      this._inapplicableSkillMisconceptionIds = (-        inapplicableSkillMisconceptionIds);-    };--    // ---- Instance methods ----+export class Question {+  _id: string;+  _stateData: State;+  _stateDataSchemaVersion: number;+  _languageCode: string;+  _version: number;+  _linkedSkillIds: string[];+  _inapplicableSkillMisconceptionIds: string[];++  constructor(+      id: string, stateData: State, stateDataSchemaVersion: number,+      languageCode: string, version: number, linkedSkillIds: string[],+      inapplicableSkillMisconceptionIds: string[]) {+    this._id = id;+    this._stateData = stateData;+    this._stateDataSchemaVersion = stateDataSchemaVersion;+    this._languageCode = languageCode;+    this._version = version;+    this._linkedSkillIds = linkedSkillIds;+    this._inapplicableSkillMisconceptionIds = (+      inapplicableSkillMisconceptionIds);+  } -    Question.prototype.getId = function() {-      return this._id;-    };+  getId(): string {+    return this._id;+  } -    Question.prototype.getStateData = function() {-      return this._stateData;-    };+  getStateData(): State {+    return this._stateData;+  } -    Question.prototype.setStateData = function(newStateData) {-      this._stateData = angular.copy(newStateData);-    };+  setStateData(newStateData: State): void {+    this._stateData = angular.copy(newStateData);+  } -    Question.prototype.getLanguageCode = function() {-      return this._languageCode;-    };+  getStateDataSchemaVersion(): number {+    return this._stateDataSchemaVersion;+  } -    Question.prototype.setLanguageCode = function(languageCode) {-      this._languageCode = languageCode;-    };+  getLanguageCode(): string {+    return this._languageCode;+  } -    Question.prototype.getVersion = function() {-      return this._version;-    };+  setLanguageCode(languageCode: string): void {+    this._languageCode = languageCode;+  } -    Question.prototype.getLinkedSkillIds = function() {-      return this._linkedSkillIds;-    };+  getVersion(): number {+    return this._version;+  } -    Question.prototype.setLinkedSkillIds = function(linkedSkillIds) {-      this._linkedSkillIds = linkedSkillIds;-    };+  getLinkedSkillIds(): string[] {+    return this._linkedSkillIds;+  } -    Question.prototype.getInapplicableSkillMisconceptionIds = function() {-      return this._inapplicableSkillMisconceptionIds;-    };+  setLinkedSkillIds(linkedSkillIds: string[]): void {+    this._linkedSkillIds = linkedSkillIds;+  } -    Question.prototype.setInapplicableSkillMisconceptionIds = function(-        inapplicableSkillMisconceptionIds) {-      this._inapplicableSkillMisconceptionIds = (-        inapplicableSkillMisconceptionIds);-    };+  getInapplicableSkillMisconceptionIds(): string[] {+    return this._inapplicableSkillMisconceptionIds;+  } -    // TODO(ankita240796): Remove the bracket notation once Angular2 gets in.-    /* eslint-disable-next-line dot-notation */-    Question['createDefaultQuestion'] = function(skillIds) {-      return new Question(-        null, StateObjectFactory.createDefaultState(null),-        DEFAULT_LANGUAGE_CODE, 1, skillIds, []);-    };+  setInapplicableSkillMisconceptionIds(+      inapplicableSkillMisconceptionIds: string[]): void {+    this._inapplicableSkillMisconceptionIds = (+      inapplicableSkillMisconceptionIds);+  } -    Question.prototype.getValidationErrorMessage = function() {-      var interaction = this._stateData.interaction;-      if (interaction.id === null) {-        return 'An interaction must be specified';+  getValidationErrorMessage(): string {+    var interaction = this._stateData.interaction;

Use let/const instead of var here and everywhere else. From the context, it looks like it can be const.

nadintamer

comment created time in 3 days

Pull request review commentoppia/oppia

Fix part of #8472: Migrate topic-rights-backend-api.service & question-validation.service to Angular 8

  * question domain objects.  */ -require('domain/state/StateObjectFactory.ts');+import { downgradeInjectable } from '@angular/upgrade/static';+import { Injectable } from '@angular/core';+import { State, StateBackendDict, StateObjectFactory }+  from 'domain/state/StateObjectFactory'; -import { StateBackendDict } from 'domain/state/StateObjectFactory';+const INTERACTION_SPECS = require('interactions/interaction_specs.json');+const constants = require('constants.ts');

The import order we follow is this:

  1. Angular imports (imports from @angular/*)
  2. Third-party imports (imports from rxjs, ng bootstrap, etc)
  3. Application imports. (imports from our application)

Within these sub-categories: sort lexicographically based on module (i.e. where it is imported from, not what is being imported). For example:

Right way (because 'B' < 'D')

import { C } from 'B';
import { A } from 'D'; 

Wrong way

import { A } from 'D';
import { C } from 'B'; 

Can you change that here and everywhere else in this PR (only for the migrated files)?

nadintamer

comment created time in 3 days

Pull request review commentoppia/oppia

Fix part of #8472: Migrate topic-rights-backend-api.service & question-validation.service to Angular 8

  * @fileoverview Unit tests for TopicRightsBackendApiService.  */ -// TODO(#7222): Remove the following block of unnnecessary imports once-// the code corresponding to the spec is upgraded to Angular 8.-import { UpgradedServices } from 'services/UpgradedServices';-// ^^^ This block is to be removed.--import { TranslatorProviderForTests } from 'tests/test.extras';--require('domain/topic/topic-rights-backend-api.service.ts');-require('services/csrf-token.service.ts');--describe('Topic rights backend API service', function() {-  var TopicRightsBackendApiService = null;-  var $rootScope = null;-  var $httpBackend = null;-  var CsrfService = null;-  var topicId = '0';--  beforeEach(angular.mock.module('oppia'));-  beforeEach(-    angular.mock.module('oppia', TranslatorProviderForTests));-  beforeEach(angular.mock.module('oppia', function($provide) {-    var ugs = new UpgradedServices();-    for (let [key, value] of Object.entries(ugs.getUpgradedServices())) {-      $provide.value(key, value);-    }-  }));--  beforeEach(angular.mock.inject(function($injector, $q) {-    TopicRightsBackendApiService = $injector.get(-      'TopicRightsBackendApiService');-    CsrfService = $injector.get('CsrfTokenService');-    $rootScope = $injector.get('$rootScope');-    $httpBackend = $injector.get('$httpBackend');--    spyOn(CsrfService, 'getTokenAsync').and.callFake(function() {-      var deferred = $q.defer();-      deferred.resolve('sample-csrf-token');-      return deferred.promise;+import { HttpClientTestingModule, HttpTestingController } from+  '@angular/common/http/testing';+import { TestBed, fakeAsync, flushMicrotasks } from '@angular/core/testing';++import { TopicRightsBackendApiService } from+  'domain/topic/topic-rights-backend-api.service';+import { TopicRights } from 'domain/topic/topic-rights.model.ts';++describe('Topic rights backend API service', () => {+  let topicRightsBackendApiService: TopicRightsBackendApiService = null;+  let httpTestingController: HttpTestingController;+  let topicId = '0';+  let topicName = '';+  let topicRightsDict = {+    can_edit_topic: false,+    can_publish_topic: true,+    published: true+  };+  let topicRightsObject = null;++  beforeEach(() => {+    TestBed.configureTestingModule({+      imports: [HttpClientTestingModule],+      providers: [TopicRightsBackendApiService]     });-  }));++    topicRightsBackendApiService = TestBed.get(TopicRightsBackendApiService);+    httpTestingController = TestBed.get(HttpTestingController);++    topicRightsObject = TopicRights.createFromBackendDict(topicRightsDict);+  });    afterEach(function() {-    $httpBackend.verifyNoOutstandingExpectation();-    $httpBackend.verifyNoOutstandingRequest();+    httpTestingController.verify();   }); -  it('should fetch a topic rights', function() {-    var successHandler = jasmine.createSpy('success');-    var failHandler = jasmine.createSpy('fail');+  it('should fetch a topic rights', fakeAsync(() => {+    let successHandler = jasmine.createSpy('success');+    let failHandler = jasmine.createSpy('fail'); -    $httpBackend.expect('GET', '/rightshandler/get_topic_rights/' + topicId)-      .respond(200);-    TopicRightsBackendApiService.fetchTopicRights(topicId).then(+    topicRightsBackendApiService.fetchTopicRights(topicId).then(       successHandler, failHandler);-    $httpBackend.flush();+    var req = httpTestingController.expectOne(

const

nadintamer

comment created time in 3 days

Pull request review commentoppia/oppia

Fix part of #8472: Migrate topic-rights-backend-api.service & question-validation.service to Angular 8

  * @fileoverview Unit tests for TopicRightsBackendApiService.  */ -// TODO(#7222): Remove the following block of unnnecessary imports once-// the code corresponding to the spec is upgraded to Angular 8.-import { UpgradedServices } from 'services/UpgradedServices';-// ^^^ This block is to be removed.--import { TranslatorProviderForTests } from 'tests/test.extras';--require('domain/topic/topic-rights-backend-api.service.ts');-require('services/csrf-token.service.ts');--describe('Topic rights backend API service', function() {-  var TopicRightsBackendApiService = null;-  var $rootScope = null;-  var $httpBackend = null;-  var CsrfService = null;-  var topicId = '0';--  beforeEach(angular.mock.module('oppia'));-  beforeEach(-    angular.mock.module('oppia', TranslatorProviderForTests));-  beforeEach(angular.mock.module('oppia', function($provide) {-    var ugs = new UpgradedServices();-    for (let [key, value] of Object.entries(ugs.getUpgradedServices())) {-      $provide.value(key, value);-    }-  }));--  beforeEach(angular.mock.inject(function($injector, $q) {-    TopicRightsBackendApiService = $injector.get(-      'TopicRightsBackendApiService');-    CsrfService = $injector.get('CsrfTokenService');-    $rootScope = $injector.get('$rootScope');-    $httpBackend = $injector.get('$httpBackend');--    spyOn(CsrfService, 'getTokenAsync').and.callFake(function() {-      var deferred = $q.defer();-      deferred.resolve('sample-csrf-token');-      return deferred.promise;+import { HttpClientTestingModule, HttpTestingController } from+  '@angular/common/http/testing';+import { TestBed, fakeAsync, flushMicrotasks } from '@angular/core/testing';++import { TopicRightsBackendApiService } from+  'domain/topic/topic-rights-backend-api.service';+import { TopicRights } from 'domain/topic/topic-rights.model.ts';++describe('Topic rights backend API service', () => {+  let topicRightsBackendApiService: TopicRightsBackendApiService = null;+  let httpTestingController: HttpTestingController;+  let topicId = '0';+  let topicName = '';+  let topicRightsDict = {+    can_edit_topic: false,+    can_publish_topic: true,+    published: true+  };+  let topicRightsObject = null;++  beforeEach(() => {+    TestBed.configureTestingModule({+      imports: [HttpClientTestingModule],+      providers: [TopicRightsBackendApiService]     });-  }));++    topicRightsBackendApiService = TestBed.get(TopicRightsBackendApiService);+    httpTestingController = TestBed.get(HttpTestingController);++    topicRightsObject = TopicRights.createFromBackendDict(topicRightsDict);+  });    afterEach(function() {-    $httpBackend.verifyNoOutstandingExpectation();-    $httpBackend.verifyNoOutstandingRequest();+    httpTestingController.verify();   }); -  it('should fetch a topic rights', function() {-    var successHandler = jasmine.createSpy('success');-    var failHandler = jasmine.createSpy('fail');+  it('should fetch a topic rights', fakeAsync(() => {+    let successHandler = jasmine.createSpy('success');+    let failHandler = jasmine.createSpy('fail');

I think these two can be const.

nadintamer

comment created time in 3 days

Pull request review commentoppia/oppia

Fix part of #8472: Migrate topic-rights-backend-api.service & question-validation.service to Angular 8

 export interface QuestionBackendDict {   'inapplicable_skill_misconception_ids': string[]; } -angular.module('oppia').factory('QuestionObjectFactory', [-  'StateObjectFactory', 'DEFAULT_LANGUAGE_CODE', 'INTERACTION_SPECS',-  function(StateObjectFactory, DEFAULT_LANGUAGE_CODE, INTERACTION_SPECS) {-    var Question = function(-        id, stateData, languageCode, version, linkedSkillIds,-        inapplicableSkillMisconceptionIds) {-      this._id = id;-      this._stateData = stateData;-      this._languageCode = languageCode;-      this._version = version;-      this._linkedSkillIds = linkedSkillIds;-      this._inapplicableSkillMisconceptionIds = (-        inapplicableSkillMisconceptionIds);-    };--    // ---- Instance methods ----+export class Question {+  _id: string;+  _stateData: State;+  _stateDataSchemaVersion: number;+  _languageCode: string;+  _version: number;+  _linkedSkillIds: string[];+  _inapplicableSkillMisconceptionIds: string[];

Can you add private modifier for all these variables?

nadintamer

comment created time in 3 days

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentoppia/oppia

Migrating directives to angular components

 import { platformFeatureInitFactory, PlatformFeatureService } from   ],   declarations: [     OppiaAngularRootComponent,

For reviewers: Ideally, we would like to keep this array sorted but since the OppiaAngularRootComponent is temporary we are keeping it at the top. Everything after the line should be sorted. I will add a comment about this too in the module too.

krishita30j

comment created time in 3 days

PullRequestReviewEvent
PullRequestReviewEvent

pull request commentoppia/oppia

Migrating directives to angular components

@DubeySandeep, @kevintab95, and @nithusha21 PTAL!

krishita30j

comment created time in 3 days

pull request commentoppia/oppia

Migrating directives to angular components

Hi @srijanreddy98,

This is the testing video for this PR: Link

LGTM! thanks @krishita30j. I am moving this link into PR description so that other reviewers can also see it at the very beginning.

krishita30j

comment created time in 3 days

issue openedoppia/oppia

Incorrect usage of constants in the codebase.

Constants are read-only and shouldn't be assigned to mutable variables. Here are the instances of all the incorrect usages of constants throughout the codebase.

To get these errors you need to make the change the require('constants.ts'); statements to import statements. In VSCode, this can be done using global regex search and replace. Search for const (\w*) = require\('constants.ts'\); and replace all with import $1 from 'assets/constants';

File (Line, position) Error
StatesObjectFactorySpec.ts(460,15) error TS2540: Cannot assign to 'NEW_STATE_TEMPLATE' because it is a read-only property.
StatesObjectFactorySpec.ts(511,15) error TS2540: Cannot assign to 'NEW_STATE_TEMPLATE' because it is a read-only property.
SkillObjectFactory.ts(57,3) error TS4104: The type 'readonly ["Easy", "Medium", "Hard"]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
StateObjectFactory.ts(130,7) error TS2322: Type '{ readonly id: any; readonly customization_args: {}; readonly answer_groups: readonly []; readonly default_outcome: { readonly dest: "Introduction"; readonly feedback: { readonly content_id: "default_outcome"; readonly html: ""; }; readonly labelled_as_correct: false; readonly param_changes: readonly []; readonly re...' is not assignable to type 'InteractionBackendDict'.The types of ''default_outcome'['param_changes']' are incompatible between these types.The type 'readonly []' is 'readonly' and cannot be assigned to the mutable type 'ParamChangeBackendDict[]'.
StateObjectFactory.ts(131,7) error TS4104: The type 'readonly []' is 'readonly' and cannot be assigned to the mutable type 'ParamChangeBackendDict[]'.
StateObjectFactorySpec.ts(90,15) error TS2540: Cannot assign to 'NEW_STATE_TEMPLATE' because it is a read-only property.
StateObjectFactorySpec.ts(144,15) error TS2540: Cannot assign to 'NEW_STATE_TEMPLATE' because it is a read-only property.
language-util.service.spec.ts(64,15) error TS2540: Cannot assign to 'SUPPORTED_CONTENT_LANGUAGES' because it is a read-only property.
language-util.service.spec.ts(65,15) error TS2540: Cannot assign to 'AUTOGENERATED_AUDIO_LANGUAGES' because it is a read-only property.
language-util.service.spec.ts(66,15) error TS2540: Cannot assign to 'SUPPORTED_AUDIO_LANGUAGES' because it is a read-only property.
language-util.service.spec.ts(75,15) error TS2540: Cannot assign to 'SUPPORTED_CONTENT_LANGUAGES' because it is a read-only property.
language-util.service.spec.ts(76,15) error TS2540: Cannot assign to 'AUTOGENERATED_AUDIO_LANGUAGES' because it is a read-only property.
language-util.service.spec.ts(77,15) error TS2540: Cannot assign to 'SUPPORTED_AUDIO_LANGUAGES' because it is a read-only property.
language-util.service.ts(57,3) error TS4104: The type 'readonly [{ readonly id: "en"; readonly description: "English"; readonly relatedLanguages: readonly ["en"]; }, { readonly id: "ak"; readonly description: "Akan"; readonly relatedLanguages: readonly ["ak"]; }, ... 43 more ..., { ...; }]' is 'readonly' and cannot be assigned to the mutable type 'AudioLanguageBackendDict[]'.
language-util.service.ts(59,3) error TS4104: The type 'readonly [{ readonly id: "en-auto"; readonly description: "English (auto)"; readonly explorationLanguage: "en"; readonly speechSynthesisCode: "en-US"; readonly speechSynthesisCodeMobile: "en_US"; }]' is 'readonly' and cannot be assigned to the mutable type 'AutogeneratedAudioLanguageDict[]'.
url-interpolation.service.spec.ts(44,15) error TS2540: Cannot assign to 'DEV_MODE' because it is a read-only property.
url-interpolation.service.spec.ts(50,15) error TS2540: Cannot assign to 'DEV_MODE' because it is a read-only property.
admin-features-tab/admin-features-tab.constants.ts(29,25) error TS2352: Conversion of type 'readonly ["Web", "Android"]' to type 'string[]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.The type 'readonly ["Web", "Android"]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
admin-features-tab/admin-features-tab.constants.ts(32,26) error TS2352: Conversion of type 'readonly ["Chrome", "Edge", "Safari", "Firefox", "Others"]' to type 'string[]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. The type 'readonly ["Chrome", "Edge", "Safari", "Firefox", "Others"]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
admin-features-tab/admin-features-tab.constants.ts(44,32) error TS2352: Conversion of type 'readonly ["test", "alpha", "beta", "release"]' to type 'string[]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. The type 'readonly ["test", "alpha", "beta", "release"]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.
assets-backend-api.service.spec.ts(373,17) error TS2540: Cannot assign to 'GCS_RESOURCE_BUCKET_NAME' because it is a read-only property.
assets-backend-api.service.spec.ts(375,17) error TS2540: Cannot assign to 'DEV_MODE' because it is a read-only property.
assets-backend-api.service.spec.ts(379,17) error TS2540: Cannot assign to 'GCS_RESOURCE_BUCKET_NAME' because it is a read-only property.
assets-backend-api.service.spec.ts(380,17) error TS2540: Cannot assign to 'DEV_MODE' because it is a read-only property.
assets-backend-api.service.spec.ts(406,17) error TS2540: Cannot assign to 'DEV_MODE' because it is a read-only property.
assets-backend-api.service.spec.ts(410,17) error TS2540: Cannot assign to 'DEV_MODE' because it is a read-only property.
site-analytics.service.spec.ts(34,15) error TS2540: Cannot assign to 'CAN_SEND_ANALYTICS_EVENTS' because it is a read-only property.
site-analytics.service.spec.ts(41,15) error TS2540: Cannot assign to 'CAN_SEND_ANALYTICS_EVENTS' because it is a read-only property.

created time in 3 days

pull request commentoppia/oppia

Migrating directives to angular components

Hi @krishita30j, could you also provide a testing video for this PR as mentioned in the wiki (https://github.com/oppia/oppia/wiki/Angular-Migration#testing-videos). Here are some links that might help: How to find usages of your PR: https://vimeo.com/442416282 How to check your PR: https://vimeo.com/440915367 (This is an example on how to check topic landing page).

krishita30j

comment created time in 4 days

Pull request review commentoppia/oppia

Fix part of #9749: Migrates Continue Button Directive to Angular

+<button md-button class="oppia-learner-confirm-button protractor-test-continue-to-next-card-button"
<button mat-raised-button class="oppia-learner-confirm-button protractor-test-continue-to-next-card-button"
EricZLou

comment created time in 5 days

PullRequestReviewEvent

Pull request review commentoppia/oppia

Fix part of #9749: Migrates Continue Button Directive to Angular

 <md-button class="oppia-learner-confirm-button protractor-test-continue-to-next-card-button"-           focus-on="<[::focusLabel]>"-           ng-click="onClickContinueButton()"+           focus-on="{{::focusLabel}}"+           (click)="onClickContinueButton()"            aria-label="Continue">-  <div ng-if="!isLearnAgainButton()">-    <span class="protractor-test-next-card-button" translate="I18N_PLAYER_CONTINUE_BUTTON"></span>+  <div *ngIf="!isLearnAgainButton()">+    <span class="protractor-test-next-card-button" [innerHTML]="'I18N_PLAYER_CONTINUE_BUTTON' | translate"></span>     <i class="fas fa-arrow-right icon">     </i>   </div>-  <div ng-if="isLearnAgainButton()">-    <span class="protractor-test-next-card-button" translate="I18N_PLAYER_LEARN_AGAIN_BUTTON"></span>+  <div *ngIf="isLearnAgainButton()">
  <div *ngIf="isLearnAgainButton">
EricZLou

comment created time in 5 days

Pull request review commentoppia/oppia

Fix part of #9749: Migrates Continue Button Directive to Angular

 <md-button class="oppia-learner-confirm-button protractor-test-continue-to-next-card-button"-           focus-on="<[::focusLabel]>"-           ng-click="onClickContinueButton()"+           focus-on="{{::focusLabel}}"+           (click)="onClickContinueButton()"            aria-label="Continue">-  <div ng-if="!isLearnAgainButton()">-    <span class="protractor-test-next-card-button" translate="I18N_PLAYER_CONTINUE_BUTTON"></span>+  <div *ngIf="!isLearnAgainButton()">
  <div *ngIf="!isLearnAgainButton">
EricZLou

comment created time in 5 days

Pull request review commentoppia/oppia

Fix part of #9749: Migrates Continue Button Directive to Angular

+// Copyright 2017 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.++import { Component } from '@angular/core';+import { downgradeComponent } from '@angular/upgrade/static';

Move these below file overview.

import { Component, Input, Output } from '@angular/core';
import { downgradeComponent } from '@angular/upgrade/static';
EricZLou

comment created time in 5 days

Pull request review commentoppia/oppia

Fix part of #9749: Migrates Continue Button Directive to Angular

+// Copyright 2017 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.++import { Component } from '@angular/core';+import { downgradeComponent } from '@angular/upgrade/static';++/**+ * @fileoverview Component for the Continue button in exploration player and+ * editor.+ */++// [Question]: How do I migrate the scope part of this directive?+// angular.module('oppia').directive('continueButton', [+//   function() {+//     return {+//       scope: {+//         onClickContinueButton: '&',+//         isLearnAgainButton: '&',+//         focusLabel: '@'+//       }+//     };+//   }+// ]);++@Component({+  selector: 'continue-button',+  templateUrl: './continue-button.component.html',+  styleUrls: []+})+export class ContinueButtonComponent {}+
@Input foucsLabel: string;
@Input() isLearnAgainButton: boolean: false;
@Output() clickContinueButton: EventEmitter<void> = new EventEmitter();
EricZLou

comment created time in 5 days

Pull request review commentoppia/oppia

Fix part of #9749: Migrates Continue Button Directive to Angular

 <md-button class="oppia-learner-confirm-button protractor-test-continue-to-next-card-button"-           focus-on="<[::focusLabel]>"-           ng-click="onClickContinueButton()"+           focus-on="{{::focusLabel}}"+           (click)="onClickContinueButton()"
           (click)="clickContinueButton.emit()"
EricZLou

comment created time in 5 days

PullRequestReviewEvent
PullRequestReviewEvent

push eventoppia/oppia

Siddharth Batra

commit sha ae35f494ee7ac2ef4ff16662b9434046ace8138d

Fixes Part of #8472: Migrate Expression Interpolation Service (#10991) * Fix Minor Issue * Fix Minor Issue * Fix Review Comments * Fix type issue

view details

push time in 5 days

PR merged oppia/oppia

Fixes Part of #8472: Migrate Expression Interpolation Service PR CHANGELOG: Angular Migration -- @srijanreddy98 PR: LGTM

Overview

  1. This PR fixes or fixes part of #8472
  2. This PR does the following: Migrates expression-interpolation-service to angular 8

Essential Checklist

  • [x] The PR title starts with "Fix #bugnum: ", followed by a short, clear summary of the changes. (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".)
  • [x] The linter/Karma presubmit checks have passed locally on your machine.
  • [x] "Allow edits from maintainers" is checked. (See here for instructions on how to enable it.)
    • This lets reviewers restart your CircleCI tests for you.
  • [x] The PR is made from a branch that's not called "develop".
+191 -219

10 comments

14 changed files

darksun27

pr closed time in 5 days

push eventsrijanreddy98/oppia

Srijan Reddy

commit sha 6987d838f9aef9e782d9ff7f397c434ea41940a4

Changes to package.lock

view details

push time in 5 days

pull request commentoppia/oppia

Upgrade to Angular to 10.2.0

@vojtechjelinek PTAL!

srijanreddy98

comment created time in 5 days

PR opened oppia/oppia

Reviewers
Upgrade to Angular to 10.2.0

Overview

<!-- READ ME FIRST: Please answer both questions below and check off every point from the Essential Checklist! If there is no corresponding issue number, fill in N/A where it says [fill_in_number_here] below in 1. -->

  1. This PR fixes or fixes part of #N/A.
  2. This PR does the following: Upgrades angular to version 10

Essential Checklist

  • [x] The PR title starts with "Fix #bugnum: ", followed by a short, clear summary of the changes. (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".)
  • [x] The linter/Karma presubmit checks have passed locally on your machine.
  • [x] "Allow edits from maintainers" is checked. (See here for instructions on how to enable it.)
    • This lets reviewers restart your CircleCI tests for you.
  • [x] The PR is made from a branch that's not called "develop".

PR Pointers

  • Make sure to follow the instructions for making a code change.
  • Oppiabot will notify you when you don't add a PR_CHANGELOG label. If you are unable to do so, please @-mention a code owner (who will be in the Reviewers list), or ask on Gitter.
  • For what code owners will expect, see the Code Owner's wiki page.
  • Make sure your PR follows conventions in the style guide, otherwise this will lead to review delays.
  • Never force push. If you do, your PR will be closed.
+14 -14

0 comment

1 changed file

pr created time in 5 days

create barnchsrijanreddy98/oppia

branch : upgrade-angular-version

created branch time in 5 days

PullRequestReviewEvent

Pull request review commentoppia/oppia

Migrating directives to angular components

-<md-card class="oppia-page-card oppia-long-text oppia-long-text-card">+<mat-card class="oppia-page-card oppia-long-text oppia-long-text-card"> The 'Activities' tab is not available in the production environment.-</md-card>+</mat-card>

Can wrap this in a div with class = admin-prod-mode-activities-tab and change the style in line number 5 to .admin-prod-mode-activities-tab .oppia-long-text-card (Note the extra dot at the beginning of the change).

krishita30j

comment created time in 6 days

Pull request review commentoppia/oppia

Migrating directives to angular components

 // limitations under the License.  /**- * @fileoverview Directive for the activities tab in the admin panel when Oppia+ * @fileoverview Component for the activities tab in the admin panel when Oppia  * is in production mode.  */ -require('domain/utilities/url-interpolation.service.ts');+import { Component } from '@angular/core';+import { downgradeComponent } from '@angular/upgrade/static';+++@Component({+  selector: 'admin-prod-mode-activities-tab',+  templateUrl: './admin-prod-mode-activities-tab.component.html',+  styleUrls: []+})++export class AdminProdModeActivitiesTabComponent {+  constructor() {}+} -angular.module('oppia').directive('adminProdModeActivitiesTab', [-  'UrlInterpolationService', function(UrlInterpolationService) {-    return {-      restrict: 'E',-      scope: {},-      bindToController: {},-      templateUrl: UrlInterpolationService.getDirectiveTemplateUrl(-        '/pages/admin-page/activities-tab/' +-        'admin-prod-mode-activities-tab.directive.html'),-      controllerAs: '$ctrl',-      controller: [function() {}]-    };-  }-]);+angular.module('oppia').directive(+  'adminProdModeActivitiesTab', downgradeComponent(+    {+      component: AdminProdModeActivitiesTabComponent+    }+  )+);
angular.module('oppia').directive(
  'adminProdModeActivitiesTab', downgradeComponent({
    component: AdminProdModeActivitiesTabComponent}));
krishita30j

comment created time in 6 days

Pull request review commentoppia/oppia

Migrating directives to angular components

+// Copyright 2018 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 Component for the navbar breadcrumb of the collection editor.+ */++import { Component } from '@angular/core';+import { downgradeComponent } from '@angular/upgrade/static';++@Component({+  selector: 'topics-and-skills-dashboard-navbar-breadcrumb',+  templateUrl: './topics-and-skills-dashboard-navbar-breadcrumb.component.html',+  styleUrls: []+})++export class TopicsAndSkillsDashboardNavbarBreadcrumbComponent {+  constructor() {}+}++angular.module('oppia').directive(+  'topicsAndSkillsDashboardNavbarBreadcrumb', downgradeComponent(+    {+      component: TopicsAndSkillsDashboardNavbarBreadcrumbComponent+    }+  )+);
angular.module('oppia').directive(
  'topicsAndSkillsDashboardNavbarBreadcrumb', downgradeComponent({
    component: TopicsAndSkillsDashboardNavbarBreadcrumbComponent}));
krishita30j

comment created time in 6 days

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentoppia/oppia

Fix Part of #8472: Migrate image upload helper

  * @fileoverview Image upload helper service.  */ -require('services/assets-backend-api.service.ts');--// TODO(#9186): Change variable name to 'constants' once this file-// is migrated to Angular.-const Constants = require('constants.ts');--angular.module('oppia').factory('ImageUploadHelperService', [-  '$sce', 'AssetsBackendApiService',-  function($sce, AssetsBackendApiService) {-    var _generateDateTimeStringForFilename = function() {-      var date = new Date();-      return date.getFullYear() +-        ('0' + (date.getMonth() + 1)).slice(-2) +-        ('0' + date.getDate()).slice(-2) + '_' +-        ('0' + date.getHours()).slice(-2) +-        ('0' + date.getMinutes()).slice(-2) +-        ('0' + date.getSeconds()).slice(-2) + '_' +-        Math.random().toString(36).substr(2, 10);-    };-    return {-      convertImageDataToImageFile: function(dataURI) {-        // Convert base64/URLEncoded data component to raw binary data-        // held in a string.-        var byteString = atob(dataURI.split(',')[1]);--        // Separate out the mime component.-        var mime = dataURI.split(',')[0].split(':')[1].split(';')[0];--        // Write the bytes of the string to a typed array.-        var ia = new Uint8Array(byteString.length);-        for (var i = 0; i < byteString.length; i++) {-          ia[i] = byteString.charCodeAt(i);+import { Injectable } from '@angular/core';+import { downgradeInjectable } from '@angular/upgrade/static';+import { DomSanitizer } from '@angular/platform-browser';++import { AssetsBackendApiService } from 'services/assets-backend-api.service';++import constants from 'assets/constants';++@Injectable({+  providedIn: 'root'+})+export class ImageUploadHelperService {+  constructor(+    private assetsBackendApiService: AssetsBackendApiService,+    private sanitizer: DomSanitizer+  ) {}++  private _generateDateTimeStringForFilename() {+    let date = new Date();+    return date.getFullYear() ++      ('0' + (date.getMonth() + 1)).slice(-2) ++      ('0' + date.getDate()).slice(-2) + '_' ++      ('0' + date.getHours()).slice(-2) ++      ('0' + date.getMinutes()).slice(-2) ++      ('0' + date.getSeconds()).slice(-2) + '_' ++      Math.random().toString(36).substr(2, 10);+  }++  convertImageDataToImageFile(dataURI: string): Blob {+    // Convert base64/URLEncoded data component to raw binary data+    // held in a string.+    let byteString = atob(dataURI.split(',')[1]);++    // Separate out the mime component.+    let mime = dataURI.split(',')[0].split(':')[1].split(';')[0];++    // Write the bytes of the string to a typed array.+    let ia = new Uint8Array(byteString.length);+    for (let i = 0; i < byteString.length; i++) {+      ia[i] = byteString.charCodeAt(i);+    }++    let blob = new Blob([ia], { type: mime });+    if (blob.type.match('image') &&+      blob.size > 0) {+      return blob;+    } else {+      return null;+    }+  }++  getInvalidSvgTagsAndAttrs(dataURI: string): {} {+    // Convert base64/URLEncoded data component to raw binary data+    // held in a string.+    let svgString = atob(dataURI.split(',')[1]);+    let domParser = new DOMParser();+    let doc = domParser.parseFromString(svgString, 'image/svg+xml');+    let invalidTags = [];+    let invalidAttrs = [];+    let allowedTags = Object.keys(constants.SVG_ATTRS_WHITELIST);+    let nodeTagName = null;+    doc.querySelectorAll('*').forEach((node) => {+      nodeTagName = node.tagName.toLowerCase();+      if (allowedTags.indexOf(nodeTagName) !== -1) {+        for (let i = 0; i < node.attributes.length; i++) {+          if (constants.SVG_ATTRS_WHITELIST[nodeTagName].indexOf(+            node.attributes[i].name.toLowerCase()) === -1) {+            invalidAttrs.push(+              node.tagName + ':' + node.attributes[i].name);+          }         }+      } else {+        invalidTags.push(node.tagName);+      }+    });+    return { tags: invalidTags, attrs: invalidAttrs };+  } -        var blob = new Blob([ia], { type: mime });-        if (blob.type.match('image') &&-          blob.size > 0) {-          return blob;-        } else {-          return null;+  getTrustedResourceUrlForThumbnailFilename(+      imageFileName: string, entityType: string, entityId: string): string {+    let encodedFilepath = window.encodeURIComponent(imageFileName);+    return this.sanitizer.bypassSecurityTrustResourceUrl(+      this.assetsBackendApiService.getThumbnailUrlForPreview(+        entityType, entityId, encodedFilepath)) as string;+  }++  generateImageFilename(+      height: number, width: number, extension: string): string {+    return 'img_' ++      this._generateDateTimeStringForFilename() ++      '_height_' + height ++      '_width_' + width ++      '.' + extension;+  }++  cleanMathExpressionSvgString(svgString: string): string {+    // We need to modify/remove unnecessary attributes added by mathjax+    // from the svg tag.+    let domParser = new DOMParser();+    let doc = domParser.parseFromString(svgString, 'image/svg+xml');+    doc.querySelectorAll('*').forEach((node) => {+      if (node.tagName.toLowerCase() === 'svg') {+        node.removeAttribute('xmlns:xlink');+        node.removeAttribute('role');+        // We are removing this attribute, because currently it is not in+        // the white list of valid attributes.+        node.removeAttribute('aria-hidden');+        node.setAttribute('xmlns', 'http://www.w3.org/2000/svg');+      }+      // Remove the custom data attributes added by MathJax.+      // These custom attributes don't affect the rendering of the SVGs,+      // and they are not present in the white list for allowed attributes.+      for (let i = 0; i < node.attributes.length; i++) {+        if (node.attributes[i].name.toLowerCase().startsWith('data-')) {+          node.removeAttribute(node.attributes[i].name.toLowerCase());         }-      },--      getInvalidSvgTagsAndAttrs: function(dataURI) {-        // Convert base64/URLEncoded data component to raw binary data-        // held in a string.-        var svgString = atob(dataURI.split(',')[1]);-        var domParser = new DOMParser();-        var doc = domParser.parseFromString(svgString, 'image/svg+xml');-        var invalidTags = [];-        var invalidAttrs = [];-        var allowedTags = Object.keys(Constants.SVG_ATTRS_WHITELIST);-        var nodeTagName = null;-        doc.querySelectorAll('*').forEach((node) => {-          nodeTagName = node.tagName.toLowerCase();-          if (allowedTags.indexOf(nodeTagName) !== -1) {-            for (var i = 0; i < node.attributes.length; i++) {-              if (Constants.SVG_ATTRS_WHITELIST[nodeTagName].indexOf(-                node.attributes[i].name.toLowerCase()) === -1) {-                invalidAttrs.push(-                  node.tagName + ':' + node.attributes[i].name);-              }-            }-          } else {-            invalidTags.push(node.tagName);-          }-        });-        return { tags: invalidTags, attrs: invalidAttrs };-      },--      getTrustedResourceUrlForThumbnailFilename: function(-          imageFileName, entityType, entityId) {-        var encodedFilepath = window.encodeURIComponent(imageFileName);-        return $sce.trustAsResourceUrl(

Just FYI, as per offline discussion with @darksun27, we will be migrating the directives that use this function from image-uploader-helper.service.ts To use this function properly, we need angular 8 binding mechanism <some-html-tag [src]="variable">.... we can't use <some-thml ng-src="" src="$ctrl.somevar">

darksun27

comment created time in 6 days

PullRequestReviewEvent

issue commentoppia/oppia

Fixing End-to-End Tests with action.js and waitFor.js

Hi @U8NWXD , I'd like to work on core/tests/protractor_utils/GetStartedPage.js, please. thanks!

Done! It's all yours now.

U8NWXD

comment created time in 8 days

Pull request review commentoppia/oppia

Fix Part of #8472: Migrate image upload helper

  * @fileoverview Image upload helper service.  */ -require('services/assets-backend-api.service.ts');--// TODO(#9186): Change variable name to 'constants' once this file-// is migrated to Angular.-const Constants = require('constants.ts');--angular.module('oppia').factory('ImageUploadHelperService', [-  '$sce', 'AssetsBackendApiService',-  function($sce, AssetsBackendApiService) {-    var _generateDateTimeStringForFilename = function() {-      var date = new Date();-      return date.getFullYear() +-        ('0' + (date.getMonth() + 1)).slice(-2) +-        ('0' + date.getDate()).slice(-2) + '_' +-        ('0' + date.getHours()).slice(-2) +-        ('0' + date.getMinutes()).slice(-2) +-        ('0' + date.getSeconds()).slice(-2) + '_' +-        Math.random().toString(36).substr(2, 10);-    };-    return {-      convertImageDataToImageFile: function(dataURI) {-        // Convert base64/URLEncoded data component to raw binary data-        // held in a string.-        var byteString = atob(dataURI.split(',')[1]);--        // Separate out the mime component.-        var mime = dataURI.split(',')[0].split(':')[1].split(';')[0];--        // Write the bytes of the string to a typed array.-        var ia = new Uint8Array(byteString.length);-        for (var i = 0; i < byteString.length; i++) {-          ia[i] = byteString.charCodeAt(i);+import { Injectable } from '@angular/core';+import { downgradeInjectable } from '@angular/upgrade/static';+import { DomSanitizer } from '@angular/platform-browser';++import { AssetsBackendApiService } from 'services/assets-backend-api.service';++import constants from 'assets/constants';++@Injectable({+  providedIn: 'root'+})+export class ImageUploadHelperService {+  constructor(+    private assetsBackendApiService: AssetsBackendApiService,+    private sanitizer: DomSanitizer+  ) {}++  private _generateDateTimeStringForFilename() {+    let date = new Date();+    return date.getFullYear() ++      ('0' + (date.getMonth() + 1)).slice(-2) ++      ('0' + date.getDate()).slice(-2) + '_' ++      ('0' + date.getHours()).slice(-2) ++      ('0' + date.getMinutes()).slice(-2) ++      ('0' + date.getSeconds()).slice(-2) + '_' ++      Math.random().toString(36).substr(2, 10);+  }++  convertImageDataToImageFile(dataURI: string): Blob {+    // Convert base64/URLEncoded data component to raw binary data+    // held in a string.+    let byteString = atob(dataURI.split(',')[1]);++    // Separate out the mime component.+    let mime = dataURI.split(',')[0].split(':')[1].split(';')[0];++    // Write the bytes of the string to a typed array.+    let ia = new Uint8Array(byteString.length);+    for (let i = 0; i < byteString.length; i++) {+      ia[i] = byteString.charCodeAt(i);+    }++    let blob = new Blob([ia], { type: mime });+    if (blob.type.match('image') &&+      blob.size > 0) {+      return blob;+    } else {+      return null;+    }+  }++  getInvalidSvgTagsAndAttrs(dataURI: string): {} {+    // Convert base64/URLEncoded data component to raw binary data+    // held in a string.+    let svgString = atob(dataURI.split(',')[1]);+    let domParser = new DOMParser();+    let doc = domParser.parseFromString(svgString, 'image/svg+xml');+    let invalidTags = [];+    let invalidAttrs = [];+    let allowedTags = Object.keys(constants.SVG_ATTRS_WHITELIST);+    let nodeTagName = null;+    doc.querySelectorAll('*').forEach((node) => {+      nodeTagName = node.tagName.toLowerCase();+      if (allowedTags.indexOf(nodeTagName) !== -1) {+        for (let i = 0; i < node.attributes.length; i++) {+          if (constants.SVG_ATTRS_WHITELIST[nodeTagName].indexOf(+            node.attributes[i].name.toLowerCase()) === -1) {+            invalidAttrs.push(+              node.tagName + ':' + node.attributes[i].name);+          }         }+      } else {+        invalidTags.push(node.tagName);+      }+    });+    return { tags: invalidTags, attrs: invalidAttrs };+  } -        var blob = new Blob([ia], { type: mime });-        if (blob.type.match('image') &&-          blob.size > 0) {-          return blob;-        } else {-          return null;+  getTrustedResourceUrlForThumbnailFilename(+      imageFileName: string, entityType: string, entityId: string): string {+    let encodedFilepath = window.encodeURIComponent(imageFileName);+    return this.sanitizer.bypassSecurityTrustResourceUrl(+      this.assetsBackendApiService.getThumbnailUrlForPreview(+        entityType, entityId, encodedFilepath)) as string;+  }++  generateImageFilename(+      height: number, width: number, extension: string): string {+    return 'img_' ++      this._generateDateTimeStringForFilename() ++      '_height_' + height ++      '_width_' + width ++      '.' + extension;+  }++  cleanMathExpressionSvgString(svgString: string): string {+    // We need to modify/remove unnecessary attributes added by mathjax+    // from the svg tag.+    let domParser = new DOMParser();+    let doc = domParser.parseFromString(svgString, 'image/svg+xml');+    doc.querySelectorAll('*').forEach((node) => {+      if (node.tagName.toLowerCase() === 'svg') {+        node.removeAttribute('xmlns:xlink');+        node.removeAttribute('role');+        // We are removing this attribute, because currently it is not in+        // the white list of valid attributes.+        node.removeAttribute('aria-hidden');+        node.setAttribute('xmlns', 'http://www.w3.org/2000/svg');+      }+      // Remove the custom data attributes added by MathJax.+      // These custom attributes don't affect the rendering of the SVGs,+      // and they are not present in the white list for allowed attributes.+      for (let i = 0; i < node.attributes.length; i++) {+        if (node.attributes[i].name.toLowerCase().startsWith('data-')) {+          node.removeAttribute(node.attributes[i].name.toLowerCase());         }-      },--      getInvalidSvgTagsAndAttrs: function(dataURI) {-        // Convert base64/URLEncoded data component to raw binary data-        // held in a string.-        var svgString = atob(dataURI.split(',')[1]);-        var domParser = new DOMParser();-        var doc = domParser.parseFromString(svgString, 'image/svg+xml');-        var invalidTags = [];-        var invalidAttrs = [];-        var allowedTags = Object.keys(Constants.SVG_ATTRS_WHITELIST);-        var nodeTagName = null;-        doc.querySelectorAll('*').forEach((node) => {-          nodeTagName = node.tagName.toLowerCase();-          if (allowedTags.indexOf(nodeTagName) !== -1) {-            for (var i = 0; i < node.attributes.length; i++) {-              if (Constants.SVG_ATTRS_WHITELIST[nodeTagName].indexOf(-                node.attributes[i].name.toLowerCase()) === -1) {-                invalidAttrs.push(-                  node.tagName + ':' + node.attributes[i].name);-              }-            }-          } else {-            invalidTags.push(node.tagName);-          }-        });-        return { tags: invalidTags, attrs: invalidAttrs };-      },--      getTrustedResourceUrlForThumbnailFilename: function(-          imageFileName, entityType, entityId) {-        var encodedFilepath = window.encodeURIComponent(imageFileName);-        return $sce.trustAsResourceUrl(

@kevintab95, @seanlip any idea why this is here in the first place? There is no appropriate unit test for this function as well.

darksun27

comment created time in 9 days

PullRequestReviewEvent
PullRequestReviewEvent

push eventoppia/oppia

Siddharth Batra

commit sha a63fe8aada02e07592e1186711a7ed83d44e665b

Fix part of #10700: Refactor Object Factories with Dependencies (#10868) * Refactor Collection Node Object Factory * Refactor Collection Object Factory * Refactor Email Query Deashboard and Email Query Dashboard Results Object Factories * Refactor Platform Parameter Filter, Rule Object Factories * Refactor Exploration Stats Object Factories * Refactor LearnerExplorationSummary and UserProfile Object Factories * Refactor ReadOnlyStoryNode and StoryPlaythrough Object Factories * Refactor TopicSummary and ClassroomData Object Factories * Refactor HighBounceRateTask Object Factory * Refactor SuccessiveIncorrectAnswerTask IneffectiveFeedbackLoopTask NeedsGuidingResponseTask and ExplorationTask Object Factories * Fix coverage * Fix coverage * Fix coverage * Fix Coverage * Fix Review Issues * Fix Frontend Test Issues * Add TODO(#10875): Fix type mismatch * Add TODO(#10875): Fix type mismatch * Fix Merge conflicts in angular-services * Fix compile issues

view details

push time in 9 days

PR merged oppia/oppia

Fix part of #10700: Refactor Object Factories with Dependencies PR CHANGELOG: Angular Migration -- @srijanreddy98 PR: LGTM

Overview

  1. This PR fixes or fixes part of #10700
  2. This PR does the following: This PR refactors the following object factories:
  • CollectionNode
  • CollectionPlaythrough
  • Collection
  • EmailDashboardQuery
  • EmailDashboardQueryResults
  • PlatformParameter
  • PlatformParameterFilter
  • PlatformParameterRule
  • LearnerExplorationSummary
  • ReadOnlyStoryNode
  • StoryPlaythrough
  • UserProfile
  • ExplorationStats
  • HighBounceRateTask
  • SuccessiveIncorrectAnswersTask
  • IneffectiveFeedbackLoopTask
  • NeedsGuidingResponesTask
  • ExplorationTasks
  • TopicSummary
  • ClassroomData

Essential Checklist

  • [x] The PR title starts with "Fix #bugnum: ", followed by a short, clear summary of the changes. (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".)
  • [x] The linter/Karma presubmit checks have passed locally on your machine.
  • [x] "Allow edits from maintainers" is checked. (See here for instructions on how to enable it.)
    • This lets reviewers restart your CircleCI tests for you.
  • [x] The PR is made from a branch that's not called "develop".
+1127 -2016

16 comments

105 changed files

darksun27

pr closed time in 9 days

Pull request review commentoppia/oppia

Fixes Part of #8472: Migrate Expression Interpolation Service

  * @fileoverview Service for interpolating expressions.  */ -require('filters/convert-html-to-unicode.filter.ts');-require('expressions/expression-evaluator.service.ts');-require('expressions/expression-parser.service.ts');-require('expressions/expression-syntax-tree.service.ts');-require('services/html-escaper.service.ts');+import { Injectable } from '@angular/core';+import { downgradeInjectable } from '@angular/upgrade/static'; -// Interpolates an HTML or a unicode string containing expressions.-// The input value is evaluated against the supplied environments.-//-// Examples:-//   processHtml('abc{{a}}', [{'a': 'b'}]) gives 'abcb'.-//   processHtml('abc{{a}}', [{}]) returns null.-//   processHtml('abc', [{}]) returns 'abc'.-//   processHtml('{[a}}', [{'a': '<button></button>'}])-//     returns '&lt;button&gt;&lt;/button&gt;'.-//   processUnicode('abc{{a}}', [{'a': 'b'}]) gives 'abcb'.-//   processUnicode('abc{{a}}', [{}]) returns null.-//   processUnicode('{[a}}', [{'a': '<button></button>'}]) returns-//     '<button></button>'.-angular.module('oppia').factory('ExpressionInterpolationService', [-  '$filter', 'ExpressionEvaluatorService', 'ExpressionParserService',-  'ExpressionSyntaxTreeService', 'HtmlEscaperService',-  function(-      $filter, ExpressionEvaluatorService, ExpressionParserService,-      ExpressionSyntaxTreeService, HtmlEscaperService) {-    return {-      // This method should only be used if its result would immediately be-      // displayed on the screen without passing through further computation.-      // It differs from other methods in this service in that it-      // auto-escapes the returned HTML, and returns an 'error' label if the-      // evaluation fails.-      processHtml: function(sourceHtml, envs) {-        return sourceHtml.replace(/{{([^}]*)}}/g, function(match, p1) {-          try {-            // TODO(sll): Remove the call to $filter once we have a-            // custom UI for entering expressions. It is only needed because-            // expressions are currently input inline via the RTE.-            return HtmlEscaperService.unescapedStrToEscapedStr(-              ExpressionEvaluatorService.evaluateExpression(-                $filter('convertHtmlToUnicode')(p1), envs));-          } catch (e) {-            var EXPRESSION_ERROR_TAG = (-              '<oppia-expression-error-tag></oppia-expression-error-tag>');-            if ((e instanceof ExpressionParserService.SyntaxError) ||-                (e instanceof ExpressionSyntaxTreeService.ExpressionError)) {-              return EXPRESSION_ERROR_TAG;-            }-            throw e;-          }-        });-      },-      // Returns null if the evaluation fails.-      processUnicode: function(sourceUnicode, envs) {-        try {-          return sourceUnicode.replace(/{{([^}]*)}}/g, function(match, p1) {-            // TODO(sll): Remove the call to $filter once we have a-            // custom UI for entering expressions. It is only needed because-            // expressions are currently input inline via the RTE.-            return ExpressionEvaluatorService.evaluateExpression(-              $filter('convertHtmlToUnicode')(p1), envs);-          });-        } catch (e) {-          if ((e instanceof ExpressionParserService.SyntaxError) ||-              (e instanceof ExpressionSyntaxTreeService.ExpressionError)) {-            return null;-          }-          throw e;+import { convertHtmlToUnicode } from 'filters/convert-html-to-unicode.filter';+import { ExpressionEvaluatorService } from+  'expressions/expression-evaluator.service';+import { ExpressionParserService } from 'expressions/expression-parser.service';+import { ExpressionSyntaxTreeService } from+  'expressions/expression-syntax-tree.service';+import { HtmlEscaperService } from 'services/html-escaper.service';++@Injectable({+  providedIn: 'root'+})+export class ExpressionInterpolationService {+  constructor(+    private expressionEvaluatorService: ExpressionEvaluatorService,+    private expressionParserService: ExpressionParserService,+    private expressionSyntaxTreeService: ExpressionSyntaxTreeService,+    private htmlEscaperService: HtmlEscaperService+  ) {}++  processHtml(sourceHtml: string, envs: [{}]): string {

What does an element of env constitute of?

darksun27

comment created time in 9 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentoppia/oppia

Fixes Part of #8472: Migrate Expression Interpolation Service

  * @fileoverview Service for interpolating expressions.  */ -require('filters/convert-html-to-unicode.filter.ts');-require('expressions/expression-evaluator.service.ts');-require('expressions/expression-parser.service.ts');-require('expressions/expression-syntax-tree.service.ts');-require('services/html-escaper.service.ts');+import { Injectable } from '@angular/core';+import { downgradeInjectable } from '@angular/upgrade/static'; -// Interpolates an HTML or a unicode string containing expressions.-// The input value is evaluated against the supplied environments.-//-// Examples:-//   processHtml('abc{{a}}', [{'a': 'b'}]) gives 'abcb'.-//   processHtml('abc{{a}}', [{}]) returns null.-//   processHtml('abc', [{}]) returns 'abc'.-//   processHtml('{[a}}', [{'a': '<button></button>'}])-//     returns '&lt;button&gt;&lt;/button&gt;'.-//   processUnicode('abc{{a}}', [{'a': 'b'}]) gives 'abcb'.-//   processUnicode('abc{{a}}', [{}]) returns null.-//   processUnicode('{[a}}', [{'a': '<button></button>'}]) returns-//     '<button></button>'.-angular.module('oppia').factory('ExpressionInterpolationService', [-  '$filter', 'ExpressionEvaluatorService', 'ExpressionParserService',-  'ExpressionSyntaxTreeService', 'HtmlEscaperService',-  function(-      $filter, ExpressionEvaluatorService, ExpressionParserService,-      ExpressionSyntaxTreeService, HtmlEscaperService) {-    return {-      // This method should only be used if its result would immediately be-      // displayed on the screen without passing through further computation.-      // It differs from other methods in this service in that it-      // auto-escapes the returned HTML, and returns an 'error' label if the-      // evaluation fails.-      processHtml: function(sourceHtml, envs) {-        return sourceHtml.replace(/{{([^}]*)}}/g, function(match, p1) {-          try {-            // TODO(sll): Remove the call to $filter once we have a-            // custom UI for entering expressions. It is only needed because-            // expressions are currently input inline via the RTE.-            return HtmlEscaperService.unescapedStrToEscapedStr(-              ExpressionEvaluatorService.evaluateExpression(-                $filter('convertHtmlToUnicode')(p1), envs));-          } catch (e) {-            var EXPRESSION_ERROR_TAG = (-              '<oppia-expression-error-tag></oppia-expression-error-tag>');-            if ((e instanceof ExpressionParserService.SyntaxError) ||-                (e instanceof ExpressionSyntaxTreeService.ExpressionError)) {-              return EXPRESSION_ERROR_TAG;-            }-            throw e;-          }-        });-      },-      // Returns null if the evaluation fails.-      processUnicode: function(sourceUnicode, envs) {-        try {-          return sourceUnicode.replace(/{{([^}]*)}}/g, function(match, p1) {-            // TODO(sll): Remove the call to $filter once we have a-            // custom UI for entering expressions. It is only needed because-            // expressions are currently input inline via the RTE.-            return ExpressionEvaluatorService.evaluateExpression(-              $filter('convertHtmlToUnicode')(p1), envs);-          });-        } catch (e) {-          if ((e instanceof ExpressionParserService.SyntaxError) ||-              (e instanceof ExpressionSyntaxTreeService.ExpressionError)) {-            return null;-          }-          throw e;+import { convertHtmlToUnicode } from 'filters/convert-html-to-unicode.filter';+import { ExpressionEvaluatorService } from+  'expressions/expression-evaluator.service';+import { ExpressionParserService } from 'expressions/expression-parser.service';+import { ExpressionSyntaxTreeService } from+  'expressions/expression-syntax-tree.service';+import { HtmlEscaperService } from 'services/html-escaper.service';++@Injectable({+  providedIn: 'root'+})+export class ExpressionInterpolationService {+  constructor(+    private expressionEvaluatorService: ExpressionEvaluatorService,+    private expressionParserService: ExpressionParserService,+    private expressionSyntaxTreeService: ExpressionSyntaxTreeService,+    private htmlEscaperService: HtmlEscaperService+  ) {}++  processHtml(sourceHtml: string, envs: [{}]): string {

Is env an array containing only one empty object?

darksun27

comment created time in 10 days

Pull request review commentoppia/oppia

Fixes Part of #8472: Migrate Expression Interpolation Service

  * @fileoverview Service for interpolating expressions.  */ -require('filters/convert-html-to-unicode.filter.ts');-require('expressions/expression-evaluator.service.ts');-require('expressions/expression-parser.service.ts');-require('expressions/expression-syntax-tree.service.ts');-require('services/html-escaper.service.ts');+import { Injectable } from '@angular/core';+import { downgradeInjectable } from '@angular/upgrade/static'; -// Interpolates an HTML or a unicode string containing expressions.-// The input value is evaluated against the supplied environments.-//-// Examples:-//   processHtml('abc{{a}}', [{'a': 'b'}]) gives 'abcb'.-//   processHtml('abc{{a}}', [{}]) returns null.-//   processHtml('abc', [{}]) returns 'abc'.-//   processHtml('{[a}}', [{'a': '<button></button>'}])-//     returns '&lt;button&gt;&lt;/button&gt;'.-//   processUnicode('abc{{a}}', [{'a': 'b'}]) gives 'abcb'.-//   processUnicode('abc{{a}}', [{}]) returns null.-//   processUnicode('{[a}}', [{'a': '<button></button>'}]) returns-//     '<button></button>'.-angular.module('oppia').factory('ExpressionInterpolationService', [-  '$filter', 'ExpressionEvaluatorService', 'ExpressionParserService',-  'ExpressionSyntaxTreeService', 'HtmlEscaperService',-  function(-      $filter, ExpressionEvaluatorService, ExpressionParserService,-      ExpressionSyntaxTreeService, HtmlEscaperService) {-    return {-      // This method should only be used if its result would immediately be-      // displayed on the screen without passing through further computation.-      // It differs from other methods in this service in that it-      // auto-escapes the returned HTML, and returns an 'error' label if the-      // evaluation fails.-      processHtml: function(sourceHtml, envs) {-        return sourceHtml.replace(/{{([^}]*)}}/g, function(match, p1) {-          try {-            // TODO(sll): Remove the call to $filter once we have a-            // custom UI for entering expressions. It is only needed because-            // expressions are currently input inline via the RTE.-            return HtmlEscaperService.unescapedStrToEscapedStr(-              ExpressionEvaluatorService.evaluateExpression(-                $filter('convertHtmlToUnicode')(p1), envs));-          } catch (e) {-            var EXPRESSION_ERROR_TAG = (-              '<oppia-expression-error-tag></oppia-expression-error-tag>');-            if ((e instanceof ExpressionParserService.SyntaxError) ||-                (e instanceof ExpressionSyntaxTreeService.ExpressionError)) {-              return EXPRESSION_ERROR_TAG;-            }-            throw e;-          }-        });-      },-      // Returns null if the evaluation fails.-      processUnicode: function(sourceUnicode, envs) {-        try {-          return sourceUnicode.replace(/{{([^}]*)}}/g, function(match, p1) {-            // TODO(sll): Remove the call to $filter once we have a-            // custom UI for entering expressions. It is only needed because-            // expressions are currently input inline via the RTE.-            return ExpressionEvaluatorService.evaluateExpression(-              $filter('convertHtmlToUnicode')(p1), envs);-          });-        } catch (e) {-          if ((e instanceof ExpressionParserService.SyntaxError) ||-              (e instanceof ExpressionSyntaxTreeService.ExpressionError)) {-            return null;-          }-          throw e;+import { convertHtmlToUnicode } from 'filters/convert-html-to-unicode.filter';+import { ExpressionEvaluatorService } from+  'expressions/expression-evaluator.service';+import { ExpressionParserService } from 'expressions/expression-parser.service';+import { ExpressionSyntaxTreeService } from+  'expressions/expression-syntax-tree.service';+import { HtmlEscaperService } from 'services/html-escaper.service';++@Injectable({+  providedIn: 'root'+})+export class ExpressionInterpolationService {+  constructor(+    private expressionEvaluatorService: ExpressionEvaluatorService,+    private expressionParserService: ExpressionParserService,+    private expressionSyntaxTreeService: ExpressionSyntaxTreeService,+    private htmlEscaperService: HtmlEscaperService+  ) {}++  processHtml(sourceHtml: string, envs: [{}]): string {+    return sourceHtml.replace(/{{([^}]*)}}/g, (match, p1)=> {+      try {+        // TODO(sll): Remove the call to $filter once we have a+        // custom UI for entering expressions. It is only needed because+        // expressions are currently input inline via the RTE.+        return this.htmlEscaperService.unescapedStrToEscapedStr(+          this.expressionEvaluatorService.evaluateExpression(+            convertHtmlToUnicode(p1), envs) as string);+      } catch (e) {+        var EXPRESSION_ERROR_TAG = (

const

darksun27

comment created time in 9 days

Pull request review commentoppia/oppia

Fixes Part of #8472: Migrate Expression Interpolation Service

  * @fileoverview Service for interpolating expressions.  */ -require('filters/convert-html-to-unicode.filter.ts');-require('expressions/expression-evaluator.service.ts');-require('expressions/expression-parser.service.ts');-require('expressions/expression-syntax-tree.service.ts');-require('services/html-escaper.service.ts');+import { Injectable } from '@angular/core';+import { downgradeInjectable } from '@angular/upgrade/static'; -// Interpolates an HTML or a unicode string containing expressions.-// The input value is evaluated against the supplied environments.-//-// Examples:-//   processHtml('abc{{a}}', [{'a': 'b'}]) gives 'abcb'.-//   processHtml('abc{{a}}', [{}]) returns null.-//   processHtml('abc', [{}]) returns 'abc'.-//   processHtml('{[a}}', [{'a': '<button></button>'}])-//     returns '&lt;button&gt;&lt;/button&gt;'.-//   processUnicode('abc{{a}}', [{'a': 'b'}]) gives 'abcb'.-//   processUnicode('abc{{a}}', [{}]) returns null.-//   processUnicode('{[a}}', [{'a': '<button></button>'}]) returns-//     '<button></button>'.-angular.module('oppia').factory('ExpressionInterpolationService', [-  '$filter', 'ExpressionEvaluatorService', 'ExpressionParserService',-  'ExpressionSyntaxTreeService', 'HtmlEscaperService',-  function(-      $filter, ExpressionEvaluatorService, ExpressionParserService,-      ExpressionSyntaxTreeService, HtmlEscaperService) {-    return {-      // This method should only be used if its result would immediately be-      // displayed on the screen without passing through further computation.-      // It differs from other methods in this service in that it-      // auto-escapes the returned HTML, and returns an 'error' label if the-      // evaluation fails.-      processHtml: function(sourceHtml, envs) {-        return sourceHtml.replace(/{{([^}]*)}}/g, function(match, p1) {-          try {-            // TODO(sll): Remove the call to $filter once we have a-            // custom UI for entering expressions. It is only needed because-            // expressions are currently input inline via the RTE.-            return HtmlEscaperService.unescapedStrToEscapedStr(-              ExpressionEvaluatorService.evaluateExpression(-                $filter('convertHtmlToUnicode')(p1), envs));-          } catch (e) {-            var EXPRESSION_ERROR_TAG = (-              '<oppia-expression-error-tag></oppia-expression-error-tag>');-            if ((e instanceof ExpressionParserService.SyntaxError) ||-                (e instanceof ExpressionSyntaxTreeService.ExpressionError)) {-              return EXPRESSION_ERROR_TAG;-            }-            throw e;-          }-        });-      },-      // Returns null if the evaluation fails.-      processUnicode: function(sourceUnicode, envs) {-        try {-          return sourceUnicode.replace(/{{([^}]*)}}/g, function(match, p1) {-            // TODO(sll): Remove the call to $filter once we have a-            // custom UI for entering expressions. It is only needed because-            // expressions are currently input inline via the RTE.-            return ExpressionEvaluatorService.evaluateExpression(-              $filter('convertHtmlToUnicode')(p1), envs);-          });-        } catch (e) {-          if ((e instanceof ExpressionParserService.SyntaxError) ||-              (e instanceof ExpressionSyntaxTreeService.ExpressionError)) {-            return null;-          }-          throw e;+import { convertHtmlToUnicode } from 'filters/convert-html-to-unicode.filter';+import { ExpressionEvaluatorService } from+  'expressions/expression-evaluator.service';+import { ExpressionParserService } from 'expressions/expression-parser.service';+import { ExpressionSyntaxTreeService } from+  'expressions/expression-syntax-tree.service';+import { HtmlEscaperService } from 'services/html-escaper.service';++@Injectable({+  providedIn: 'root'+})+export class ExpressionInterpolationService {+  constructor(+    private expressionEvaluatorService: ExpressionEvaluatorService,+    private expressionParserService: ExpressionParserService,+    private expressionSyntaxTreeService: ExpressionSyntaxTreeService,+    private htmlEscaperService: HtmlEscaperService+  ) {}++  processHtml(sourceHtml: string, envs: [{}]): string {+    return sourceHtml.replace(/{{([^}]*)}}/g, (match, p1)=> {+      try {+        // TODO(sll): Remove the call to $filter once we have a+        // custom UI for entering expressions. It is only needed because+        // expressions are currently input inline via the RTE.+        return this.htmlEscaperService.unescapedStrToEscapedStr(+          this.expressionEvaluatorService.evaluateExpression(+            convertHtmlToUnicode(p1), envs) as string);+      } catch (e) {+        var EXPRESSION_ERROR_TAG = (+          '<oppia-expression-error-tag></oppia-expression-error-tag>');+        if ((e instanceof this.expressionParserService.SyntaxError) ||+            (e instanceof this.expressionSyntaxTreeService.ExpressionError)) {+          return EXPRESSION_ERROR_TAG;         }-      },-      // This works for both unicode and HTML.-      getParamsFromString: function(sourceString) {-        var matches = sourceString.match(/{{([^}]*)}}/g) || [];+        throw e;+      }+    });+  }++  processUnicode(sourceUnicode: string, envs: [{}]): string {+    try {+      return sourceUnicode.replace(/{{([^}]*)}}/g, (match, p1)=> {+        // TODO(sll): Remove the call to $filter once we have a+        // custom UI for entering expressions. It is only needed because+        // expressions are currently input inline via the RTE.+        return this.expressionEvaluatorService.evaluateExpression(+          convertHtmlToUnicode(p1), envs) as string;+      });+    } catch (e) {+      if ((e instanceof this.expressionParserService.SyntaxError) ||+          (e instanceof this.expressionSyntaxTreeService.ExpressionError)) {+        return null;+      }+      throw e;+    }+  } -        var allParams = [];-        for (var i = 0; i < matches.length; i++) {-          // Trim the '{{' and '}}'.-          matches[i] = matches[i].substring(2, matches[i].length - 2);+  getParamsFromString(sourceString: string): string[] {+    var matches = sourceString.match(/{{([^}]*)}}/g) || [];

use const/let everywhere

darksun27

comment created time in 9 days

Pull request review commentoppia/oppia

Fixes Part of #8472: Migrate Expression Interpolation Service

  * @fileoverview Unit tests for ExpressionInterpolationService.  */ -// TODO(#7222): Remove the following block of unnnecessary imports once-// the code corresponding to the spec is upgraded to Angular 8.-import { UpgradedServices } from 'services/UpgradedServices';-// ^^^ This block is to be removed.+import { HttpClientTestingModule } from+  '@angular/common/http/testing';+import { TestBed } from '@angular/core/testing'; -require('App.ts');-require('expressions/expression-interpolation.service.ts');+import { ExpressionInterpolationService } from+  'expressions/expression-interpolation.service'; -describe('Expression interpolation service', function() {-  beforeEach(angular.mock.module('oppia'));-  beforeEach(angular.mock.module('oppia', function($provide) {-    var ugs = new UpgradedServices();-    for (let [key, value] of Object.entries(ugs.getUpgradedServices())) {-      $provide.value(key, value);-    }-  }));+import 'App';

What happens when you remove this import?

darksun27

comment created time in 10 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent
GollumEvent
PullRequestReviewEvent

Pull request review commentoppia/oppia

Fixes part of #9749: Migrates state-param-changes-editor.component to Angular

  * @fileoverview Unit tests for stateParamChangesEditor component.  */ -import { TestBed } from '@angular/core/testing';+import { NO_ERRORS_SCHEMA } from '@angular/core';+import { ComponentFixture, async, TestBed } from '@angular/core/testing';++import { StateParamChangesEditorComponent } from+  // eslint-disable-next-line max-len+  'pages/exploration-editor-page/editor-tab/state-param-changes-editor/state-param-changes-editor.component'; import { StateParamChangesService } from   // eslint-disable-next-line max-len   'components/state-editor/state-editor-properties-services/state-param-changes.service'; -require(-  'pages/exploration-editor-page/editor-tab/state-param-changes-editor/' +-  'state-param-changes-editor.component.ts');--describe('State Param Changes Editor directive', function() {-  var $scope = null;-  var stateParamChangesService = null;--  beforeEach(angular.mock.module('oppia'));+let component: StateParamChangesEditorComponent;+let fixture: ComponentFixture<StateParamChangesEditorComponent>;+describe('State Param Changes Editor directive', () => {+  let stateParamChangesService: StateParamChangesService = null;+  beforeEach(async(() => {+    TestBed.configureTestingModule({+      declarations: [StateParamChangesEditorComponent],+      providers: [+        StateParamChangesService+      ],

This might not be required. Can you remove once and check.

Deepam101

comment created time in 13 days

Pull request review commentoppia/oppia

Fixes part of #9749: Migrates state-param-changes-editor.component to Angular

 import { ParamSpecsObjectFactory } from import { StateCustomizationArgsService } from   // eslint-disable-next-line max-len   'components/state-editor/state-editor-properties-services/state-customization-args.service';+import { destroyPlatform } from '@angular/core';+import { setupAndGetUpgradedComponent } from 'tests/unit-test-utils';+import { async } from '@angular/core/testing';+import { ParamChangesEditorDirective } from './param-changes-editor.component';

The import order we follow is this:

  1. Angular imports (imports from @angular/*)
  2. Third-party imports (imports from rxjs, ng bootstrap, etc)
  3. Application imports. (imports from our application)

Within these sub-categories: sort lexicographically based on module (i.e. where it is imported from, not what is being imported). For example:

Right way (because 'B' < 'D')

import { C } from 'B';
import { A } from 'D'; 

Wrong way

import { A } from 'D';
import { C } from 'B'; 

Can you check for that here and every other "migrated" file (not wrapped).

Deepam101

comment created time in 13 days

Pull request review commentoppia/oppia

Fixes part of #9749: Migrates state-param-changes-editor.component to Angular

  * state editor.  */ -require(-  'components/state-editor/state-editor-properties-services/' +-  'state-param-changes.service.ts');-require(-  'components/state-editor/state-editor-properties-services/' +-  'state-property.service.ts');+import { Component, OnInit } from '@angular/core';+import { downgradeComponent } from '@angular/upgrade/static';+import { StateParamChangesService } from+  // eslint-disable-next-line max-len+  'components/state-editor/state-editor-properties-services/state-param-changes.service'; -angular.module('oppia').component('stateParamChangesEditor', {-  template: require('./state-param-changes-editor.component.html'),-  controller: [-    '$scope', 'StateParamChangesService',-    function($scope, StateParamChangesService) {-      $scope.StateParamChangesService = StateParamChangesService;-    }-  ]-});+@Component({+  selector: 'state-param-changes-editor',+  templateUrl: './state-param-changes-editor.component.html',+  styleUrls: []+})+export class StateParamChangesEditorComponent implements OnInit {+  public spcs: StateParamChangesService;

public is not required here.

Deepam101

comment created time in 13 days

Pull request review commentoppia/oppia

Fixes part of #9749: Migrates state-param-changes-editor.component to Angular

 import { CkEditorCopyToolbarComponent } from 'components/ck-editor-helpers/ck-ed   ],   declarations: [     CkEditorCopyToolbarComponent,-    OppiaAngularRootComponent+    OppiaAngularRootComponent,+    StateParamChangesEditorComponent,+    ParamChangesEditorDirective

Can this be sorted lexicographically?

Deepam101

comment created time in 13 days

PullRequestReviewEvent
PullRequestReviewEvent

issue commentoppia/oppia

Introduce HttpService and phase in usage throughout codebase

@brianrodri why can't this be achieved with Http Interceptors? https://angular.io/guide/http#intercepting-requests-and-responses.

brianrodri

comment created time in 13 days

push eventoppia/oppia

linnhallonqvist

commit sha 5229d2e9803c3015351cd64d150022885398eb55

Fix Part of #8668: Add JsDocs to date-time-format file (#10814) * add jsdoc to date-time-format.service.ts * Update add jsdoc to date-time-format.service.js * Correct errors * Address review comments Co-authored-by: linha255 <linha255@tlhw-5-2.ad.liu.se> Co-authored-by: linha255 <linha255@tlhw-4-3.ad.liu.se>

view details

push time in 13 days

PR merged oppia/oppia

Fix Part of #8668: Add JsDocs to date-time-format file PR: LGTM

Overview

<!-- READ ME FIRST: Please answer both questions below and check off every point from the Essential Checklist! If there is no corresponding issue number, fill in N/A where it says [fill_in_number_here] below in 1. -->

  1. This PR fixes or fixes part of #8668
  2. This PR does the following: Adding JsDocs to the file date-time-format.service.ts.

Essential Checklist

  • [x] The PR title starts with "Fix #bugnum: ", followed by a short, clear summary of the changes. (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".)
  • [x] The linter/Karma presubmit checks have passed locally on your machine.
  • [x] "Allow edits from maintainers" is checked. (See here for instructions on how to enable it.)
    • This lets reviewers restart your CircleCI tests for you.
  • [x] The PR is made from a branch that's not called "develop".

PR Pointers

  • Make sure to follow the instructions for making a code change.
  • Oppiabot will notify you when you don't add a PR_CHANGELOG label. If you are unable to do so, please @-mention a code owner (who will be in the Reviewers list), or ask on Gitter.
  • For what code owners will expect, see the Code Owner's wiki page.
  • Make sure your PR follows conventions in the style guide, otherwise this will lead to review delays.
  • Never force push. If you do, your PR will be closed.
+28 -7

8 comments

1 changed file

linnhallonqvist

pr closed time in 13 days

pull request commentoppia/oppia

Fix Part of #8668: Add JsDocs to date-time-format file

@linnhallonqvist congrats on getting your first PR merged.

linnhallonqvist

comment created time in 13 days

PullRequestReviewEvent
more