quby 4.0.4 → 5.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/quby/questionnaires.rb +1 -0
- data/lib/quby/questionnaires/api.rb +5 -1
- data/lib/quby/questionnaires/deserializer.rb +433 -0
- data/lib/quby/questionnaires/dsl.rb +10 -15
- data/lib/quby/questionnaires/entities.rb +1 -0
- data/lib/quby/questionnaires/entities/charting/line_chart.rb +23 -0
- data/lib/quby/questionnaires/entities/charting/overview_chart.rb +3 -1
- data/lib/quby/questionnaires/entities/definition.rb +3 -5
- data/lib/quby/questionnaires/entities/fields.rb +0 -15
- data/lib/quby/questionnaires/entities/question.rb +9 -32
- data/lib/quby/questionnaires/entities/questionnaire.rb +4 -15
- data/lib/quby/questionnaires/entities/questions/checkbox_question.rb +0 -24
- data/lib/quby/questionnaires/entities/questions/date_question.rb +0 -8
- data/lib/quby/questionnaires/entities/score_calculation.rb +36 -3
- data/lib/quby/questionnaires/repos.rb +1 -0
- data/lib/quby/questionnaires/repos/bundle_disk_repo.rb +51 -0
- data/lib/quby/version.rb +1 -1
- data/spec/internal/log/test-events.log +0 -451
- data/spec/internal/log/test.log +0 -18003
- data/spec/quby/answers/services/answer_validations_spec.rb +8 -8
- data/spec/quby/questionnaires/deserializer/questionnaire_spec.rb +237 -0
- data/spec/quby/questionnaires/dsl_spec.rb +0 -9
- data/spec/quby/questionnaires/entities/fields_spec.rb +3 -3
- data/spec/quby/questionnaires/entities/question_spec.rb +0 -8
- data/spec/quby/questionnaires/entities/questionnaire_spec.rb +2 -26
- data/spec/quby/table_backend/range_tree_spec.rb +7 -0
- data/spec/spec_helper.rb +1 -0
- metadata +22 -139
- data/lib/quby/questionnaires/dsl/base.rb +0 -20
- data/lib/quby/questionnaires/dsl/calls_custom_methods.rb +0 -29
- data/lib/quby/questionnaires/dsl/charting/bar_chart_builder.rb +0 -18
- data/lib/quby/questionnaires/dsl/charting/chart_builder.rb +0 -91
- data/lib/quby/questionnaires/dsl/charting/line_chart_builder.rb +0 -57
- data/lib/quby/questionnaires/dsl/charting/overview_chart_builder.rb +0 -31
- data/lib/quby/questionnaires/dsl/charting/radar_chart_builder.rb +0 -18
- data/lib/quby/questionnaires/dsl/helpers.rb +0 -51
- data/lib/quby/questionnaires/dsl/panel_builder.rb +0 -80
- data/lib/quby/questionnaires/dsl/question_builder.rb +0 -40
- data/lib/quby/questionnaires/dsl/questionnaire_builder.rb +0 -260
- data/lib/quby/questionnaires/dsl/questions/base.rb +0 -179
- data/lib/quby/questionnaires/dsl/questions/checkbox_question_builder.rb +0 -20
- data/lib/quby/questionnaires/dsl/questions/date_question_builder.rb +0 -18
- data/lib/quby/questionnaires/dsl/questions/deprecated_question_builder.rb +0 -18
- data/lib/quby/questionnaires/dsl/questions/float_question_builder.rb +0 -21
- data/lib/quby/questionnaires/dsl/questions/integer_question_builder.rb +0 -21
- data/lib/quby/questionnaires/dsl/questions/radio_question_builder.rb +0 -20
- data/lib/quby/questionnaires/dsl/questions/select_question_builder.rb +0 -18
- data/lib/quby/questionnaires/dsl/questions/string_question_builder.rb +0 -20
- data/lib/quby/questionnaires/dsl/questions/text_question_builder.rb +0 -22
- data/lib/quby/questionnaires/dsl/score_builder.rb +0 -22
- data/lib/quby/questionnaires/dsl/standardized_panel_generators.rb +0 -33
- data/lib/quby/questionnaires/dsl/table_builder.rb +0 -48
- data/lib/quby/questionnaires/services/definition_validator.rb +0 -298
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-21-57.510.html +0 -1
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-21-57.510.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-23-56.006.html +0 -1
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-23-56.006.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-24-43.842.html +0 -12
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-24-43.842.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-25-04.631.html +0 -12
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-25-04.631.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-25-11.690.html +0 -12
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-25-11.690.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-26-25.111.html +0 -12
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-26-25.111.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-26-57.026.html +0 -12
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-26-57.026.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-27-13.545.html +0 -12
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-27-13.545.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-27-45.475.html +0 -12
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-27-45.475.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-32-13.907.html +0 -1
- data/spec/internal/tmp/capybara/screenshot_2020-10-27-18-32-13.907.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-16-31.954.html +0 -207
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-16-31.954.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-16-59.938.html +0 -323
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-16-59.938.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-08.700.html +0 -323
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-08.700.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-11.550.html +0 -323
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-11.550.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-14.413.html +0 -323
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-14.413.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-17.275.html +0 -323
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-17.275.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-20.191.html +0 -323
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-20.191.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-23.042.html +0 -323
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-23.042.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-25.927.html +0 -323
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-25.927.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-28.735.html +0 -323
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-17-28.735.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-40-20.422.html +0 -1
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-40-20.422.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-40-20.738.html +0 -1
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-40-20.738.png +0 -0
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-41-16.971.html +0 -207
- data/spec/internal/tmp/capybara/screenshot_2020-11-04-13-41-16.971.png +0 -0
- data/spec/quby/questionnaires/dsl/calls_custom_methods_spec.rb +0 -38
- data/spec/quby/questionnaires/dsl/charting/bar_chart_builder_spec.rb +0 -41
- data/spec/quby/questionnaires/dsl/charting/chart_builder_spec.rb +0 -127
- data/spec/quby/questionnaires/dsl/charting/line_chart_builder_spec.rb +0 -66
- data/spec/quby/questionnaires/dsl/charting/radar_chart_builder_spec.rb +0 -41
- data/spec/quby/questionnaires/dsl/helpers_spec.rb +0 -80
- data/spec/quby/questionnaires/dsl/questionnaire_builder_spec.rb +0 -480
- data/spec/quby/questionnaires/services/definition_validator_spec.rb +0 -793
- data/spec/support/examples_for_chart_builders.rb +0 -59
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d344a78d772e4e8e4453a3c698152243750e60bc7a89e2e13c6f4d1cd68b334
|
4
|
+
data.tar.gz: acd71c1add05e591048ddd0fae1e658fb3a2e32d3b04c886bb9566c0754de09b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ec1ef22216c6c83a8313cf7e98d499de62774677dc00d3b79543f5607e0e935d841fe5293f0d4babf1c45f26843c61d0fb436b6d4bb96c72ac47807061ae650
|
7
|
+
data.tar.gz: c269f585150a10d2e27dc96cb22350f54b3f1ed73222b68cb1191d437d399145acdae18cf42f07674c2fb6ac37bb97930497a24c34c7b730d4fd0f5160ad26b1
|
data/lib/quby/questionnaires.rb
CHANGED
@@ -39,7 +39,11 @@ module Quby
|
|
39
39
|
|
40
40
|
def build_from_definition(definition)
|
41
41
|
ActiveSupport::Notifications.instrument('quby.questionaire.build') do
|
42
|
-
|
42
|
+
if definition.json
|
43
|
+
DSL.from_json(definition.json)
|
44
|
+
else
|
45
|
+
DSL.build_from_definition(definition)
|
46
|
+
end
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
@@ -0,0 +1,433 @@
|
|
1
|
+
module Quby
|
2
|
+
module Questionnaires
|
3
|
+
module Deserializer
|
4
|
+
# This symbolizes various things. Do not run on arbitrary JSON.
|
5
|
+
def self.from_json(json)
|
6
|
+
# TODO: last_update
|
7
|
+
Entities::Questionnaire.new(json.fetch("key"), json).tap do |questionnaire|
|
8
|
+
questionnaire.title = json.fetch("title")
|
9
|
+
questionnaire.description = json.fetch("description")
|
10
|
+
questionnaire.outcome_description = json.fetch("outcome_description")
|
11
|
+
questionnaire.short_description = json.fetch("short_description")
|
12
|
+
questionnaire.abortable = json.fetch("abortable")
|
13
|
+
questionnaire.enable_previous_questionnaire_button = json.fetch("enable_previous_questionnaire_button")
|
14
|
+
questionnaire.default_answer_value = json.fetch("default_answer_value")
|
15
|
+
questionnaire.leave_page_alert = json.fetch("leave_page_alert")
|
16
|
+
questionnaire.allow_hotkeys = json.fetch("allow_hotkeys")
|
17
|
+
questionnaire.license = json.fetch("license").try(:to_sym)
|
18
|
+
questionnaire.licensor = json.fetch("licensor")
|
19
|
+
questionnaire.language = json.fetch("language").try(:to_sym)
|
20
|
+
questionnaire.renderer_version = json.fetch("renderer_version")
|
21
|
+
questionnaire.last_update = json.fetch("last_update")
|
22
|
+
questionnaire.last_author = json.fetch("last_author")
|
23
|
+
questionnaire.extra_css = json.fetch("extra_css")
|
24
|
+
questionnaire.allow_switch_to_bulk = json.fetch("allow_switch_to_bulk")
|
25
|
+
|
26
|
+
questionnaire.flags = json.fetch("flags").with_indifferent_access.transform_values do |attrs|
|
27
|
+
build_flag(attrs)
|
28
|
+
end
|
29
|
+
|
30
|
+
questionnaire.textvars = json.fetch("textvars").with_indifferent_access.transform_values do |attrs|
|
31
|
+
build_textvar(attrs)
|
32
|
+
end
|
33
|
+
|
34
|
+
questionnaire.lookup_tables = YAML.load(json.fetch("lookup_tables")).transform_values do |attrs|
|
35
|
+
Quby::TableBackend::RangeTree.new(levels: attrs[:levels], tree: attrs[:tree])
|
36
|
+
end
|
37
|
+
|
38
|
+
questionnaire.score_calculations = json.fetch("score_calculations").with_indifferent_access.transform_values do |attrs|
|
39
|
+
build_score_calculation(attrs)
|
40
|
+
end
|
41
|
+
|
42
|
+
questionnaire.score_schemas = json.fetch("score_schemas").with_indifferent_access.transform_values do |schema|
|
43
|
+
build_score_schema(schema)
|
44
|
+
end
|
45
|
+
|
46
|
+
json.fetch("panels").each do |panel_json|
|
47
|
+
load_panel(questionnaire, panel_json)
|
48
|
+
end
|
49
|
+
|
50
|
+
# roqua domain
|
51
|
+
questionnaire.roqua_keys = json.fetch("roqua_keys")
|
52
|
+
questionnaire.sbg_key = json.fetch("sbg_key")
|
53
|
+
questionnaire.sbg_domains = json.fetch("sbg_domains").map(&:symbolize_keys)
|
54
|
+
questionnaire.outcome_regeneration_requested_at = json.fetch("outcome_regeneration_requested_at").try { |str| Time.zone.parse(str) }
|
55
|
+
questionnaire.deactivate_answers_requested_at = json.fetch("deactivate_answers_requested_at").try { |str| Time.zone.parse(str) }
|
56
|
+
questionnaire.respondent_types = json.fetch("respondent_types").map(&:to_sym)
|
57
|
+
questionnaire.tags = json.fetch("tags")
|
58
|
+
|
59
|
+
if overview_json = json.fetch("charts").fetch("overview")
|
60
|
+
questionnaire.charts.overview = Quby::Questionnaires::Entities::Charting::OverviewChart.new(
|
61
|
+
subscore: overview_json.fetch("subscore").to_sym,
|
62
|
+
y_max: overview_json.fetch("y_max"),
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
json.fetch("charts").fetch("others").each do |chart_json|
|
67
|
+
questionnaire.add_chart(build_chart(questionnaire, chart_json))
|
68
|
+
end
|
69
|
+
|
70
|
+
questionnaire.outcome_tables = json.fetch("outcome_tables").map do |attributes|
|
71
|
+
build_outcome_table(questionnaire, attributes)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.load_panel(questionnaire, panel_json)
|
77
|
+
panel = Entities::Panel.new(
|
78
|
+
questionnaire: questionnaire,
|
79
|
+
key: panel_json.fetch("key"),
|
80
|
+
title: panel_json.fetch("title"),
|
81
|
+
items: []
|
82
|
+
)
|
83
|
+
|
84
|
+
panel_json.fetch("items").each do |item_json|
|
85
|
+
panel.items << load_item(questionnaire, item_json, panel: panel)
|
86
|
+
end
|
87
|
+
|
88
|
+
questionnaire.add_panel(panel)
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.load_item(questionnaire, item_json, panel: nil)
|
92
|
+
case item_json.fetch("type")
|
93
|
+
when "text"
|
94
|
+
build_text(item_json)
|
95
|
+
when "question"
|
96
|
+
question = build_question(questionnaire, item_json)
|
97
|
+
questionnaire.register_question(question)
|
98
|
+
question
|
99
|
+
when "table"
|
100
|
+
table = Entities::Table.new(
|
101
|
+
title: item_json.fetch("title"),
|
102
|
+
description: item_json.fetch("description"),
|
103
|
+
columns: item_json.fetch("columns"),
|
104
|
+
show_option_desc: item_json.fetch("show_option_desc"),
|
105
|
+
)
|
106
|
+
|
107
|
+
item_json.fetch("items").each do |table_item_json|
|
108
|
+
case table_item_json.fetch("type")
|
109
|
+
when "text"
|
110
|
+
table.items << build_text(table_item_json)
|
111
|
+
when "question"
|
112
|
+
question = build_question(questionnaire, table_item_json, table: table)
|
113
|
+
questionnaire.register_question(question)
|
114
|
+
table.items << question
|
115
|
+
panel.items << question
|
116
|
+
else
|
117
|
+
raise "Unknown table item: #{table_item_json}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
table
|
122
|
+
else
|
123
|
+
raise "Unknown item: #{item_json}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.build_text(item_json)
|
128
|
+
Entities::Text.new(item_json.fetch("str"), {
|
129
|
+
html_content: item_json.fetch("html_content"),
|
130
|
+
display_in: item_json.fetch("display_in").map(&:to_sym),
|
131
|
+
col_span: item_json.fetch("col_span"),
|
132
|
+
row_span: item_json.fetch("row_span"),
|
133
|
+
raw_content: item_json.fetch("raw_content"),
|
134
|
+
switch_cycle: item_json.fetch("switch_cycle")
|
135
|
+
})
|
136
|
+
end
|
137
|
+
|
138
|
+
def self.build_question(questionnaire, item_json, parent: nil, table: nil)
|
139
|
+
key = item_json.fetch("key").to_sym
|
140
|
+
attributes = {
|
141
|
+
questionnaire: questionnaire,
|
142
|
+
parent: parent,
|
143
|
+
type: item_json.fetch("question_type").to_sym,
|
144
|
+
title: item_json.fetch("title"),
|
145
|
+
context_free_title: item_json.fetch("context_free_title"),
|
146
|
+
description: item_json.fetch("description"),
|
147
|
+
presentation: item_json.fetch("presentation").to_sym,
|
148
|
+
hidden: item_json.fetch("hidden"),
|
149
|
+
depends_on: item_json.fetch("depends_on")&.map(&:to_sym),
|
150
|
+
default_position: item_json.fetch("default_position"),
|
151
|
+
validations: item_json.fetch("validations").map {|attrs| build_question_validation(attrs)},
|
152
|
+
table: table,
|
153
|
+
|
154
|
+
# only selectable via options passed in DSL, not via DSL methods
|
155
|
+
# many apply only to certain types of questions
|
156
|
+
sbg_key: item_json.fetch("sbg_key"),
|
157
|
+
allow_duplicate_option_values: item_json.fetch("allow_duplicate_option_values"),
|
158
|
+
allow_blank_titles: item_json.fetch("allow_blank_titles"),
|
159
|
+
as: item_json.fetch("as")&.to_sym,
|
160
|
+
display_modes: item_json.fetch("display_modes")&.map(&:to_sym),
|
161
|
+
autocomplete: item_json.fetch("autocomplete"),
|
162
|
+
show_values: item_json.fetch("show_values").to_sym,
|
163
|
+
deselectable: item_json.fetch("deselectable"),
|
164
|
+
disallow_bulk: item_json.fetch("disallow_bulk"),
|
165
|
+
score_header: item_json.fetch("score_header").to_sym,
|
166
|
+
sets_textvar: item_json.fetch("sets_textvar"),
|
167
|
+
default_invisible: item_json.fetch("default_invisible"),
|
168
|
+
question_group: item_json.fetch("question_group"), # sometimes string, sometimes a symbol in the DSL. Just have to hope this works
|
169
|
+
group_minimum_answered: item_json.fetch("group_minimum_answered"),
|
170
|
+
group_maximum_answered: item_json.fetch("group_maximum_answered"),
|
171
|
+
value_tooltip: item_json.fetch("value_tooltip"),
|
172
|
+
|
173
|
+
# might be able to deduce from tree structure
|
174
|
+
parent_option_key: item_json.fetch("parent_option_key")&.to_sym
|
175
|
+
}
|
176
|
+
|
177
|
+
case item_json.fetch("question_type")
|
178
|
+
when "check_box"
|
179
|
+
Entities::Questions::CheckboxQuestion.new(key, attributes.merge(
|
180
|
+
check_all_option: item_json.fetch("check_all_option")&.to_sym,
|
181
|
+
uncheck_all_option: item_json.fetch("uncheck_all_option")&.to_sym,
|
182
|
+
maximum_checked_allowed: item_json.fetch("maximum_checked_allowed"),
|
183
|
+
minimum_checked_required: item_json.fetch("minimum_checked_required"),
|
184
|
+
)).tap do |question|
|
185
|
+
item_json.fetch("options").each do |option_json|
|
186
|
+
question.options << build_option(questionnaire, question, option_json)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
when "date"
|
190
|
+
Entities::Questions::DateQuestion.new(key, attributes.merge(
|
191
|
+
components: item_json.fetch("components").map(&:to_sym),
|
192
|
+
required_components: item_json.fetch("required_components").map(&:to_sym),
|
193
|
+
year_key: item_json.fetch("year_key")&.to_sym,
|
194
|
+
month_key: item_json.fetch("month_key")&.to_sym,
|
195
|
+
day_key: item_json.fetch("day_key")&.to_sym,
|
196
|
+
hour_key: item_json.fetch("hour_key")&.to_sym,
|
197
|
+
minute_key: item_json.fetch("minute_key")&.to_sym,
|
198
|
+
))
|
199
|
+
when "deprecated", "hidden"
|
200
|
+
Entities::Questions::DeprecatedQuestion.new(key, attributes).tap do |question|
|
201
|
+
item_json.fetch("options").each do |option_json|
|
202
|
+
question.options << build_option(questionnaire, question, option_json)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
when "float"
|
206
|
+
Entities::Questions::FloatQuestion.new(key, attributes.merge(
|
207
|
+
labels: item_json.fetch("labels"),
|
208
|
+
unit: item_json.fetch("unit"),
|
209
|
+
size: item_json.fetch("size"),
|
210
|
+
))
|
211
|
+
when "integer"
|
212
|
+
Entities::Questions::IntegerQuestion.new(key, attributes.merge(
|
213
|
+
labels: item_json.fetch("labels"),
|
214
|
+
unit: item_json.fetch("unit"),
|
215
|
+
size: item_json.fetch("size"),
|
216
|
+
))
|
217
|
+
when "radio", "scale"
|
218
|
+
Entities::Questions::RadioQuestion.new(key, attributes).tap do |question|
|
219
|
+
item_json.fetch("options").each do |option_json|
|
220
|
+
question.options << build_option(questionnaire, question, option_json)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
when "select"
|
224
|
+
Entities::Questions::SelectQuestion.new(key, attributes).tap do |question|
|
225
|
+
item_json.fetch("options").each do |option_json|
|
226
|
+
question.options << build_option(questionnaire, question, option_json)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
when "string"
|
230
|
+
Entities::Questions::StringQuestion.new(key, attributes.merge(
|
231
|
+
unit: item_json.fetch("unit"),
|
232
|
+
size: item_json.fetch("size"),
|
233
|
+
))
|
234
|
+
when "textarea"
|
235
|
+
Entities::Questions::TextQuestion.new(key, attributes.merge(
|
236
|
+
lines: item_json.fetch("lines"),
|
237
|
+
))
|
238
|
+
else
|
239
|
+
raise "Unknown question type: #{item_json}"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def self.build_option(questionnaire, question, option_json)
|
244
|
+
option = Entities::QuestionOption.new(option_json.fetch("key")&.to_sym, question,
|
245
|
+
value: option_json.fetch("value"),
|
246
|
+
description: option_json.fetch("description"),
|
247
|
+
context_free_description: option_json.fetch("context_free_description"),
|
248
|
+
inner_title: option_json.fetch("inner_title"),
|
249
|
+
hides_questions: option_json.fetch("hides_questions").map(&:to_sym),
|
250
|
+
shows_questions: option_json.fetch("shows_questions").map(&:to_sym),
|
251
|
+
hidden: option_json.fetch("hidden"),
|
252
|
+
placeholder: option_json.fetch("placeholder"),
|
253
|
+
)
|
254
|
+
|
255
|
+
option_json.fetch("questions").each do |question_json|
|
256
|
+
subquestion = build_question(questionnaire, question_json, parent: question)
|
257
|
+
questionnaire.register_question(subquestion)
|
258
|
+
option.questions << subquestion
|
259
|
+
end
|
260
|
+
|
261
|
+
option
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.build_question_validation(attrs)
|
265
|
+
base_validation = {
|
266
|
+
type: attrs.fetch("type").to_sym,
|
267
|
+
explanation: attrs["explanation"] # not always specified for min/max validation
|
268
|
+
}
|
269
|
+
|
270
|
+
case attrs.fetch("type")
|
271
|
+
when "requires_answer"
|
272
|
+
base_validation
|
273
|
+
when "answer_group_minimum", "answer_group_maximum"
|
274
|
+
base_validation.merge(
|
275
|
+
group: attrs.fetch("group"), # TODO: sometimes a symbol, sometimes a string in the original, but I hope it doesn't matter
|
276
|
+
value: attrs.fetch("value")
|
277
|
+
)
|
278
|
+
when "valid_integer", "valid_float"
|
279
|
+
base_validation
|
280
|
+
when "valid_date"
|
281
|
+
base_validation.merge(
|
282
|
+
subtype: attrs.fetch("subtype").to_sym
|
283
|
+
)
|
284
|
+
when "minimum", "maximum"
|
285
|
+
value = case attrs.fetch("value_type")
|
286
|
+
when "Date"
|
287
|
+
Date.parse(attrs.fetch("value"))
|
288
|
+
when "DateTime"
|
289
|
+
DateTime.parse(attrs.fetch("value"))
|
290
|
+
when "Time", "ActiveSuport::TimeWithZone"
|
291
|
+
Time.zone.parse(attrs.fetch("value"))
|
292
|
+
else
|
293
|
+
attrs.fetch("value")
|
294
|
+
end
|
295
|
+
|
296
|
+
base_validation.merge(
|
297
|
+
value: value,
|
298
|
+
subtype: attrs.fetch("subtype").to_sym,
|
299
|
+
)
|
300
|
+
when "too_many_checked"
|
301
|
+
base_validation.merge(
|
302
|
+
uncheck_all_key: attrs.fetch("uncheck_all_key").to_sym
|
303
|
+
)
|
304
|
+
when "minimum_checked_required"
|
305
|
+
base_validation.merge(
|
306
|
+
minimum_checked_value: attrs.fetch("minimum_checked_value")
|
307
|
+
)
|
308
|
+
when "maximum_checked_allowed"
|
309
|
+
base_validation.merge(
|
310
|
+
maximum_checked_value: attrs.fetch("maximum_checked_value")
|
311
|
+
)
|
312
|
+
when "regexp"
|
313
|
+
base_validation.merge(
|
314
|
+
matcher: Regexp.new(attrs.fetch("matcher"))
|
315
|
+
)
|
316
|
+
when "not_all_checked"
|
317
|
+
base_validation.merge(
|
318
|
+
check_all_key: attrs.fetch("check_all_key").to_sym
|
319
|
+
)
|
320
|
+
else
|
321
|
+
raise "Unknown validation type: #{attrs.inspect}"
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def self.build_score_calculation(attrs)
|
326
|
+
Entities::ScoreCalculation.new(attrs.fetch("key").to_sym,
|
327
|
+
label: attrs.fetch("label"),
|
328
|
+
sbg_key: attrs.fetch("sbg_key"),
|
329
|
+
options: attrs.fetch("options").symbolize_keys,
|
330
|
+
sourcecode: attrs.fetch("sourcecode"),
|
331
|
+
)
|
332
|
+
end
|
333
|
+
|
334
|
+
def self.build_flag(attrs)
|
335
|
+
Entities::Flag.new(
|
336
|
+
key: attrs.fetch("key").to_sym,
|
337
|
+
description_true: attrs.fetch("description_true"),
|
338
|
+
description_false: attrs.fetch("description_false"),
|
339
|
+
description: attrs.fetch("description"),
|
340
|
+
internal: attrs.fetch("internal"),
|
341
|
+
trigger_on: attrs.fetch("trigger_on"),
|
342
|
+
shows_questions: attrs.fetch("shows_questions").map(&:to_sym),
|
343
|
+
hides_questions: attrs.fetch("hides_questions").map(&:to_sym),
|
344
|
+
depends_on: attrs.fetch("depends_on"), # TODO: emperically determined to be a string in DSL, is that right?
|
345
|
+
default_in_interface: attrs.fetch("default_in_interface"),
|
346
|
+
)
|
347
|
+
end
|
348
|
+
|
349
|
+
def self.build_textvar(attrs)
|
350
|
+
Entities::Textvar.new(
|
351
|
+
key: attrs.fetch("key").to_sym,
|
352
|
+
description: attrs.fetch("description"),
|
353
|
+
default: attrs.fetch("default"),
|
354
|
+
depends_on_flag: attrs.fetch("depends_on_flag")&.to_sym
|
355
|
+
)
|
356
|
+
end
|
357
|
+
|
358
|
+
def self.build_chart(questionnaire, chart_json)
|
359
|
+
base_args = {
|
360
|
+
title: chart_json.fetch("title"),
|
361
|
+
plottables: chart_json.fetch("plottables").map do |plottable_json|
|
362
|
+
Quby::Questionnaires::Entities::Charting::Plottable.new(
|
363
|
+
plottable_json.fetch("key").to_sym,
|
364
|
+
label: plottable_json.fetch("label"),
|
365
|
+
plotted_key: plottable_json.fetch("plotted_key").to_sym,
|
366
|
+
global: plottable_json.fetch("global"),
|
367
|
+
questionnaire_key: plottable_json.fetch("questionnaire_key")
|
368
|
+
)
|
369
|
+
end,
|
370
|
+
y_categories: chart_json.fetch("y_categories"),
|
371
|
+
y_range_categories: chart_json.fetch("y_range_categories"),
|
372
|
+
chart_type: chart_json.fetch("chart_type"),
|
373
|
+
y_range: chart_json.fetch("y_range"),
|
374
|
+
tick_interval: chart_json.fetch("tick_interval"),
|
375
|
+
plotbands: chart_json.fetch("plotbands").map do |plotband_json|
|
376
|
+
{
|
377
|
+
color: plotband_json.fetch("color").to_sym,
|
378
|
+
from: plotband_json.fetch("from"),
|
379
|
+
to: plotband_json.fetch("to")
|
380
|
+
}
|
381
|
+
end,
|
382
|
+
}
|
383
|
+
|
384
|
+
case chart_json.fetch("type")
|
385
|
+
when "bar_chart"
|
386
|
+
Quby::Questionnaires::Entities::Charting::BarChart.new(chart_json.fetch("key").to_sym,
|
387
|
+
plotlines: chart_json.fetch("plotlines"),
|
388
|
+
**base_args
|
389
|
+
)
|
390
|
+
when "line_chart"
|
391
|
+
Quby::Questionnaires::Entities::Charting::LineChart.new(chart_json.fetch("key").to_sym,
|
392
|
+
y_label: chart_json.fetch("y_label"),
|
393
|
+
tonality: chart_json.fetch("tonality").to_sym,
|
394
|
+
baseline: YAML.load(chart_json.fetch("baseline")),
|
395
|
+
clinically_relevant_change: chart_json.fetch("clinically_relevant_change"),
|
396
|
+
**base_args
|
397
|
+
)
|
398
|
+
when "radar_chart"
|
399
|
+
Quby::Questionnaires::Entities::Charting::BarChart.new(chart_json.fetch("key").to_sym,
|
400
|
+
plotlines: chart_json.fetch("plotlines"),
|
401
|
+
**base_args
|
402
|
+
)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
def self.build_score_schema(attributes)
|
407
|
+
Entities::ScoreSchema.new(
|
408
|
+
key: attributes.fetch("key").to_sym,
|
409
|
+
label: attributes.fetch("label"),
|
410
|
+
subscore_schemas: attributes.fetch("subscore_schemas").map do |subschema|
|
411
|
+
{
|
412
|
+
key: subschema.fetch("key").to_sym,
|
413
|
+
label: subschema.fetch("label"),
|
414
|
+
export_key: subschema.fetch("export_key").to_sym,
|
415
|
+
only_for_export: subschema.fetch("only_for_export")
|
416
|
+
}
|
417
|
+
end
|
418
|
+
)
|
419
|
+
end
|
420
|
+
|
421
|
+
def self.build_outcome_table(questionnaire, attributes)
|
422
|
+
Entities::OutcomeTable.new(
|
423
|
+
questionnaire: questionnaire,
|
424
|
+
key: attributes.fetch("key").to_sym,
|
425
|
+
score_keys: attributes.fetch("score_keys").map(&:to_sym),
|
426
|
+
subscore_keys: attributes.fetch("subscore_keys").map(&:to_sym),
|
427
|
+
name: attributes.fetch("name"),
|
428
|
+
default_collapsed: attributes.fetch("default_collapsed"),
|
429
|
+
)
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
end
|