-
Notifications
You must be signed in to change notification settings - Fork 46
[Developers] Survey Builder current state
All the templates are in the directory frontend/templates/
.
-
edit_survey.html
is the main template. It shows the questions in the survey. There are two survey types:audio_survey
s andtracking_survey
s. We're not changing anything about audio surveys; those surveys just have a "prompt" (something telling the respondent what to say). We're only concerned with tracking surveys; those are surveys with questions that you answer on a screen. The templateedit_survey.html
also includes three other templates:-
survey_schedule.html
: you can mostly ignore this. This is the box at the top of the screen that gives options about what times of the week the survey gets asked. -
question_summary.html
: This is written in Handlebars; it provides the text representation of a question in the mainedit_survey.html
page, and the four buttons attached to each question: Edit, Delete, Move Up, and Move Down. It should be rewritten in AngularJS. -
randomize_questions.html
: This shows some checkboxes at the bottom of the screen about whether to randomize the questions in a survey. We need two changes to this:- Rewrite it to work in AngularJS instead of in Handlebars
- A survey can have either skip logic or randomized questions, but not both. This interface should reflect that. One way of doing this is to create an additional checkbox (somewhere in
edit_survey.html
) for whether the survey uses skip logic, and if that checkbox is checked, then disable the Randomize Questions checkboxes using<input disabled>
.
-
-
edit_question.html
is the template for the create/edit question popup/modal form.
All the relevant JS files are in frontend/static/javascript/survey-editor/
:
-
handlebars-question-rendering.js
This file has helper functions for turning a question data object into a text representation of the question on the main survey page. -
question-from-modal.js
You edit questions in a modal/popup (there's no inline editing).questions-from-modal.js
has functions to take the input from the modal form and turn that into a question data object. -
radiobutton-checkbox-questions.js
This file has functions for creating/editing radio button and checkbox questions in the modal/popup form. Radio button and checkbox questions are similar in that they have an arbitrary number of answers, so these functions are for increasing or decreasing the number of answer fields in the create/edit question modal. AngularJS could easily replace this functionality. -
schedule.js
You can probably ignore this file; it's all linked to the survey scheduling functionality in thesurvey_schedule.html
template. -
set-up-modal.js
Most of this file is for parsing a question data object and populating the fields in the edit question modal form. This is functionality that would probably be much cleaner to write in AngularJS. -
survey-editor.js
This file has most of the functionality for the main survey editor page (i.e., not the edit question modal/popup). It has functions to add new questions, edit questions, re-order questions, and delete questions. It also has functions to read in an entire survey when you load the page, and to export the whole survey when you click "Save and Deploy." This file references functions defined in some of the other files (for example, lines 171-172 call functionsclearModal()
andpopulateEditQuestionModal()
which are defined inset-up-modal.js
); I think it's the only JS file in this directory that references other files, but I'm not totally sure.
A survey is represented as JSON and currently stored as a string in MongoDB. Its top-level attributes are:
-
_id
: a randomly-generated, unique MongoDB ID -
content
: the list of questions. Each question has several attributes:-
question_id
: a randomly-generated ID (currently it's generated in JavaScript inquestion-from-modal.js
'sgenerateUUID()
function -
question_text
: the text that appears with the question -
question_type
: allowed values are:free_response
,checkbox
,radio_button
,slider
, andinfo_text_box
. -
text_field_type
(free_response questions only): allowed values are:NUMERIC
,SINGLE_LINE_TEXT
, andMULTI_LINE_TEXT
-
max
andmin
(slider questions only): numbers that define the bottom and top of the slider's range -
answers
(radio_button and checkbox questions only): a list of answer options for a multiple-choice question
-
-
settings
: currently, there are four attributes. None of these need to change to support skip logic, but we may need to add an additional setting that says survey skip logic is active, and which overrules therandomize
attribute:-
randomize
:True
orFalse
; ifTrue
, the survey questions should appear in random order. -
number_of_random_questions
: this only matters ifrandomize == True
. If it'sNone
, then each survey the user takes should ask all the questions in the survey. If it's set to an integer, then each survey should ask only that many questions, drawn at random from the questions in this survey. For example, you could have a 30-question survey, but each time the survey gets asked, the user only sees a random 5 of those questions. -
randomize_with_memory
:True
orFalse
- ifTrue
, then the app remembers which questions were previously asked on a survey, and asks random questions without replacement, so it will go through the 30-question survey bank in 6 survey instances until it's asked all questions, and then start over. -
trigger_on_first_download
:True
orFalse
. IfTrue
, then as soon as the app downloads this survey for the first time (usually when the user installs and registers the app), the survey will appear. IfFalse
, the survey won't appear until its first explicitly scheduled time.
-
-
survey_type
: this is set totracking_survey
for a survey with questions, oraudio_survey
for a survey with a "Record" button and a voice prompt. For this feature, we are only concerned with tracking surveys; you can ignore audio surveys. -
timings
: this is a list of the times during each week that the survey is supposed to be asked to the user. It's a list of 7 lists (one for each day of the week), and each day list is a list of integers, where each integer is the time, in seconds past midnight, that the survey is supposed to send. So for example, if you want to send a survey only once per week at 5pm on Mondays (5pm is (17 hours) * (3600 seconds/hour) = 61,200 seconds past midnight), your timings list-of-lists would look like this:[[], [61200], [], [], [], [], []]
Here is an example JSON representation of a survey:
{u'_id': ObjectId('55f34e5f73cc0a25217215ce'),
u'content': [{u'question_id': u'5a0c14a3-7e7d-45df-ff71-7af4bff518e4',
u'question_text': u'What do you most fear?',
u'question_type': u'free_response',
u'text_field_type': u'SINGLE_LINE_TEXT'},
{u'answers': [{u'text': u'Cauliflower'},
{u'text': u'Chia seeds'},
{u'text': u'More cauliflower'},
{u'text': u'Just food in general'}],
u'question_id': u'92a9a918-b8c2-4535-e017-9c7cbd399a66',
u'question_text': u'How many of these would you eat?',
u'question_type': u'checkbox'},
{u'answers': [{u'text': u'Harry Potter'},
{u'text': u'Star Trek'},
{u'text': u'Red vs. Blue'}],
u'question_id': u'325519b7-92eb-47e1-cd70-49fe25ca21a2',
u'question_text': u'OK. Which is your favorite?',
u'question_type': u'radio_button'},
{u'max': u'7',
u'min': u'1',
u'question_id': u'737c838b-3cb7-4d69-e4cc-16e90b1e4ff4',
u'question_text': u'How much do you crave Chipotle today, on a scale of 1-7?',
u'question_type': u'slider'},
{u'question_id': u'c36ded54-bf41-45de-9bfe-240845fe87c2',
u'question_text': u'This is just a piece of information- nothing to answer here. Please move on to the next question.',
u'question_type': u'info_text_box'},
{u'question_id': u'a135435a-6d0b-437d-9312-4de6f828b11f',
u'question_text': u'What do you think is the ideal number of surveys to take in a day?',
u'question_type': u'free_response',
u'text_field_type': u'NUMERIC'}],
u'settings': {u'number_of_random_questions': 3,
u'randomize': False,
u'randomize_with_memory': True,
u'trigger_on_first_download': True},
u'survey_type': u'tracking_survey',
u'timings': [[34320, 77520],
[34320, 77520],
[34320, 77520],
[34320, 77520],
[34320, 77520],
[34320, 77520],
[34320, 77520]]}
This is lower priority than supporting skip logic, but it's in the same task spec in case refactoring into AngularJS makes it easier to support skip logic.
AngularJS is already used in one piece of the repo (a search filter, code for which is in frontend/templates/navbar.html
and frontend/static/javascript/search_filter.js
). It references a copy of the AngularJS code at frontend/static/javascript/libraries/angular.min.js
.