Skip to content

Commit

Permalink
Fix oppia#6672: Translation prioritization (oppia#9443)
Browse files Browse the repository at this point in the history
* added config for featured language

* styling

* added get endpoint

* frontend backend service + tests

* styling; codeowners

* sort inputs

* sorted imports

* Styling

* formatting

* basic component setup

* fixed linting

* new selector completed

* styling

* EtE tests

* Added E2E test for switching languages

* e2e

* removed usused code

* tests are failing

* a few tests

* finished tests

* relative reference exception

* relative reference exception

* relative reference exception

* linting

* linting

* linting

* linter

* Addressed comments

* cleaned up code

* styling

* increased coverage by fixing async tests [skip ci]

* [skip ci] cleaned up code

* async/await for backend

* try catch

* [skip ci] removed unnecessary try catch wrap

* let => const

* fixed e2e test, backend lint, typescript eror

* Addressed review comments

* added validator

* fixed test

* fixed e2e test

* addressed review comments

* Styling

* styling

* html styling

* fixed relative import

* fixed import

* typos

* review comments

* syntax

* syntax

* tests

* styling

* remove fit

* review

* doc string

* test

* conf

* fixed frontend tests

* fixed test

* styling

* fixed test

* Update core/templates/pages/community-dashboard-page/translation-language-selector/translation-language-selector.component.spec.ts

Co-authored-by: Mariana Zangrossi <[email protected]>

* async try catch

* styling

Co-authored-by: shavavo <[email protected]>
Co-authored-by: Mariana Zangrossi <[email protected]>
  • Loading branch information
3 people authored Jul 1, 2020
1 parent 1ee6ceb commit 165c637
Show file tree
Hide file tree
Showing 22 changed files with 811 additions and 49 deletions.
15 changes: 15 additions & 0 deletions core/controllers/community_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from constants import constants
from core.controllers import acl_decorators
from core.controllers import base
from core.domain import config_domain
from core.domain import exp_fetchers
from core.domain import opportunity_services
from core.domain import topic_fetchers
Expand Down Expand Up @@ -233,3 +234,17 @@ def get(self):
community_rights.can_review_questions
if community_rights else False)
})


class FeaturedTranslationLanguagesHandler(base.BaseHandler):
"""Provides featured translation languages set in admin config."""

GET_HANDLER_ERROR_RETURN_TYPE = feconf.HANDLER_TYPE_JSON

@acl_decorators.open_access
def get(self):
"""Handles GET requests."""
self.render_json({
'featured_translation_languages':
config_domain.FEATURED_TRANSLATION_LANGUAGES.value
})
27 changes: 27 additions & 0 deletions core/controllers/community_dashboard_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from __future__ import absolute_import # pylint: disable=import-only-modules
from __future__ import unicode_literals # pylint: disable=import-only-modules

from core.domain import config_services
from core.domain import exp_domain
from core.domain import exp_services
from core.domain import story_domain
Expand Down Expand Up @@ -452,3 +453,29 @@ def test_user_check_community_rights(self):
'can_review_voiceover_for_language_codes': [],
'can_review_questions': True
})


class FeaturedTranslationLanguagesHandlerTest(test_utils.GenericTestBase):
"""Test for the FeaturedTranslationLanguagesHandler."""

def test_get_featured_translation_languages(self):
response = self.get_json('/retrivefeaturedtranslationlanguages')
self.assertEqual(
response,
{'featured_translation_languages': []}
)

new_value = [
{'language_code': 'en', 'explanation': 'Partnership with ABC'}
]
config_services.set_property(
'admin',
'featured_translation_languages',
new_value
)

response = self.get_json('/retrivefeaturedtranslationlanguages')
self.assertEqual(
response,
{'featured_translation_languages': new_value}
)
27 changes: 27 additions & 0 deletions core/domain/config_domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,27 @@

CMD_CHANGE_PROPERTY_VALUE = 'change_property_value'

LIST_OF_FEATURED_TRANSLATION_LANGUAGES_DICTS_SCHEMA = {
'type': 'list',
'items': {
'type': 'dict',
'properties': [{
'name': 'language_code',
'schema': {
'type': 'unicode',
'validators': [{
'id': 'is_supported_audio_language_code',
}]
},
}, {
'name': 'explanation',
'schema': {
'type': 'unicode'
}
}]
}
}

