Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #14698: Add ability to generate X sample translation opportunities on local dev server #14889

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6a77f51
change LoadingMoreData to always equal to true at the start ngoinit, …
jimbyo Dec 1, 2021
2176f3e
fix lints
jimbyo Dec 1, 2021
e644427
fix nit
jimbyo Dec 1, 2021
70f942f
Merge branch 'develop' of https://github.com/oppia/oppia into add-laz…
jimbyo Dec 3, 2021
4797f8b
Merge branch 'develop' of https://github.com/oppia/oppia into add-laz…
jimbyo Dec 22, 2021
980929a
create opportunity generation button
jimbyo Feb 9, 2022
3a21e8b
fix lints
jimbyo Feb 9, 2022
2683a64
fix lints
jimbyo Feb 9, 2022
bf21e85
add fail cases
jimbyo Feb 9, 2022
dc06c2a
fix indent
jimbyo Feb 9, 2022
1612e9e
resolve merge conflicts
jimbyo Feb 10, 2022
1162cd4
create function _create_dummy_opportunities_with_existing_topic
jimbyo Feb 15, 2022
6219634
fix_lints
jimbyo Feb 15, 2022
46fade6
fix_lints
jimbyo Feb 15, 2022
016eac9
fix_lints
jimbyo Feb 16, 2022
4b09fb1
fix lints
jimbyo Feb 16, 2022
8db94ab
Merge branch 'develop' of https://github.com/oppia/oppia into add-laz…
jimbyo Feb 16, 2022
15de1ba
fix backend tests
jimbyo Feb 16, 2022
33a8172
refactor code
jimbyo Feb 16, 2022
777fb7d
fix lints
jimbyo Feb 16, 2022
c5b2234
resolve comments
jimbyo Feb 17, 2022
657b4f9
resolve nits
jimbyo Feb 17, 2022
710ebc3
resolve comments
jimbyo Feb 17, 2022
d312748
resolve nits
jimbyo Feb 17, 2022
6ff29c6
fix backend tests
jimbyo Feb 17, 2022
3d089a8
fix backend tests
jimbyo Feb 18, 2022
33d075d
fix backend tests
jimbyo Feb 18, 2022
2cb1e26
Add submit_suggestions checkbox and logic
jimbyo Feb 24, 2022
e34d010
replace email address in admin_test
jimbyo Feb 28, 2022
ebb4efa
Merge branch 'develop' of https://github.com/oppia/oppia into add-laz…
jimbyo Feb 28, 2022
a82a4c3
fix coverage tests
jimbyo Feb 28, 2022
d068aa1
Merge branch 'develop' of https://github.com/oppia/oppia into add-laz…
jimbyo Mar 11, 2022
d983cb5
add-lazy-loading
jimbyo Mar 11, 2022
7975dab
Merge branch 'develop' of https://github.com/oppia/oppia into add-laz…
jimbyo Mar 20, 2022
7c2542f
third pass
jimbyo Mar 21, 2022
25f86c8
fix spacing issues
jimbyo Mar 21, 2022
5f5e5d2
revert changes on _generate_dummy_explorations
jimbyo Mar 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
519 changes: 484 additions & 35 deletions core/controllers/admin.py

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions core/controllers/admin_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from core.domain import story_domain
from core.domain import story_fetchers
from core.domain import story_services
from core.domain import suggestion_services
from core.domain import topic_domain
from core.domain import topic_fetchers
from core.domain import topic_services
Expand Down Expand Up @@ -912,6 +913,76 @@ def test_revoke_super_admin_privileges_fails_for_default_admin(self):
'Cannot revoke privileges from the default super admin account')


class GenerateSampleOpportunitiesTest(test_utils.GenericTestBase):
"""Test the conditions for generation of sample opportunities."""

def setUp(self):
super(GenerateSampleOpportunitiesTest, self).setUp()
self.signup(
self.CURRICULUM_ADMIN_EMAIL, self.CURRICULUM_ADMIN_USERNAME)

