Skip to content

Commit 267a9b8

Browse files
authored
Make Poll and Survey Indexable (#81)
1 parent d56dd83 commit 267a9b8

File tree

5 files changed

+125
-3
lines changed

5 files changed

+125
-3
lines changed

poll/poll.py

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
from xblockutils.resources import ResourceLoader
4242
from xblockutils.settings import ThemableXBlockMixin, XBlockWithSettingsMixin
4343

44-
from .utils import DummyTranslationService, _
44+
from .utils import DummyTranslationService, _, remove_markdown_and_html_tags
4545

4646
try:
4747
# pylint: disable=import-error, bad-option-value, ungrouped-imports
@@ -840,6 +840,41 @@ def generate_report_data(self, user_state_iterator, limit_responses=None):
840840
count += 1
841841
yield (user_state.username, report)
842842

843+
def index_dictionary(self):
844+
"""
845+
Return dictionary prepared with module content and type for indexing.
846+
"""
847+
# return key/value fields in a Python dict object
848+
# values may be numeric / string or dict
849+
# default implementation is an empty dict
850+
xblock_body = super(PollBlock, self).index_dictionary()
851+
answers = {
852+
"option_{}".format(answer_i): remove_markdown_and_html_tags(answer[1]['label'])
853+
for answer_i, answer in enumerate(self.answers)
854+
if len(answer) == 2 and 'label' in answer[1] and answer[1]['label']
855+
}
856+
image_alt_text = {
857+
"image_alt_{}".format(answer_i): answer[1]['img_alt']
858+
for answer_i, answer in enumerate(self.answers)
859+
if len(answer) == 2 and 'img_alt' in answer[1] and answer[1]['img_alt']
860+
}
861+
862+
index_body = {
863+
"display_name": self.display_name,
864+
"question": remove_markdown_and_html_tags(self.question),
865+
}
866+
index_body.update(answers)
867+
index_body.update(image_alt_text)
868+
869+
if "content" in xblock_body:
870+
xblock_body["content"].update(index_body)
871+
else:
872+
xblock_body["content"] = index_body
873+
874+
xblock_body["content_type"] = "Poll"
875+
876+
return xblock_body
877+
843878

844879
@XBlock.wants('settings')
845880
@XBlock.needs('i18n')
@@ -1357,3 +1392,44 @@ def generate_report_data(self, user_state_iterator, limit_responses=None):
13571392
}
13581393
count += 1
13591394
yield (user_state.username, report)
1395+
1396+
def index_dictionary(self):
1397+
"""
1398+
Return dictionary prepared with module content and type for indexing.
1399+
"""
1400+
# return key/value fields in a Python dict object
1401+
# values may be numeric / string or dict
1402+
# default implementation is an empty dict
1403+
xblock_body = super(SurveyBlock, self).index_dictionary()
1404+
1405+
questions = {
1406+
"question_{}".format(question_i): remove_markdown_and_html_tags(question[1]['label'])
1407+
for question_i, question in enumerate(self.questions)
1408+
if len(question) == 2 and 'label' in question[1] and question[1]['label']
1409+
}
1410+
answers = {
1411+
"option_{}".format(answer_i): remove_markdown_and_html_tags(answer[1])
1412+
for answer_i, answer in enumerate(self.answers)
1413+
if len(answer) == 2 and answer[1]
1414+
}
1415+
image_alt_text = {
1416+
"image_alt_{}".format(question_i): question[1]['img_alt']
1417+
for question_i, question in enumerate(self.questions)
1418+
if len(question) == 2 and 'img_alt' in question[1] and question[1]['img_alt']
1419+
}
1420+
1421+
index_body = {
1422+
"display_name": self.display_name,
1423+
}
1424+
index_body.update(questions)
1425+
index_body.update(answers)
1426+
index_body.update(image_alt_text)
1427+
1428+
if "content" in xblock_body:
1429+
xblock_body["content"].update(index_body)
1430+
else:
1431+
xblock_body["content"] = index_body
1432+
1433+
xblock_body["content_type"] = "Survey"
1434+
1435+
return xblock_body

poll/utils.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# -*- coding: utf-8 -*-
22
#
3+
from bleach.sanitizer import Cleaner
4+
from markdown import markdown
35

46

57
# Make '_' a no-op so we can scrape strings
@@ -12,6 +14,17 @@ def ngettext_fallback(text_singular, text_plural, number):
1214
return text_singular if number == 1 else text_plural
1315

1416

17+
def remove_html_tags(data):
18+
""" Remove html tags from provided data """
19+
cleaner = Cleaner(tags=[], strip=True)
20+
return cleaner.clean(data)
21+
22+
23+
def remove_markdown_and_html_tags(data):
24+
""" Remove both markdown and html tags from provided data """
25+
return remove_html_tags(markdown(data))
26+
27+
1528
class DummyTranslationService(object): # pylint: disable=bad-option-value
1629
"""
1730
Dummy drop-in replacement for i18n XBlock service

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ markdown
33
ddt
44
mock
55
django-nose==1.4.6
6+
bleach==3.1.5
67
-e .

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def package_data(pkg, roots):
4646

4747
setup(
4848
name='xblock-poll',
49-
version='1.9.10',
49+
version='1.10.0',
5050
description='An XBlock for polling users.',
5151
packages=[
5252
'poll',
@@ -56,6 +56,7 @@ def package_data(pkg, roots):
5656
'markdown',
5757
'ddt',
5858
'mock',
59+
'bleach',
5960
],
6061
entry_points={
6162
'xblock.v1': [

tests/unit/test_xblock_poll.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,21 @@ def test_generate_report_data_limit_responses(self):
114114
report_data = list(report_data)
115115
self.assertEqual(len(report_data), 0)
116116

117-
117+
def test_indexing(self):
118+
self.assertEqual(
119+
self.poll_block.index_dictionary(),
120+
{
121+
'content': {
122+
'display_name': 'My Poll',
123+
'question': 'What is your favorite color?',
124+
'option_0': 'Red',
125+
'option_1': 'Blue',
126+
'option_2': 'Green',
127+
'option_3': 'Other',
128+
},
129+
'content_type': 'Poll'
130+
}
131+
)
118132
class TestSurveyBlock(unittest.TestCase):
119133
"""
120134
Tests for XBlock Survey.
@@ -270,3 +284,20 @@ def test_generate_report_data_limit_responses(self):
270284
report_data = self.survey_block.generate_report_data(user_states, limit_responses=0)
271285
report_data = list(report_data)
272286
self.assertEqual(len(report_data), 0)
287+
288+
def test_indexing(self):
289+
self.assertEqual(
290+
self.survey_block.index_dictionary(),
291+
{
292+
'content': {
293+
'display_name': 'My Survey',
294+
'question_0': 'Are you enjoying the course?',
295+
'question_1': 'Would you recommend this course to your friends?',
296+
'question_2': 'Do you think you will learn a lot?',
297+
'option_0': 'Yes',
298+
'option_1': 'No',
299+
'option_2': 'Maybe',
300+
},
301+
'content_type': 'Survey'
302+
}
303+
)

0 commit comments

Comments
 (0)