SET_OF_STRINGS_SCHEMA = {
'type': 'list',
'items': {
Expand Down Expand Up @@ -345,3 +366,9 @@ def get_all_config_property_names(cls):
CLASSROOM_PAGE_IS_SHOWN = ConfigProperty(
'classroom_page_is_shown', BOOL_SCHEMA,
'Show classroom components.', False)

FEATURED_TRANSLATION_LANGUAGES = ConfigProperty(
'featured_translation_languages',
LIST_OF_FEATURED_TRANSLATION_LANGUAGES_DICTS_SCHEMA,
'Featured Translation Languages', []
)
5 changes: 5 additions & 0 deletions core/templates/components/oppia-angular-root.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ import { ExtensionTagAssemblerService } from
import { ExtractImageFilenamesFromStateService } from
// eslint-disable-next-line max-len
'pages/exploration-player-page/services/extract-image-filenames-from-state.service';
import { FeaturedTranslationLanguageObjectFactory } from
'domain/opportunity/FeaturedTranslationLanguageObjectFactory';
import { FeedbackMessageSummaryObjectFactory } from
'domain/feedback_message/FeedbackMessageSummaryObjectFactory';
import { FeedbackThreadObjectFactory } from
Expand Down Expand Up @@ -706,6 +708,7 @@ export class OppiaAngularRootComponent implements AfterViewInit {
static expressionSyntaxTreeService: ExpressionSyntaxTreeService;
static extensionTagAssemblerService: ExtensionTagAssemblerService;
static extractImageFilenamesFromStateService: ExtractImageFilenamesFromStateService;
static featuredTranslationLanguageObjectFactory: FeaturedTranslationLanguageObjectFactory;
static feedbackMessageSummaryObjectFactory: FeedbackMessageSummaryObjectFactory;
static feedbackThreadObjectFactory: FeedbackThreadObjectFactory;
static feedbackThreadSummaryObjectFactory: FeedbackThreadSummaryObjectFactory;
Expand Down Expand Up @@ -989,6 +992,7 @@ private explorationTaskObjectFactory: ExplorationTaskObjectFactory,
private expressionSyntaxTreeService: ExpressionSyntaxTreeService,
private extensionTagAssemblerService: ExtensionTagAssemblerService,
private extractImageFilenamesFromStateService: ExtractImageFilenamesFromStateService,
private featuredTranslationLanguageObjectFactory: FeaturedTranslationLanguageObjectFactory,
private feedbackMessageSummaryObjectFactory: FeedbackMessageSummaryObjectFactory,
private feedbackThreadObjectFactory: FeedbackThreadObjectFactory,
private feedbackThreadSummaryObjectFactory: FeedbackThreadSummaryObjectFactory,
Expand Down Expand Up @@ -1273,6 +1277,7 @@ private writtenTranslationsObjectFactory: WrittenTranslationsObjectFactory
OppiaAngularRootComponent.expressionSyntaxTreeService = this.expressionSyntaxTreeService;
OppiaAngularRootComponent.extensionTagAssemblerService = this.extensionTagAssemblerService;
OppiaAngularRootComponent.extractImageFilenamesFromStateService = this.extractImageFilenamesFromStateService;
OppiaAngularRootComponent.featuredTranslationLanguageObjectFactory = this.featuredTranslationLanguageObjectFactory;
OppiaAngularRootComponent.feedbackMessageSummaryObjectFactory = this.feedbackMessageSummaryObjectFactory;
OppiaAngularRootComponent.feedbackThreadObjectFactory = this.feedbackThreadObjectFactory;
OppiaAngularRootComponent.feedbackThreadSummaryObjectFactory = this.feedbackThreadSummaryObjectFactory;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// 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 Factory for creating and mutating instances of frontend
* featured translation language domain objects.
*/

import { downgradeInjectable } from '@angular/upgrade/static';
import { Injectable } from '@angular/core';

export interface IFeaturedTranslationLanguageBackendDict {
'language_code': string;
explanation: string;
}

export class FeaturedTranslationLanguage {
constructor(
readonly languageCode: string,
readonly explanation: string
) {}
}

@Injectable({
providedIn: 'root'
})
export class FeaturedTranslationLanguageObjectFactory {
createFromBackendDict(
featuredTranslationBackendDict: IFeaturedTranslationLanguageBackendDict
): FeaturedTranslationLanguage {
return new FeaturedTranslationLanguage(
featuredTranslationBackendDict.language_code,
featuredTranslationBackendDict.explanation
);
}
}

angular.module('oppia').factory(
'FeaturedTranslationLanguageObjectFactory',
downgradeInjectable(FeaturedTranslationLanguageObjectFactory));
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// 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 Tests for FeaturedTranslationLanguageObjectFactory.
*/

import { TestBed } from '@angular/core/testing';

import {
FeaturedTranslationLanguageObjectFactory,
FeaturedTranslationLanguage,
IFeaturedTranslationLanguageBackendDict
} from
'domain/opportunity/FeaturedTranslationLanguageObjectFactory';

describe('Featured Translation Language object factory', () => {
let featuredTranslationLanguageObjectFactory:
FeaturedTranslationLanguageObjectFactory = null;
let sampleFTL: FeaturedTranslationLanguage = null;

beforeEach(() => {
featuredTranslationLanguageObjectFactory = TestBed.get(
FeaturedTranslationLanguageObjectFactory);

let sampleFTLDict: IFeaturedTranslationLanguageBackendDict = {
language_code: 'en',
explanation: 'English'
};
sampleFTL = featuredTranslationLanguageObjectFactory
.createFromBackendDict(sampleFTLDict);
});

it('should correctly evaluate all the values based on backend' +
' dict', function() {
expect(sampleFTL.languageCode).toBe('en');
expect(sampleFTL.explanation).toBe('English');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,10 @@
<[$ctrl.tabsDetails[$ctrl.activeTabName].description]>
</div>
<div class="oppia-dashboard-language-container" ng-if="$ctrl.showLanguageSelector()">
<span class="oppia-dashboard-language-container-label">Translate text to:</span>
<select class="oppia-opportunity-language-selector protractor-test-language-selector"
ng-change="$ctrl.onChangeLanguage()"
ng-model="$ctrl.languageCode"
ng-options="language.id as language.description for language in $ctrl.languageCodesAndDescriptions">
</select>
<span class="oppia-dashboard-language-container-label">Translate to</span>
<translation-language-selector [active-language-code]="$ctrl.languageCode"
(set-active-language-code)="$ctrl.onChangeLanguage($event)">
</translation-language-selector>
</div>
</div>
</div>
Expand All @@ -80,23 +78,22 @@
.oppia-dashboard-language-container-label {
color: #4a4a4a;
font-size: 18px;
margin-top: 10px;
}
.oppia-dashboard-language-container {
display: flex;
flex-direction: column;
height: 80px;
margin-left: 10%;
width: 15%;
width: 250px;
}
.oppia-opportunity-language-selector {
background: white;
border: 1px solid #e8e7e3;
height: 35px;
}
.oppia-opportunities-tabs-explanation {
padding-top: 25px;
padding-top: 50px;
position: relative;
width: 40%;
}
.oppia-opportunities-tabs-explanation::before {
bottom: 65%;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,6 @@ describe('Community dashboard page', function() {
expect(ctrl.profilePictureDataUrl).toBe(userProfileImage);
});

it('should get all language codes and its descriptions', function() {
const allLanguageCodesAndDescriptionsFromConstants = (
CONSTANTS.SUPPORTED_AUDIO_LANGUAGES.map(language => ({
id: language.id,
description: language.description
})));
expect(ctrl.languageCodesAndDescriptions).toEqual(
allLanguageCodesAndDescriptionsFromConstants);
});

it('should change active tab name', function() {
var changedTab = 'translateTextTab';
expect(ctrl.activeTabName).toBe('myContributionTab');
Expand All @@ -121,7 +111,7 @@ describe('Community dashboard page', function() {
spyOn(LocalStorageService, 'updateLastSelectedTranslationLanguageCode')
.and.callThrough();

ctrl.onChangeLanguage();
ctrl.onChangeLanguage('hi');

expect(TranslationLanguageService.setActiveLanguageCode)
.toHaveBeenCalledWith('hi');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ require(
require(
'pages/community-dashboard-page/contributions-and-review/' +
'contributions-and-review.directive.ts');
require(
'pages/community-dashboard-page/translation-language-selector/' +
'translation-language-selector.component.ts');
require(
'pages/community-dashboard-page/question-opportunities/' +
'question-opportunities.directive.ts');
Expand Down Expand Up @@ -73,7 +76,8 @@ angular.module('oppia').component('communityDashboardPage', {
return languageDescriptions;
};

ctrl.onChangeLanguage = function() {
ctrl.onChangeLanguage = function(languageCode: string) {
ctrl.languageCode = languageCode;
TranslationLanguageService.setActiveLanguageCode(ctrl.languageCode);
LocalStorageService.updateLastSelectedTranslationLanguageCode(
ctrl.languageCode);
Expand Down Expand Up @@ -135,15 +139,6 @@ angular.module('oppia').component('communityDashboardPage', {
}
});

ctrl.languageCodesAndDescriptions = (
allAudioLanguageCodes.map(function(languageCode) {
return {
id: languageCode,
description: (
LanguageUtilService.getAudioLanguageDescription(
languageCode))
};
}));
ctrl.languageCode = (
allAudioLanguageCodes.indexOf(prevSelectedLanguageCode) !== -1 ?
prevSelectedLanguageCode : DEFAULT_OPPORTUNITY_LANGUAGE_CODE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ angular.module('oppia', [
'toastr', 'ui.bootstrap', 'ui.sortable', 'ui.tree', 'ui.validate'
]);

import { Component, NgModule, StaticProvider } from '@angular/core';
import { NgModule, StaticProvider } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { downgradeComponent } from '@angular/upgrade/static';
import { HttpClientModule } from '@angular/common/http';
Expand All @@ -39,6 +39,8 @@ import { OppiaAngularRootComponent } from
import { AppConstants } from 'app.constants';
import { CommunityDashboardConstants } from
'pages/community-dashboard-page/community-dashboard-page.constants';
import { TranslationLanguageSelectorComponent } from
'./translation-language-selector/translation-language-selector.component';

@NgModule({
imports: [
Expand All @@ -47,10 +49,12 @@ import { CommunityDashboardConstants } from
SharedComponentsModule
],
declarations: [
OppiaAngularRootComponent
OppiaAngularRootComponent,
TranslationLanguageSelectorComponent
],
entryComponents: [
OppiaAngularRootComponent
OppiaAngularRootComponent,
TranslationLanguageSelectorComponent
],
providers: [
AppConstants,
Expand Down
Loading

0 comments on commit 165c637

Please sign in to comment.