def test_generate_opportunities_with_valid_number(self):
self.login(self.CURRICULUM_ADMIN_EMAIL, is_super_admin=True)
csrf_token = self.get_new_csrf_token()

self.post_json(
'/adminhandler', {
'action': 'generate_sample_opportunities',
'num_sample_ops': 8,
'num_sample_interactions_per_opportunity': 10,
'should_submit_suggestions': False

}, csrf_token=csrf_token)

translation_ops = opportunity_services.get_translation_opportunities(
'ak', None, None)
self.assertEqual(len(translation_ops[0]), 8)

self.post_json(
'/adminhandler', {
'action': 'generate_sample_opportunities',
'num_sample_ops': 2,
'num_sample_interactions_per_opportunity': 10,
'should_submit_suggestions': False

}, csrf_token=csrf_token)

translation_ops = opportunity_services.get_translation_opportunities(
'ak', None, None)
self.assertEqual(len(translation_ops[0]), 10)

def test_generate_opportunities_and_submit_suggestions(self):
self.login(self.CURRICULUM_ADMIN_EMAIL, is_super_admin=True)
csrf_token = self.get_new_csrf_token()
user_id = self.get_user_id_from_email(self.CURRICULUM_ADMIN_EMAIL)

self.post_json(
'/adminhandler', {
'action': 'generate_sample_opportunities',
'num_sample_ops': 5,
'num_sample_interactions_per_opportunity': 5,
'should_submit_suggestions': True

}, csrf_token=csrf_token)

submitted_suggestions = suggestion_services.get_submitted_suggestions(
user_id, feconf.SUGGESTION_TYPE_TRANSLATE_CONTENT)
self.assertEqual(len(submitted_suggestions), 100)

self.post_json(
'/adminhandler', {
'action': 'generate_sample_opportunities',
'num_sample_ops': 5,
'num_sample_interactions_per_opportunity': 5,
'should_submit_suggestions': True

}, csrf_token=csrf_token)

submitted_suggestions = suggestion_services.get_submitted_suggestions(
user_id, feconf.SUGGESTION_TYPE_TRANSLATE_CONTENT)
self.assertEqual(len(submitted_suggestions), 200)


class GenerateDummyExplorationsTest(test_utils.GenericTestBase):
"""Test the conditions for generation of dummy explorations."""

Expand Down
59 changes: 59 additions & 0 deletions core/templates/domain/admin/admin-backend-api.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,65 @@ describe('Admin backend api service', () => {
}
));

it('should generate sample opportunities', fakeAsync(() => {
const action = 'generate_sample_opportunities';
const numSampleOpsToGenerate = 20;
const numSampleInteractionsToGenerate = 5;
const shouldSubmitSuggestions = false;
const payload = {
action: action,
num_sample_ops: numSampleOpsToGenerate,
num_sample_interactions_per_opportunity:
numSampleInteractionsToGenerate,
should_submit_suggestions: shouldSubmitSuggestions
};

abas.generateSampleOpportunitiesAsync(
numSampleOpsToGenerate,
numSampleInteractionsToGenerate,
shouldSubmitSuggestions).then(successHandler, failHandler);

const req = httpTestingController.expectOne('/adminhandler');
expect(req.request.method).toEqual('POST');
expect(req.request.body).toEqual(payload);
req.flush(200);
flushMicrotasks();

expect(successHandler).toHaveBeenCalled();
expect(failHandler).not.toHaveBeenCalled();
}
));

