from typing import Any
from typing import Dict
from typing import List
from typing import Union
from pydantic import BaseModel
from pydantic import Extra
from pydantic import HttpUrl
try:
from typing import Literal
except ImportError: # pragma: NO COVER
from typing_extensions import Literal
from . import settings
from .utils import get_params_for_repr
class _Base(BaseModel):
"""Base class for questions classes. Main responsibility is renaming
Python parameter names to Javascript's camelCase convention."""
def __repr__(self):
class_name = self.__class__.__name__
params = get_params_for_repr(dict(self))
return f"{class_name}({params}\n )"
class Config:
fields = {
"kind": "type",
"all_rows_required": "isAllRowRequired",
"expression_format": "format",
"max_value": "max",
"min_value": "min",
"required": "isRequired",
}
@classmethod
def fix_name(cls, name):
words = name.split("_")
name = ""
for index, word in enumerate(words):
if index == 0:
name += word
else:
name += word.capitalize()
return name
extra = Extra.allow
alias_generator = fix_name
[docs]class Validator(_Base):
"""Base class for all validators."""
kind: str
message: str = "Invalid value"
[docs]class TextValidator(Validator):
"""Validator for text input."""
kind: str = "text"
max_length: int = 0
min_length: int = 0
allow_digits: bool = True
[docs]class NumericValidator(Validator):
"""Validator for numeric input."""
kind: str = "numeric"
max_value: int = 0
min_value: int = 0
[docs]class EmailValidator(Validator):
"""Checks if a value is a valid email address."""
kind: str = "email"
[docs]class RegexValidator(Validator):
"""Checks if a value matches a regular expression."""
kind: str = "regex"
regex: str = ""
[docs]class ExpressionValidator(Validator):
"""Checks if a question's answer matches a set of conditions."""
kind: str = "regex"
expression: str = ""
[docs]class Question(_Base):
"""
Base question class. All questions share these properties, and all can be
set by passing them as parameters when instantiating the question.
"""
kind: str
name: str = ""
title: Union[str, Dict[str, str]] = ""
description: Union[str, Dict[str, str]] = ""
required: bool = False
visible: bool = True
default_value: str = ""
correct_answer: str = ""
visible_if: str = ""
enable_if: str = ""
start_with_new_line: bool = True
value_name: str = ""
required_if: str = ""
required_error_text: str = ""
hide_number: bool = True
indent: int = 0
title_location: Literal[settings.TITLE_LOCATIONS] = "default"
description_location: Literal[settings.DESCRIPTION_LOCATIONS] = "default"
width: str = ""
max_width: str = "initial"
min_width: str = "300px"
use_display_values_in_title: bool = True
validators: List[Validator] = []
extra_js: List[HttpUrl] = []
extra_css: List[HttpUrl] = []
[docs]class TextQuestion(Question):
"""
A question that uses a text input box. It can handle all HTML5 text input
types.
"""
kind: str = "text"
place_holder: Union[str, Dict[str, str]] = ""
input_type: Literal[settings.TEXT_INPUT_TYPES] = "text"
max_length: int = -1
max_value: str = ""
min_value: str = ""
size: int = 0
step: str = ""
text_update_mode: Literal[settings.TEXT_UPDATE_MODES] = "default"
input_mask: str = ""
input_format: str = ""
prefix: str = ""
auto_unmask: bool = True
extra_js: List[HttpUrl] = [
"https://unpkg.com/jquery@3.5.1/dist/jquery.js",
"https://unpkg.com/inputmask@5.0.3/dist/inputmask.js",
]
[docs]class ChoicesQuestion(Question):
"""
Base class for questions that let the user select one or more options
from a list of choices. The choices can either be set at question
instantiation time, or come from a JSON web service at run time.
"""
kind: str = ""
col_count: int = 4
choices: List[Union[str, Dict[str, Union[str, HttpUrl, Dict[str, str]]]]] = []
choices_by_url: Dict[Literal[settings.CHOICES_BY_URL_KEYS], str] = []
choices_order: Literal[settings.CHOICE_ORDER_VALUES] = "none"
choices_enable_if: str = ""
choices_visible_if: str = ""
hide_if_choices_empty: bool = True
has_other: bool = False
other_text: Union[str, Dict[str, str]] = "Other"
other_error_text: Union[str, Dict[str, str]] = ""
other_place_holder: Union[str, Dict[str, str]] = ""
[docs]class RadioGroupQuestion(ChoicesQuestion):
"""
Select one option from a group of radio buttons.
"""
kind: str = "radiogroup"
show_clear_button: bool = False
[docs]class DropdownQuestion(ChoicesQuestion):
"""
Select one option from a dropdown menu.
"""
kind: str = "dropdown"
choices_max: int = 0
choices_min: int = 0
choices_step: int = 1
options_caption: str = ""
show_options_caption: bool = True
[docs]class CheckboxQuestion(ChoicesQuestion):
"""
Select one or more options from a group of check boxes.
"""
kind: str = "checkbox"
has_none: bool = False
has_select_all: bool = False
none_text: Union[str, Dict[str, str]] = "None"
select_all_text: Union[str, Dict[str, str]] = ""
[docs]class ImagePickerQuestion(ChoicesQuestion):
"""
Display a group of images and let the user pick one or more.
"""
kind: str = "imagepicker"
content_mode: Literal[settings.IMAGE_CONTENT_MODE_VALUES] = "image"
show_label: bool = False
image_height: int = 200
image_width: int = 300
image_fit: Literal[settings.IMAGE_FIT_VALUES] = "none"
multi_select: bool = False
has_other: bool = False
other_text: Union[str, Dict[str, str]] = "Other"
other_error_text: Union[str, Dict[str, str]] = ""
other_place_holder: Union[str, Dict[str, str]] = ""
[docs]class BooleanQuestion(Question):
"""
Get the answer for any two-possibility question. Usually true/false, yes/
no questions.
"""
kind: str = "boolean"
label_true: Union[str, Dict[str, str]] = ""
label_false: Union[str, Dict[str, str]] = ""
show_title: bool = False
value_true: Union[str, Dict[str, str]] = "true"
value_false: Union[str, Dict[str, str]] = "false"
[docs]class SignaturePadQuestion(Question):
"""
Allow the user to "sign" something by drawing their signature. Can be used
to capture user drawings for other types of questions.
"""
kind: str = "signaturepad"
height: int = 200
width: int = 300
allow_clear: bool = True
[docs]class MultipleTextQuestion(Question):
"""
A text question with multiple related parts. Displays a text box for each
part.
"""
kind: str = "multipletext"
col_count: int = 2
items: List[Dict[str, str]] = []
item_size: int = 0
[docs]class RatingQuestion(Question):
"""
A question that lets the user select a number on a fixed scale.
"""
kind: str = "rating"
min_rate_description: Union[str, Dict[str, str]] = ""
max_rate_description: Union[str, Dict[str, str]] = ""
rate_max: int = 5
rate_min: int = 1
rate_step: int = 1
rate_values: List[Union[int, Dict[str, Union[int, str]]]] = []
[docs]class FileQuestion(Question):
"""
A question for uploading one or more files.
"""
kind: str = "file"
show_preview: bool = True
allow_multiple: bool = False
store_data_as_text: bool = True
image_height: int = 100
image_width: int = 150
max_size: int = 0
accepted_types: str = ""
allow_images_preview: bool = True
need_confirm_remove_file: bool = False
wait_for_upload: bool = True
[docs]class MatrixQuestion(Question):
"""
A question that displays rows of radio buttons and allows the user to
select a value from one of several columns for each row.
"""
kind: str = "matrix"
columns: List[Any]
rows: List[Any] = []
all_rows_required: bool = False
cells: Dict[str, Dict[str, str]] = {}
columns_visible_if: str = ""
rows_order: Literal[settings.ROW_ORDER_VALUES] = "initial"
rows_visible_if: str = ""
show_header: bool = True
[docs]class MatrixDropdownQuestion(Question):
"""
A matrix question that can include other types of input controls, like
dropdowns and text boxes.
"""
kind: str = "matrixdropdown"
columns: List[Any]
rows: List[Any] = []
all_rows_required: bool = False
cells: Dict[str, Dict[str, Any]] = {}
columns_visible_if: str = ""
rows_order: Literal[settings.ROW_ORDER_VALUES] = "initial"
rows_visible_if: str = ""
show_header: bool = True
cell_type: Literal[settings.MATRIX_CELL_TYPES] = "dropdown"
choices: List[Any] = []
column_col_count: int = 1
column_layout: Literal[settings.MATRIX_COLUMN_LAYOUTS] = "horizontal"
column_min_width: str = ""
horizontal_scroll: bool = False
options_caption: str = ""
row_title_width: str = ""
total_text: str = ""
[docs]class MatrixDynamicQuestion(Question):
"""
A matrix dropdown question that allows the user to add or remove new rows
from their answer.
"""
kind: str = "matrixdynamic"
columns: List[Any]
rows: List[Any] = []
all_rows_required: bool = False
cells: Dict[str, Dict[str, Any]] = {}
columns_visible_if: str = ""
rows_order: Literal[settings.ROW_ORDER_VALUES] = "initial"
rows_visible_if: str = ""
show_header: bool = True
cell_type: Literal[settings.MATRIX_CELL_TYPES] = "dropdown"
choices: List[Any] = []
column_col_count: int = 1
column_layout: Literal[settings.MATRIX_COLUMN_LAYOUTS] = "horizontal"
column_min_width: str = ""
horizontal_scroll: bool = False
options_caption: str = ""
add_row_location: Literal[settings.MATRIX_ROW_LOCATIONS] = "default"
add_row_text: str = ""
allow_add_rows: bool = True
allow_remove_rows: bool = True
confirm_delete: bool = False
confirm_delete_text: str = ""
default_row_value: Any = ""
default_value_from_last_row: bool = False
key_duplication_error: str = ""
key_name: str = ""
max_row_count: int = 100
min_row_count: int = 1
remove_row_text: str = ""
row_count: int = 1
[docs]class TagBoxQuestion(DropdownQuestion):
"""
A question that uses the Select2 tag box widget.
"""
kind: str = "tagbox"
select2_config: str = ""
extra_js: List[HttpUrl] = [
"https://unpkg.com/jquery@3.5.1/dist/jquery.js",
"https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/js/select2.min.js",
]
extra_css: List[HttpUrl] = [
"https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/css/select2.min.css",
]
[docs]class JQueryUIDatePickerQuestion(TextQuestion):
"""
A question that uses the JQueryUI date picker.
"""
kind: str = "datepicker"
date_format: str = "mm/dd/yy"
config: str = ""
max_date: str = ""
min_date: str = ""
extra_js: List[HttpUrl] = [
"https://unpkg.com/jquery@3.5.1/dist/jquery.js",
"https://code.jquery.com/ui/1.11.4/jquery-ui.min.js",
]
extra_css: List[HttpUrl] = [
"https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/smoothness/jquery-ui.css",
]
[docs]class BootstrapDatePickerQuestion(TextQuestion):
"""
A question that uses the bootstrap date picker.
"""
kind: str = "bootstrapdatepicker"
date_format: str = "mm/dd/yy"
start_date: str = ""
end_date: str = ""
today_highlight: bool = True
week_start: int = 0
clear_button: bool = False
auto_close: bool = True
days_of_week_highlighted: str = ""
disable_touch_keyboard: bool = True
extra_js: List[HttpUrl] = [
"https://unpkg.com/jquery@3.5.1/dist/jquery.js",
"https://unpkg.com/moment@2.24.0/moment.js",
"https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.js",
]
extra_css: List[HttpUrl] = [
"https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css",
"https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.min.css",
]
[docs]class Select2Question(DropdownQuestion):
"""
A question that uses the Select2 dropdown widget.
"""
render_as: str = "select2"
select2_config: str = ""
extra_js: List[HttpUrl] = [
"https://unpkg.com/jquery@3.5.1/dist/jquery.js",
"https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/js/select2.min.js",
]
extra_css: List[HttpUrl] = [
"https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/css/select2.min.css",
]
[docs]class BarRatingQuestion(DropdownQuestion):
"""
A question that uses the JQuery bar rating widget.
"""
kind: str = "barrating"
rating_theme: Literal[settings.BAR_RATING_THEMES] = "fontawesome-stars"
show_values: bool = False
extra_js: List[HttpUrl] = [
"https://unpkg.com/jquery@3.5.1/dist/jquery.js",
"https://unpkg.com/jquery-bar-rating",
]
extra_css: List[HttpUrl] = [
"https://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css",
"https://unpkg.com/jquery-bar-rating@1.2.2/dist/themes/bars-1to10.css",
"https://unpkg.com/jquery-bar-rating@1.2.2/dist/themes/bars-movie.css",
"https://unpkg.com/jquery-bar-rating@1.2.2/dist/themes/bars-pill.css",
"https://unpkg.com/jquery-bar-rating@1.2.2/dist/themes/bars-reversed.css",
"https://unpkg.com/jquery-bar-rating@1.2.2/dist/themes/bars-horizontal.css",
"https://unpkg.com/jquery-bar-rating@1.2.2/dist/themes/fontawesome-stars.css",
"https://unpkg.com/jquery-bar-rating@1.2.2/dist/themes/css-stars.css",
"https://unpkg.com/jquery-bar-rating@1.2.2/dist/themes/fontawesome-stars-o.css",
]
[docs]class SortableJSQuestion(CheckboxQuestion):
"""
A question that uses the JQuery sortable widget.
"""
kind: str = "sortablelist"
empty_text: str = ""
max_answers_count: int = -1
extra_js: List[HttpUrl] = [
"https://unpkg.com/jquery@3.5.1/dist/jquery.js",
"https://unpkg.com/sortablejs@1.7.0/Sortable.js",
]
[docs]class NoUISliderQuestion(Question):
"""
A question that uses the NoUISlider JQuery widget.
"""
kind: str = "nouislider"
step: int = 1
range_min: int = 0
range_max: int = 100
pips_mode: str = "positions"
pips_values: List[int] = [0, 25, 50, 75, 100]
pips_text: List[Union[int, str]] = [0, 25, 50, 75, 100]
pips_density: int = 5
orientation: str = "horizontal"
direction: str = "ltr"
tooltips: bool = True
extra_js: List[HttpUrl] = [
"https://unpkg.com/jquery@3.5.1/dist/jquery.js",
"https://unpkg.com/nouislider@9.2.0/distribute/nouislider.js",
"https://unpkg.com/wnumb@1.1.0",
]
extra_css: List[HttpUrl] = [
"https://unpkg.com/nouislider@9.2.0/distribute/nouislider.min.css",
]
[docs]class CKEditorQuestion(Question):
"""
A question that uses the CKEditor JQuery widget.
"""
kind: str = "editor"
height: str = "300px"
extra_js: List[HttpUrl] = [
"https://unpkg.com/jquery@3.5.1/dist/jquery.js",
"https://cdn.ckeditor.com/4.14.1/standard/ckeditor.js",
]
[docs]class BootstrapSliderQuestion(Question):
"""
A question that uses the bootstrap slider widget.
"""
kind: str = "bootstrpslider"
step: int = 1
range_min: int = 0
range_max: int = 100
extra_js: List[HttpUrl] = [
"https://unpkg.com/jquery@3.5.1/dist/jquery.js",
"https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/10.0.0/bootstrap-slider.js",
]
extra_css: List[HttpUrl] = [
"https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css",
"https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/10.0.0/css/bootstrap-slider.css",
]
[docs]class EmotionsRatingQuestion(DropdownQuestion):
"""
A question that uses the emotion ratings JQuery widget.
"""
kind: str = "emotionsratings"
emotions: List[str] = ["angry", "disappointed", "meh", "happy", "inLove"]
emotion_size: int = 30
emotions_count: int = 5
bg_emotion: str = "happy"
emotion_color: str = "FF0066"
extra_js: List[HttpUrl] = [
"https://unpkg.com/jquery@3.5.1/dist/jquery.js",
"https://unpkg.com/emotion-ratings@2.0.1/dist/emotion-ratings.js",
]
[docs]class MicrophoneQuestion(Question):
"""
A question that uses the RecordRTC sound recording widgets.
"""
kind: str = "microphone"
extra_js: List[HttpUrl] = [
"https://www.WebRTC-Experiment.com/RecordRTC.js",
]
[docs]class HtmlBlock(Question):
"""
An HTML block that can be embedded in a form.
"""
kind: str = "html"
html: Union[str, Dict[str, str]] = ""
[docs]class ImageBlock(Question):
"""
An block for inserting an image in a form.
"""
kind: str = "image"
image_height: int = 200
image_width: int = 300
image_fit: Literal[settings.IMAGE_FIT_VALUES] = "none"
image_link: HttpUrl
content_mode: Literal[settings.IMAGE_CONTENT_MODE_VALUES] = "image"
[docs]class ExpressionBlock(Question):
"""
A block that inserts the result of an expression in a form.
"""
kind: str = "expression"
expression: str
currency: str = "USD"
display_style: Literal[settings.EXPRESSION_DISPLAY_STYLES] = "none"
expression_format: str = ""
maximum_fraction_digits: int = -1
minimum_fraction_digits: int = -1
use_grouping: bool = True
[docs]class PanelBlock(Question):
"""
A form panel is a group of questions that go together. A form can contain
any number of panels, even nested.
"""
kind: str = "panel"
inner_indent: int = 1
elements: List[Question] = []
question_start_index: str = ""
question_title_location: Literal[settings.TITLE_LOCATIONS] = "default"
show_number: bool = False
show_question_numbers: Literal[settings.SHOW_QUESTION_NUMBERS_VALUES] = "default"
state: Literal[settings.PANEL_STATES] = "default"
[docs]class PanelDynamicBlock(Question):
"""
Dynamic blocks allow users to manually add or remove panels. A form can contain
any number of dynamic panels, even nested.
"""
kind: str = "paneldynamic"
inner_indent: int = 1
render_mode: Literal[settings.PANEL_RENDER_MODES] = "list"
panel_count: int = 1
panel_add_text: Union[str, Dict[str, str]] = ""
panel_remove_text: Union[str, Dict[str, str]] = ""
template_title: Union[str, Dict[str, str]] = ""
template_elements: List[Question] = []
allow_add_panel: bool = True
allow_remove_panel: bool = True
confirm_delete: bool = False
confirm_delete_text: Union[str, Dict[str, str]] = ""
default_value_from_last_panel: bool = False
key_duplication_error: Union[str, Dict[str, str]] = ""
key_name: str = ""
max_panel_count: int = 100
min_panel_count: int = 1
panel_add_text: Union[str, Dict[str, str]] = ""
panel_next_text: Union[str, Dict[str, str]] = ""
panel_prev_text: Union[str, Dict[str, str]] = ""
panel_remove_text: Union[str, Dict[str, str]] = ""
panels_state: Literal[settings.PANEL_STATES] = "default"
show_question_numbers: Literal[settings.SHOW_QUESTION_NUMBERS_VALUES] = "default"
show_range_in_progress: bool = True
template_description: Union[str, Dict[str, str]] = ""
template_title_location: Literal[settings.TITLE_LOCATIONS] = "default"
[docs]class Page(_Base):
"""
A group of questions presented as an individual form page. A form can contain
any number of pages.
"""
name: str = ""
title: Union[str, Dict[str, str]] = ""
questions: List[Question] = []
description: Union[str, Dict[str, str]] = ""
max_time_to_finish: int = 0
navigation_buttons_visibility: Literal[settings.NAV_BUTTONS_VISIBILITY] = "inherit"
question_title_location: Literal[settings.TITLE_LOCATIONS] = "default"
questions_order: Literal[settings.QUESTION_ORDER_VALUES] = "default"
[docs]class Survey(_Base):
"""
The main SurveyJS form container. Questions forms generate a survey
rendering the questions contained in a form.
"""
title: Union[str, Dict[str, str]] = ""
pages: List[Page] = []
calculated_values: List[Any] = []
check_errors_mode: Literal[settings.CHECK_ERRORS_MODES] = "onNextPage"
clear_invisible_values: Literal[settings.CLEAR_INVISIBLE_VALUES] = "onComplete"
completed_before_html: Union[str, Dict[str, str]] = ""
completed_html: Union[str, Dict[str, str]] = ""
completed_html_on_condition: List[Dict[str, str]] = []
complete_text: Union[str, Dict[str, str]] = ""
cookie_name: str = ""
description: Union[str, Dict[str, str]] = ""
edit_text: Union[str, Dict[str, str]] = ""
first_page_is_started: bool = False
focus_first_question_automatic: bool = True
focus_on_first_error: bool = True
go_next_page_automatic: bool = False
loading_html: Union[str, Dict[str, str]] = ""
locale: Literal[settings.LOCALES] = ""
logo: HttpUrl = ""
logo_fit: Literal[settings.IMAGE_FIT_VALUES] = "contain"
logo_height: int = 200
logo_position: Literal[settings.LOGO_POSITIONS] = "left"
logo_width: int = 300
max_others_length: int = 0
max_text_length: int = 0
max_time_to_finish: int = 0
mode: Literal[settings.SURVEY_MODES] = "edit"
navigate_to_url: HttpUrl = ""
navigate_to_url_on_condition: List[Dict[str, HttpUrl]] = []
page_next_text: Union[str, Dict[str, str]] = ""
page_prev_text: Union[str, Dict[str, str]] = ""
preview_text: Union[str, Dict[str, str]] = ""
progress_bar_type: Literal[settings.PROGRESS_BAR_TYPES] = "pages"
question_description_location: Literal[
settings.QUESTION_DESCRIPTION_LOCATIONS
] = "underTitle"
question_error_location: Literal[settings.QUESTION_ERROR_LOCATIONS] = "top"
questions_on_page_mode: Literal[settings.QUESTION_PAGE_MODES] = "standard"
questions_order: Literal[settings.QUESTION_ORDER_VALUES] = "initial"
question_start_index: str = ""
question_title_location: Literal[settings.TITLE_LOCATIONS] = "top"
question_title_pattern: str = "numTitleRequire"
question_title_template: str = ""
required_text: Union[str, Dict[str, str]] = "*"
send_result_on_page_next: bool = False
show_completed_page: bool = False
show_navigation_buttons: Literal[settings.NAV_BUTTONS_POSITIONS] = "bottom"
show_page_numbers: bool = True
show_page_titles: bool = True
show_prev_button: bool = True
show_preview_before_complete: Literal[settings.SHOW_PREVIEW_VALUES] = "noPreview"
show_progress_bar: Literal[settings.SHOW_PROGRESS_BAR_OPTIONS] = "off"
show_question_numbers: Literal[settings.PAGE_SHOW_QUESTION_NUMBERS_VALUES] = "on"
show_timer_panel: Literal[settings.SHOW_TIMER_VALUES] = "none"
show_timer_panel_mode: Literal[settings.SHOW_TIMER_MODES] = "all"
show_title: bool = True
start_survey_text: Union[str, Dict[str, str]] = ""
store_others_as_comment: bool = True
survey_id: str = ""
survey_post_id: str = ""
survey_show_data_saving: bool = True
text_update_mode: Literal[settings.TEXT_UPDATE_MODES] = "onBlur"
triggers: List[Any] = []
QUESTION_TYPES = [
BarRatingQuestion,
BooleanQuestion,
BootstrapDatePickerQuestion,
BootstrapSliderQuestion,
CheckboxQuestion,
CKEditorQuestion,
CommentQuestion,
DropdownQuestion,
EmotionsRatingQuestion,
FileQuestion,
ImagePickerQuestion,
JQueryUIDatePickerQuestion,
MatrixDropdownQuestion,
MatrixDynamicQuestion,
MatrixQuestion,
MicrophoneQuestion,
MultipleTextQuestion,
NoUISliderQuestion,
RadioGroupQuestion,
RatingQuestion,
Select2Question,
SignaturePadQuestion,
SortableJSQuestion,
TagBoxQuestion,
TextQuestion,
]
QUESTION_NAMES_TO_TYPES = {
"barrating": BarRatingQuestion,
"boolean": BooleanQuestion,
"bootstrapdatepicker": BootstrapDatePickerQuestion,
"bootstrapslider": BootstrapSliderQuestion,
"checkbox": CheckboxQuestion,
"editor": CKEditorQuestion,
"comment": CommentQuestion,
"dropdown": DropdownQuestion,
"emotionsratings": EmotionsRatingQuestion,
"expression": ExpressionBlock,
"file": FileQuestion,
"html": HtmlBlock,
"image": ImageBlock,
"imagepicker": ImagePickerQuestion,
"datepicker": JQueryUIDatePickerQuestion,
"matrixdropdown": MatrixDropdownQuestion,
"matrixdynamic": MatrixDynamicQuestion,
"matrix": MatrixQuestion,
"microphone": MicrophoneQuestion,
"multipletext": MultipleTextQuestion,
"nouislider": NoUISliderQuestion,
"radiogroup": RadioGroupQuestion,
"rating": RatingQuestion,
"select2": Select2Question,
"signaturepad": SignaturePadQuestion,
"sortablelist": SortableJSQuestion,
"tagbox": TagBoxQuestion,
"text": TextQuestion,
}