quby-compiler 0.5.18 → 0.5.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/quby/compiler/dsl/helpers.rb +6 -0
- data/lib/quby/compiler/dsl/info_block_builder.rb +44 -0
- data/lib/quby/compiler/dsl/panel_builder.rb +9 -0
- data/lib/quby/compiler/dsl/questionnaire_builder.rb +1 -0
- data/lib/quby/compiler/entities/fields.rb +4 -1
- data/lib/quby/compiler/entities/info_block.rb +28 -0
- data/lib/quby/compiler/entities/question.rb +4 -0
- data/lib/quby/compiler/entities/question_option.rb +4 -0
- data/lib/quby/compiler/entities.rb +1 -0
- data/lib/quby/compiler/outputs/quby_frontend_v1_serializer.rb +3 -1
- data/lib/quby/compiler/outputs/quby_frontend_v2_serializer.rb +16 -4
- data/lib/quby/compiler/services/definition_validator.rb +19 -11
- data/lib/quby/compiler/version.rb +1 -1
- metadata +4 -3
- data/lib/quby/compiler/dsl/merge(values(:v_1, :v_2), values(v_4).rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58538613874bd655f416eba086f07ba45321bab1306a6bd710df279e3a9cead0
|
4
|
+
data.tar.gz: 1a0c1ea24a9c0fd6e8387f6b1760e14d387e1ed41061d66c8176bf642e72f64e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68251dfd41c4d5054e0d23c7cfa202f6acced87251d2f16b9373c5494d2cbea52955d241479d807e11af8617ced647b49769204b38907bb3728d045a254431cb
|
7
|
+
data.tar.gz: 6f34cd861fec8ae281c6fffb8dea442054d5500f5e90fb5ff3594cf1d41e3dd28200e601edc29f05e68e7be32653e084f2e5c5c02ea92cbdac87c64c6581e438
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
# 0.5.20
|
2
|
+
|
3
|
+
* dsl: Add info_block support
|
4
|
+
* quby2: Add info_block support
|
5
|
+
|
6
|
+
# 0.5.19
|
7
|
+
|
8
|
+
* quby2: Make the key for inner title predictable, so the json doesn't change each time, making Roqua think the questionnaire has changed.
|
9
|
+
|
1
10
|
# 0.5.18
|
2
11
|
|
3
12
|
* add footer (quby2 only)
|
@@ -24,6 +24,12 @@ module Quby
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
def check_key_uniqueness(key, questionnaire:)
|
28
|
+
if questionnaire.key_in_use? key
|
29
|
+
fail "#{questionnaire.key}:#{key}: is already used."
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
27
33
|
def video_tag(*urls, poster: nil, autoplay: false, loop: false)
|
28
34
|
# assume the file extension is the video format
|
29
35
|
# otherwise, the host's declared mime type is used to figure out compatibility
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'quby/compiler/entities'
|
4
|
+
|
5
|
+
module Quby
|
6
|
+
module Compiler
|
7
|
+
module DSL
|
8
|
+
class InfoBlockBuilder < Base
|
9
|
+
attr_reader :info_block, :default_question_options
|
10
|
+
|
11
|
+
delegate :panel, to: :info_block
|
12
|
+
delegate :questionnaire, to: :panel
|
13
|
+
|
14
|
+
def initialize(key, start_open: true, panel:, default_question_options:)
|
15
|
+
@info_block = Entities::InfoBlock.new(key: , panel:, start_open:)
|
16
|
+
@default_question_options = default_question_options
|
17
|
+
check_key_uniqueness(key, questionnaire:)
|
18
|
+
questionnaire.fields.info_block_keys << key
|
19
|
+
panel.items << @info_block
|
20
|
+
end
|
21
|
+
|
22
|
+
def info_html(value)
|
23
|
+
raise "Can only add one info_html item per info_block" if info_block.html.present?
|
24
|
+
info_block.html = value
|
25
|
+
end
|
26
|
+
|
27
|
+
def html(value)
|
28
|
+
info_block.items << Entities::Text.new('', html_content: value.to_s)
|
29
|
+
end
|
30
|
+
|
31
|
+
def question(key, **options, &block)
|
32
|
+
options = default_question_options.merge(options).merge(questionnaire:)
|
33
|
+
|
34
|
+
check_question_keys_uniqueness key, options, questionnaire
|
35
|
+
|
36
|
+
question = QuestionBuilder.build(key, **options, &block)
|
37
|
+
|
38
|
+
questionnaire.register_question(question)
|
39
|
+
info_block.items << question
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -65,6 +65,15 @@ module Quby
|
|
65
65
|
table_builder.instance_eval(&block) if block
|
66
66
|
end
|
67
67
|
|
68
|
+
def info_block(key, **options, &block)
|
69
|
+
info_block_builder = DSL::InfoBlockBuilder.new \
|
70
|
+
key,
|
71
|
+
panel: @panel,
|
72
|
+
default_question_options: @default_question_options,
|
73
|
+
**options
|
74
|
+
info_block_builder.instance_eval(&block)
|
75
|
+
end
|
76
|
+
|
68
77
|
def method_missing(method_sym, *args, **kwargs, &block)
|
69
78
|
if @custom_methods.key? method_sym
|
70
79
|
instance_exec(*args, **kwargs, &@custom_methods[method_sym])
|
@@ -9,6 +9,7 @@ require 'quby/compiler/dsl/charting/radar_chart_builder'
|
|
9
9
|
require 'quby/compiler/dsl/charting/bar_chart_builder'
|
10
10
|
require 'quby/compiler/dsl/charting/overview_chart_builder'
|
11
11
|
require 'quby/compiler/dsl/sexp_variable_builder'
|
12
|
+
require 'quby/compiler/dsl/info_block_builder'
|
12
13
|
|
13
14
|
require_relative 'standardized_panel_generators'
|
14
15
|
|
@@ -23,11 +23,14 @@ module Quby
|
|
23
23
|
# targeted by :depends_on relations.
|
24
24
|
attr_reader :input_keys
|
25
25
|
|
26
|
+
attr_reader :info_block_keys
|
27
|
+
|
26
28
|
def initialize(questionnaire)
|
27
29
|
@question_hash = HashWithIndifferentAccess.new
|
28
30
|
@option_hash = HashWithIndifferentAccess.new
|
29
31
|
@answer_keys = Set.new
|
30
32
|
@input_keys = Set.new
|
33
|
+
@info_block_keys = Set.new
|
31
34
|
@questionnaire = questionnaire
|
32
35
|
end
|
33
36
|
|
@@ -59,7 +62,7 @@ module Quby
|
|
59
62
|
end
|
60
63
|
|
61
64
|
def key_in_use?(key)
|
62
|
-
@question_hash.key?(key) || input_keys.include?(key.to_sym)
|
65
|
+
@question_hash.key?(key) || input_keys.include?(key.to_sym) || info_block_keys.include?(key)
|
63
66
|
end
|
64
67
|
|
65
68
|
# Given a list of question and option keys returns a list of input-keys. If a given key is a question-key,
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Quby
|
2
|
+
module Compiler
|
3
|
+
module Entities
|
4
|
+
class InfoBlock < Item
|
5
|
+
attr_reader :key, :items, :start_open, :panel
|
6
|
+
attr_accessor :html
|
7
|
+
|
8
|
+
validates :key, presence: true, 'quby/compiler/type': {is_a: Symbol}
|
9
|
+
validates :html, presence: true
|
10
|
+
|
11
|
+
def initialize(key:, panel:, start_open: true)
|
12
|
+
@panel = panel
|
13
|
+
@key = key
|
14
|
+
@start_open = start_open
|
15
|
+
@items = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def index
|
19
|
+
panel.items.index(self)
|
20
|
+
end
|
21
|
+
|
22
|
+
def path_str
|
23
|
+
"#{panel.questionnaire.key}:InfoBlock:#{key}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -24,6 +24,7 @@ require 'quby/compiler/entities/charting/plottable'
|
|
24
24
|
require 'quby/compiler/entities/panel'
|
25
25
|
require 'quby/compiler/entities/text'
|
26
26
|
require 'quby/compiler/entities/table'
|
27
|
+
require 'quby/compiler/entities/info_block'
|
27
28
|
|
28
29
|
require 'quby/compiler/entities/outcome_table'
|
29
30
|
|
@@ -15,7 +15,7 @@ module Quby
|
|
15
15
|
{
|
16
16
|
key: panel.key,
|
17
17
|
title: panel.title,
|
18
|
-
items: panel.items.reject { |item| item.respond_to?(:table) && item.table }.
|
18
|
+
items: panel.items.reject { |item| item.respond_to?(:table) && item.table }.flat_map { |item| item_as_json(item) }
|
19
19
|
}
|
20
20
|
end
|
21
21
|
end
|
@@ -28,6 +28,8 @@ module Quby
|
|
28
28
|
question_as_json(item)
|
29
29
|
when Quby::Compiler::Entities::Table
|
30
30
|
table_as_json(item)
|
31
|
+
when Quby::Compiler::Entities::InfoBlock
|
32
|
+
item.items.map { item_as_json(_1) }
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
@@ -44,11 +44,23 @@ module Quby
|
|
44
44
|
when Quby::Compiler::Entities::Question
|
45
45
|
return if item.table # things inside a table are added to the table, AND ALSO to the panel. skip them.
|
46
46
|
{ type: 'question', key: item.key }
|
47
|
+
when Quby::Compiler::Entities::InfoBlock
|
48
|
+
info_block_item(item)
|
47
49
|
when Quby::Compiler::Entities::Table
|
48
50
|
{ type: "table" }
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
54
|
+
def info_block_item(info_block)
|
55
|
+
{
|
56
|
+
type: 'info',
|
57
|
+
key: info_block.key,
|
58
|
+
html: handle_html(info_block.html, type: :question_description, v1_markdown: false),
|
59
|
+
startOpen: info_block.start_open,
|
60
|
+
items: info_block.items.map { panel_item(_1) }.compact
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
52
64
|
def questions
|
53
65
|
fields.question_hash \
|
54
66
|
.to_h { |k, question| [k, question(question)] } \
|
@@ -194,9 +206,9 @@ module Quby
|
|
194
206
|
end
|
195
207
|
|
196
208
|
def children(question)
|
197
|
-
question.options.map { |child|
|
209
|
+
question.options.map.with_index { |child, idx|
|
198
210
|
if child.inner_title
|
199
|
-
inner_title_as_json(child)
|
211
|
+
inner_title_as_json(child, idx)
|
200
212
|
elsif child.placeholder
|
201
213
|
nil # placeholder attr on question.
|
202
214
|
else
|
@@ -205,10 +217,10 @@ module Quby
|
|
205
217
|
}.compact
|
206
218
|
end
|
207
219
|
|
208
|
-
def inner_title_as_json(option)
|
220
|
+
def inner_title_as_json(option, idx)
|
209
221
|
{
|
210
222
|
type: 'html',
|
211
|
-
key:
|
223
|
+
key: "i-t-#{idx}",
|
212
224
|
html: handle_html(option.description)
|
213
225
|
}
|
214
226
|
end
|
@@ -27,6 +27,7 @@ module Quby
|
|
27
27
|
validate_markdown_fields(questionnaire) if questionnaire.validate_html
|
28
28
|
validate_raw_content_items(questionnaire) if questionnaire.validate_html
|
29
29
|
validate_sexp_variables(questionnaire)
|
30
|
+
validate_info_blocks(questionnaire)
|
30
31
|
# Some compilation errors are Exceptions (pure syntax errors) and some StandardErrors (NameErrors)
|
31
32
|
rescue Exception => exception # rubocop:disable Lint/RescueException
|
32
33
|
definition.errors.add(:sourcecode, message: "Questionnaire error: #{definition.key}\n" \
|
@@ -67,7 +68,7 @@ module Quby
|
|
67
68
|
end
|
68
69
|
|
69
70
|
questionnaire.question_hash.each_value do |question|
|
70
|
-
|
71
|
+
validate_item(question)
|
71
72
|
subquestions_cant_have_default_invisible question
|
72
73
|
validate_subquestion_absence_in_select question
|
73
74
|
validate_placeholder_options_nil_values question
|
@@ -79,10 +80,10 @@ module Quby
|
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
82
|
-
def
|
83
|
-
|
84
|
-
|
85
|
-
|
83
|
+
def validate_item(item)
|
84
|
+
return if item.valid?
|
85
|
+
|
86
|
+
fail "#{item.path_str} is invalid: #{item.errors.full_messages.join(', ')}"
|
86
87
|
end
|
87
88
|
|
88
89
|
def validate_scores(questionnaire)
|
@@ -105,12 +106,9 @@ module Quby
|
|
105
106
|
|
106
107
|
def validate_question_options(questionnaire, question)
|
107
108
|
question.options.each do |option|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
end
|
112
|
-
to_be_hidden_questions_exist_and_not_subquestion?(questionnaire, option, msg_base: msg_base)
|
113
|
-
to_be_shown_questions_exist_and_not_subquestion?(questionnaire, option, msg_base: msg_base)
|
109
|
+
validate_item(option)
|
110
|
+
to_be_hidden_questions_exist_and_not_subquestion?(questionnaire, option, msg_base: option.path_str)
|
111
|
+
to_be_shown_questions_exist_and_not_subquestion?(questionnaire, option, msg_base: option.path_str)
|
114
112
|
end
|
115
113
|
end
|
116
114
|
|
@@ -140,6 +138,16 @@ module Quby
|
|
140
138
|
end
|
141
139
|
end
|
142
140
|
|
141
|
+
def validate_info_blocks(questionnaire)
|
142
|
+
questionnaire.panels.each do |panel|
|
143
|
+
panel.items.each do |item|
|
144
|
+
next unless item.is_a?(Entities::InfoBlock)
|
145
|
+
|
146
|
+
validate_item(item)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
143
151
|
def ensure_valid_descriptions(questionnaire, flag)
|
144
152
|
unless (flag.description_false.present? && flag.description_true.present?) || flag.description.present?
|
145
153
|
fail ArgumentError, "Flag '#{flag.key}' Requires at least either both description_true and description_false or a description"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quby-compiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.20
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marten Veldthuis
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-05-22 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: activemodel
|
@@ -150,7 +150,7 @@ files:
|
|
150
150
|
- lib/quby/compiler/dsl/charting/overview_chart_builder.rb
|
151
151
|
- lib/quby/compiler/dsl/charting/radar_chart_builder.rb
|
152
152
|
- lib/quby/compiler/dsl/helpers.rb
|
153
|
-
- lib/quby/compiler/dsl/
|
153
|
+
- lib/quby/compiler/dsl/info_block_builder.rb
|
154
154
|
- lib/quby/compiler/dsl/panel_builder.rb
|
155
155
|
- lib/quby/compiler/dsl/question_builder.rb
|
156
156
|
- lib/quby/compiler/dsl/questionnaire_builder.rb
|
@@ -181,6 +181,7 @@ files:
|
|
181
181
|
- lib/quby/compiler/entities/definition.rb
|
182
182
|
- lib/quby/compiler/entities/fields.rb
|
183
183
|
- lib/quby/compiler/entities/flag.rb
|
184
|
+
- lib/quby/compiler/entities/info_block.rb
|
184
185
|
- lib/quby/compiler/entities/item.rb
|
185
186
|
- lib/quby/compiler/entities/lookup_tables.rb
|
186
187
|
- lib/quby/compiler/entities/outcome_table.rb
|
@@ -1,16 +0,0 @@
|
|
1
|
-
merge(values(:v_1, :v_2), values(v_4).recode(1 => 3)).sum
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
divide(value(:v_2), multiply(value(:v_1), value(:v_1)))
|
6
|
-
|
7
|
-
w / l * l
|
8
|
-
|
9
|
-
|
10
|
-
sexp_variable :key1 do
|
11
|
-
foo = values(:v_1, :v_2)
|
12
|
-
bar = recode(foo, 1 => 3)
|
13
|
-
bla = merge(foo, bar)
|
14
|
-
sum(bla)
|
15
|
-
|
16
|
-
end
|