it('should generate sample opportunities and submit suggestions',
fakeAsync(() => {
const action = 'generate_sample_opportunities';
const numSampleOpsToGenerate = 20;
const numSampleInteractionsToGenerate = 5;
const shouldSubmitSuggestions = true;
const payload = {
action: action,
num_sample_ops: numSampleOpsToGenerate,
num_sample_interactions_per_opportunity:
numSampleInteractionsToGenerate,
should_submit_suggestions: shouldSubmitSuggestions
};

abas.generateSampleOpportunitiesAsync(
numSampleOpsToGenerate,
numSampleInteractionsToGenerate,
shouldSubmitSuggestions).then(successHandler, failHandler);

const req = httpTestingController.expectOne('/adminhandler');
expect(req.request.method).toEqual('POST');
expect(req.request.body).toEqual(payload);
req.flush(200);
flushMicrotasks();

expect(successHandler).toHaveBeenCalled();
expect(failHandler).not.toHaveBeenCalled();
}
));

it('should handle reload exploration request failure', fakeAsync(() => {
let action = 'reload_exploration';
let explorationId = 'exp1';
Expand Down
13 changes: 13 additions & 0 deletions core/templates/domain/admin/admin-backend-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,19 @@ export class AdminBackendApiService {
});
}

async generateSampleOpportunitiesAsync(
numSampleOpsToGenerate: number,
numSampleInteractionsToGenerate: number,
shouldSubmitSuggestions: boolean): Promise<void> {
return this._postRequestAsync(AdminPageConstants.ADMIN_HANDLER_URL, {
action: 'generate_sample_opportunities',
num_sample_ops: numSampleOpsToGenerate,
num_sample_interactions_per_opportunity:
numSampleInteractionsToGenerate,
should_submit_suggestions: shouldSubmitSuggestions
});
}

async reloadExplorationAsync(explorationId: string):
Promise<void> {
return this._postRequestAsync(AdminPageConstants.ADMIN_HANDLER_URL, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,38 @@ <h3>Generate dummy explorations</h3>
</div>
</mat-card>

<mat-card class="oppia-page-card oppia-long-text oppia-long-text-card">
<div class="container">
<h3>Generate sample translation opportunities</h3>
<p>
Use this form to generate sample translation opportunities with random interactions.
</p>
<span class="row">
<label for="label-target-opportunities-to-generate">Number of opportunities to generate</label>
<input class="form-control form-inline oppia-form-inline"
[(ngModel)]="numSampleOpsToGenerate"
placeholder="Opportunities to generate" type="number" min="0"
id="label-target-opportunities-to-generate">
<label for="label-target-interactions-to-generate">Number of interactions to generate</label>
<input class="form-control form-inline oppia-form-inline"
[(ngModel)]="numSampleInteractionsToGenerate"
placeholder="Interactions to generate" type="number" min="0"
id="label-target-interactions-to-generate">
<label class="oppia-submit-suggestions" for="label-target-submit-suggestions">Submit suggestions </label>
<input class="oppia-checkbox-inline"
type="checkbox"
id="label-target-submit-suggestions"
[(ngModel)]="shouldSubmitSuggestions">
<button type="button"
class="btn btn-primary oppia-generate-opportunity-text"
(click)="generateSampleOpportunities()"
[disabled]="!numSampleOpsToGenerate || !numSampleInteractionsToGenerate">
Generate Opportunities
</button>
</span>
</div>
</mat-card>

<mat-card class="oppia-page-card oppia-long-text oppia-long-text-card">
<div class="container ml-0">
<h3>Reload a single collection</h3>
Expand Down Expand Up @@ -128,10 +160,21 @@ <h3>Generate dummy skill with questions (only admins)</h3>
.admin-dev-mode-activities-tab .oppia-form-inline {
margin-bottom: 5px;
}
.admin-dev-mode-activities-tab .oppia-submit-suggestions {
margin-right: 5px;
}
.admin-dev-mode-activities-tab .oppia-publish-exploration-text {
font-size: smaller;
}
.admin-dev-mode-activities-tab .oppia-generate-exploration-text {
margin-top: 20px;
margin-top: 30px;
}

.admin-dev-mode-activities-tab .oppia-checkbox-inline {
margin-top: 5px;
}

.admin-dev-mode-activities-tab .oppia-generate-opportunity-text {
margin-top: 30px;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,71 @@ describe('Admin dev mode activities tab', () => {
expect(adminBackendSpy).not.toHaveBeenCalled();
});

it('should generate sample opportunities', async(() => {
component.numSampleOpsToGenerate = 20;
component.numSampleInteractionsToGenerate = 10;
component.shouldSubmitSuggestions = false;

spyOn(adminBackendApiService, 'generateSampleOpportunitiesAsync')
.and.returnValue(Promise.resolve());
spyOn(component.setStatusMessage, 'emit');

component.generateSampleOpportunities();
component.generateSampleOpportunities();

expect(component.setStatusMessage.emit)
.toHaveBeenCalledWith('Processing...');

fixture.whenStable().then(() => {
expect(component.setStatusMessage.emit).toHaveBeenCalledWith(
'Sample opportunities generated successfully.');
});
}));

it('should generate sample opportunities and submit suggestions',
async(() => {
component.numSampleOpsToGenerate = 5;
component.numSampleInteractionsToGenerate = 5;
component.shouldSubmitSuggestions = true;

spyOn(adminBackendApiService, 'generateSampleOpportunitiesAsync')
.and.returnValue(Promise.resolve());
spyOn(component.setStatusMessage, 'emit');

component.generateSampleOpportunities();
component.generateSampleOpportunities();

expect(component.setStatusMessage.emit)
.toHaveBeenCalledWith('Processing...');

fixture.whenStable().then(() => {
expect(component.setStatusMessage.emit).toHaveBeenCalledWith(
'Sample opportunities generated successfully.');
});
}));

it('should show error message when sample opportunities' +
'are not generated', async(() => {
component.numSampleOpsToGenerate = 2;
component.numSampleInteractionsToGenerate = 5;
component.shouldSubmitSuggestions = false;

spyOn(adminBackendApiService, 'generateSampleOpportunitiesAsync')
.and.returnValue(Promise.reject('Sample opportunities not generated.'));
spyOn(component.setStatusMessage, 'emit');

component.generateSampleOpportunities();
component.generateSampleOpportunities();

expect(component.setStatusMessage.emit)
.toHaveBeenCalledWith('Processing...');

fixture.whenStable().then(() => {
expect(component.setStatusMessage.emit).toHaveBeenCalledWith(
'Server error: Sample opportunities not generated.');
});
}));

it('should generate dummy explorations', async(() => {
component.numDummyExpsToPublish = 1;
component.numDummyExpsToGenerate = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ export class AdminDevModeActivitiesTabComponent implements OnInit {
demoExplorationIds: string[] = [];
numDummyExpsToPublish: number = 0;
numDummyExpsToGenerate: number = 0;
numSampleOpsToGenerate: number = 0;
numSampleInteractionsToGenerate: number = 0;
shouldSubmitSuggestions: boolean = false;
DEMO_COLLECTIONS: string[][] = [[]];
DEMO_EXPLORATIONS: string[][] = [[]];

Expand Down Expand Up @@ -141,6 +144,23 @@ export class AdminDevModeActivitiesTabComponent implements OnInit {
this.adminTaskManagerService.finishTask();
}

generateSampleOpportunities(): void {
this.adminTaskManagerService.startTask();
this.setStatusMessage.emit('Processing...');
this.adminBackendApiService.generateSampleOpportunitiesAsync(
this.numSampleOpsToGenerate,
this.numSampleInteractionsToGenerate,
this.shouldSubmitSuggestions
).then(() => {
this.setStatusMessage.emit(
'Sample opportunities generated successfully.');
}, (errorResponse) => {
this.setStatusMessage.emit(
'Server error: ' + errorResponse);
});
this.adminTaskManagerService.finishTask();
}

loadNewStructuresData(): void {
this.adminTaskManagerService.startTask();
this.setStatusMessage.emit('Processing...');
Expand Down