surveyor 0.21.0 → 0.22.0
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.
- data/.gitignore +1 -0
- data/Gemfile +0 -6
- data/README.md +40 -14
- data/app/helpers/surveyor_helper.rb +1 -85
- data/app/views/partials/_answer.html.haml +5 -4
- data/app/views/partials/_question.html.haml +7 -5
- data/app/views/partials/_question_group.html.haml +2 -2
- data/app/views/surveyor/export.json.rabl +75 -0
- data/app/views/surveyor/show.html.haml +75 -13
- data/app/views/surveyor/show.json.rabl +14 -0
- data/config/routes.rb +2 -3
- data/doc/surveyor reject or delete decision matrix.png +0 -0
- data/features/export_to_json.feature +96 -0
- data/features/show_survey.feature +42 -0
- data/features/step_definitions/{common_setps.rb → common_steps.rb} +0 -0
- data/features/step_definitions/surveyor_steps.rb +46 -12
- data/features/step_definitions/web_steps.rb +15 -5
- data/features/support/paths.rb +2 -1
- data/features/surveyor.feature +192 -41
- data/features/surveyor_parser.feature +10 -10
- data/features/{redcap_parser.feature → z_redcap_parser.feature} +9 -6
- data/lib/formtastic/surveyor_builder.rb +1 -4
- data/lib/generators/surveyor/install_generator.rb +6 -5
- data/lib/generators/surveyor/templates/db/migrate/add_api_id_to_question_groups.rb +9 -0
- data/lib/generators/surveyor/templates/db/migrate/add_api_ids_to_response_sets_and_responses.rb +11 -0
- data/lib/generators/surveyor/templates/public/javascripts/surveyor/jquery-ui-timepicker-addon.js +1277 -0
- data/lib/generators/surveyor/templates/public/javascripts/surveyor/jquery-ui.js +11729 -0
- data/lib/generators/surveyor/templates/public/javascripts/surveyor/jquery.surveyor.js +54 -10
- data/lib/generators/surveyor/templates/public/stylesheets/sass/surveyor.sass +1 -1
- data/lib/generators/surveyor/templates/public/stylesheets/surveyor/jquery-ui-timepicker-addon.css +6 -0
- data/lib/generators/surveyor/templates/public/stylesheets/surveyor/jquery-ui.custom.css +572 -0
- data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-icons_ef8c08_256x240.png +0 -0
- data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-icons_ffffff_256x240.png +0 -0
- data/lib/generators/surveyor/templates/surveys/EXTENDING_SURVEYOR.md +14 -0
- data/lib/generators/surveyor/templates/surveys/MODIFYING_SURVEYOR.md +91 -0
- data/lib/generators/surveyor/templates/surveys/date_survey.rb +15 -0
- data/lib/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +2 -2
- data/lib/surveyor/common.rb +31 -4
- data/lib/surveyor/helpers/surveyor_helper_methods.rb +99 -0
- data/lib/surveyor/models/answer_methods.rb +6 -5
- data/lib/surveyor/models/dependency_condition_methods.rb +0 -1
- data/lib/surveyor/models/dependency_methods.rb +1 -1
- data/lib/surveyor/models/question_group_methods.rb +5 -0
- data/lib/surveyor/models/question_methods.rb +5 -2
- data/lib/surveyor/models/response_methods.rb +44 -3
- data/lib/surveyor/models/response_set_methods.rb +14 -4
- data/lib/surveyor/models/survey_methods.rb +8 -2
- data/lib/surveyor/models/survey_section_methods.rb +13 -1
- data/lib/surveyor/parser.rb +18 -11
- data/lib/surveyor/render_text.rb +19 -0
- data/lib/surveyor/surveyor_controller_methods.rb +19 -1
- data/lib/surveyor/unparser.rb +1 -1
- data/lib/surveyor/version.rb +1 -1
- data/lib/tasks/surveyor_tasks.rake +1 -1
- data/spec/controllers/surveyor_controller_spec.rb +7 -3
- data/spec/helpers/surveyor_helper_spec.rb +104 -9
- data/spec/lib/chinese_survey.rb +14 -0
- data/spec/lib/common_spec.rb +52 -1
- data/spec/lib/rake_kitchen_sink.rb +40 -0
- data/spec/models/answer_spec.rb +11 -0
- data/spec/models/question_spec.rb +15 -0
- data/spec/models/response_set_spec.rb +45 -1
- data/spec/models/response_spec.rb +7 -4
- data/surveyor.gemspec +4 -2
- metadata +99 -40
- data/app/controllers/results_controller.rb +0 -13
- data/app/views/results/index.html.erb +0 -17
- data/app/views/results/show.html.erb +0 -25
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -3,9 +3,3 @@ source :rubygems
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
eval(File.read File.expand_path('../Gemfile.rails_version', __FILE__))
|
6
|
-
|
7
|
-
group :development do
|
8
|
-
# use git version for the ci:setup:rspecbase task; not there in
|
9
|
-
# 1.6.5, but might be in a later version.
|
10
|
-
gem 'ci_reporter', :git => 'git://github.com/nicksieger/ci_reporter.git'
|
11
|
-
end
|
data/README.md
CHANGED
@@ -55,34 +55,32 @@ The first question is "pick one" (radio buttons) with "other". The second questi
|
|
55
55
|
|
56
56
|
# Installation
|
57
57
|
|
58
|
-
1. Add surveyor to your Gemfile
|
58
|
+
1. Add surveyor to your Gemfile:
|
59
59
|
|
60
|
-
gem "surveyor"
|
61
|
-
gem "haml"
|
60
|
+
gem "surveyor"
|
62
61
|
|
63
62
|
Then run:
|
64
63
|
|
65
|
-
|
64
|
+
bundle install
|
66
65
|
|
67
66
|
2. Generate assets, run migrations:
|
68
67
|
|
69
|
-
|
70
|
-
|
68
|
+
script/rails generate surveyor:install
|
69
|
+
rake db:migrate
|
71
70
|
|
72
71
|
3. Try out the "kitchen sink" survey. The rake task above generates surveys from our custom survey DSL (a good format for end users and stakeholders).
|
73
72
|
|
74
|
-
|
73
|
+
rake surveyor FILE=surveys/kitchen_sink_survey.rb
|
75
74
|
|
76
|
-
4. Start up your app and visit:
|
77
|
-
|
78
|
-
http://localhost:3000/surveys
|
75
|
+
4. Start up your app and visit http://localhost:3000/surveys
|
79
76
|
|
80
77
|
Try taking the survey and compare it to the contents of the DSL file kitchen\_sink\_survey.rb. See how the DSL maps to what you see.
|
81
78
|
|
82
|
-
There are two other useful rake tasks
|
79
|
+
There are two other useful rake tasks:
|
83
80
|
|
84
|
-
`
|
85
|
-
`rake surveyor:unparse`
|
81
|
+
* `surveyor:remove` removes all unused surveys.
|
82
|
+
* `rake surveyor:unparse` exports a survey from the application into a
|
83
|
+
file in the surveyor DSL.
|
86
84
|
|
87
85
|
# Customizing surveyor
|
88
86
|
|
@@ -92,12 +90,40 @@ Surveyor's controller, models, and views may be customized via classes in your a
|
|
92
90
|
|
93
91
|
and read surveys/EXTENDING\_SURVEYOR
|
94
92
|
|
93
|
+
# PDF support
|
94
|
+
|
95
|
+
* Add the following lines to your Gemfile:
|
96
|
+
|
97
|
+
<pre>
|
98
|
+
gem 'pdfkit'
|
99
|
+
gem 'wkhtmltopdf'
|
100
|
+
</pre>
|
101
|
+
|
102
|
+
or on OSX:
|
103
|
+
|
104
|
+
<pre>
|
105
|
+
gem 'pdfkit'
|
106
|
+
gem 'wkhtmltopdf-binary'
|
107
|
+
</pre>
|
108
|
+
|
109
|
+
* Add the following to your application.rb:
|
110
|
+
|
111
|
+
<pre>
|
112
|
+
config.middleware.use PDFKit::Middleware
|
113
|
+
</pre>
|
114
|
+
|
115
|
+
* Create links with :format => 'pdf' in them, for example:
|
116
|
+
|
117
|
+
<pre>
|
118
|
+
%li= link_to "PDF", view_my_survey_path(:survey_code => response_set.survey.access_code, :response_set_code => response_set.access_code, :format => 'pdf')
|
119
|
+
</pre>
|
120
|
+
|
95
121
|
# Requirements
|
96
122
|
|
97
123
|
Surveyor depends on:
|
98
124
|
|
99
125
|
* Ruby (1.8.7 - 1.9.2)
|
100
|
-
* Rails 3.
|
126
|
+
* Rails 3.0-3.1
|
101
127
|
* HAML
|
102
128
|
* SASS
|
103
129
|
* fastercsv (or CSV for ruby 1.9) for csv exports
|
@@ -1,87 +1,3 @@
|
|
1
1
|
module SurveyorHelper
|
2
|
-
|
3
|
-
def surveyor_includes
|
4
|
-
surveyor_stylsheets + surveyor_javascripts
|
5
|
-
end
|
6
|
-
def surveyor_stylsheets
|
7
|
-
stylesheet_link_tag 'surveyor/reset', 'surveyor/dateinput', 'surveyor', 'custom'
|
8
|
-
end
|
9
|
-
def surveyor_javascripts
|
10
|
-
javascript_include_tag 'surveyor/jquery.tools.min', 'surveyor/jquery.surveyor', 'surveyor/jquery.blockUI'
|
11
|
-
end
|
12
|
-
# Helper for displaying warning/notice/error flash messages
|
13
|
-
def flash_messages(types)
|
14
|
-
types.map{|type| content_tag(:div, "#{flash[type]}".html_safe, :class => type.to_s)}.join.html_safe
|
15
|
-
end
|
16
|
-
# Section: dependencies, menu, previous and next
|
17
|
-
def dependency_explanation_helper(question,response_set)
|
18
|
-
# Attempts to explain why this dependent question needs to be answered by referenced the dependent question and users response
|
19
|
-
trigger_responses = []
|
20
|
-
dependent_questions = Question.find_all_by_id(question.dependency.dependency_conditions.map(&:question_id)).uniq
|
21
|
-
response_set.responses.find_all_by_question_id(dependent_questions.map(&:id)).uniq.each do |resp|
|
22
|
-
trigger_responses << resp.to_s
|
23
|
-
end
|
24
|
-
" You answered "#{trigger_responses.join("" and "")}" to the question "#{dependent_questions.map(&:text).join("","")}""
|
25
|
-
end
|
26
|
-
def menu_button_for(section)
|
27
|
-
submit_tag(section.title, :name => "section[#{section.id}]")
|
28
|
-
end
|
29
|
-
def previous_section
|
30
|
-
# use copy in memory instead of making extra db calls
|
31
|
-
submit_tag(t('surveyor.previous_section').html_safe, :name => "section[#{@sections[@sections.index(@section)-1].id}]") unless @sections.first == @section
|
32
|
-
end
|
33
|
-
def next_section
|
34
|
-
# use copy in memory instead of making extra db calls
|
35
|
-
@sections.last == @section ? submit_tag(t('surveyor.click_here_to_finish').html_safe, :name => "finish") : submit_tag(t('surveyor.next_section').html_safe, :name => "section[#{@sections[@sections.index(@section)+1].id}]")
|
36
|
-
end
|
37
|
-
|
38
|
-
# Questions
|
39
|
-
def q_text(obj)
|
40
|
-
@n ||= 0
|
41
|
-
return image_tag(obj.text) if obj.is_a?(Question) and obj.display_type == "image"
|
42
|
-
return obj.text if obj.is_a?(Question) and (obj.dependent? or obj.display_type == "label" or obj.part_of_group?)
|
43
|
-
"#{@n += 1}) #{obj.text}"
|
44
|
-
end
|
45
|
-
# def split_text(text = "") # Split text into with "|" delimiter - parts to go before/after input element
|
46
|
-
# {:prefix => text.split("|")[0].blank? ? " " : text.split("|")[0], :postfix => text.split("|")[1] || " "}
|
47
|
-
# end
|
48
|
-
# def question_help_helper(question)
|
49
|
-
# question.help_text.blank? ? "" : %Q(<span class="question-help">#{question.help_text}</span>)
|
50
|
-
# end
|
51
|
-
|
52
|
-
# Answers
|
53
|
-
def a_text(obj, pos=nil)
|
54
|
-
return image_tag(obj.text) if obj.is_a?(Answer) and obj.display_type == "image"
|
55
|
-
obj.split_or_hidden_text(pos)
|
56
|
-
end
|
57
|
-
def rc_to_attr(type_sym)
|
58
|
-
case type_sym.to_s
|
59
|
-
when /^date|time$/ then :datetime_value
|
60
|
-
when /(string|text|integer|float|datetime)/ then "#{type_sym.to_s}_value".to_sym
|
61
|
-
else :answer_id
|
62
|
-
end
|
63
|
-
end
|
64
|
-
def rc_to_as(type_sym)
|
65
|
-
case type_sym.to_s
|
66
|
-
when /(integer|float)/ then :string
|
67
|
-
else type_sym
|
68
|
-
end
|
69
|
-
end
|
70
|
-
def generate_pick_none_input_html(response_class, default_value, css_class)
|
71
|
-
html = {}
|
72
|
-
html[:class] = css_class unless css_class.blank?
|
73
|
-
html[:value] = default_value if response_class.blank?
|
74
|
-
html
|
75
|
-
end
|
76
|
-
|
77
|
-
# Responses
|
78
|
-
def response_for(response_set, question, answer = nil, response_group = nil)
|
79
|
-
return nil unless response_set && question && question.id
|
80
|
-
result = response_set.responses.detect{|r| (r.question_id == question.id) && (answer.blank? ? true : r.answer_id == answer.id) && (r.response_group.blank? ? true : r.response_group.to_i == response_group.to_i)}
|
81
|
-
result.blank? ? response_set.responses.build(:question_id => question.id, :response_group => response_group) : result
|
82
|
-
end
|
83
|
-
def response_idx(increment = true)
|
84
|
-
@rc ||= 0
|
85
|
-
(increment ? @rc += 1 : @rc).to_s
|
86
|
-
end
|
2
|
+
include Surveyor::Helpers::SurveyorHelperMethods
|
87
3
|
end
|
@@ -2,18 +2,19 @@
|
|
2
2
|
- rg ||= nil
|
3
3
|
- r = response_for(@response_set, q, a, rg)
|
4
4
|
- i = response_idx(q.pick != "one") # argument will be false (don't increment i) if we're on radio buttons
|
5
|
+
- disabled = defined?(disableFlag) ? disableFlag : false
|
5
6
|
= f.semantic_fields_for i, r do |ff|
|
6
7
|
= ff.quiet_input :question_id unless q.pick == "one" # don't repeat question_id if we're on radio buttons
|
7
8
|
= ff.quiet_input :id unless q.pick == "one" or r.new_record?
|
8
9
|
= ff.quiet_input :response_group, :value => rg if q.pick != "one" && g && g.display_type == "repeater"
|
9
10
|
- case q.pick
|
10
11
|
- when "one"
|
11
|
-
= ff.input :answer_id, :as => :surveyor_radio, :collection => [[a_text(a), a.id]], :label => false, :input_html => {:class => a.css_class}, :response_class => a.response_class
|
12
|
+
= ff.input :answer_id, :as => :surveyor_radio, :collection => [[a_text(a, nil, @render_context), a.id]], :label => false, :input_html => {:class => a.css_class, :disabled => disabled}, :response_class => a.response_class
|
12
13
|
- when "any"
|
13
|
-
= ff.input :answer_id, :as => :surveyor_check_boxes, :collection => [[a_text(a), a.id]], :label => false, :input_html => {:class => a.css_class}, :response_class => a.response_class
|
14
|
+
= ff.input :answer_id, :as => :surveyor_check_boxes, :collection => [[a_text(a, nil, @render_context), a.id]], :label => false, :input_html => {:class => a.css_class, :disabled => disabled}, :response_class => a.response_class
|
14
15
|
- when "none"
|
15
16
|
- if %w(date datetime time float integer string text).include? a.response_class
|
16
17
|
= ff.quiet_input :answer_id, :input_html => {:class => a.css_class, :value => a.id}
|
17
|
-
= ff.input rc_to_attr(a.response_class), :as => rc_to_as(a.response_class), :label => a_text(a, :pre).blank? ? false : a_text(a, :pre), :hint => a_text(a, :post), :input_html => generate_pick_none_input_html(r.as(a.response_class), a.default_value, a.css_class)
|
18
|
+
= ff.input rc_to_attr(a.response_class), :as => rc_to_as(a.response_class), :label => a_text(a, :pre, @render_context).blank? ? false : a_text(a, :pre, @render_context), :hint => a_text(a, :post, @render_context), :input_html => generate_pick_none_input_html(r.as(a.response_class), a.default_value, a.css_class, a.response_class, disabled)
|
18
19
|
- else
|
19
|
-
= a_text(a)
|
20
|
+
= a_text(a, nil, @render_context)
|
@@ -1,18 +1,19 @@
|
|
1
1
|
-# TODO: js for slider
|
2
2
|
- rg ||= nil
|
3
3
|
- renderer = q.renderer(g ||= nil)
|
4
|
-
=
|
5
|
-
|
4
|
+
- disabled = defined?(disableFlag) ? disableFlag : false
|
5
|
+
= f.inputs q_text(q, @render_context), :id => rg ? "q_#{q.id}_#{rg}" : "q_#{q.id}", :class => "q_#{renderer} #{q.css_class(@response_set)}" do
|
6
|
+
%span.help= render_help_text(q, @render_context)
|
6
7
|
- case renderer
|
7
8
|
- when :image, :label
|
8
|
-
- when :dropdown, :inline_dropdown, :slider, :repeater_dropdown
|
9
|
+
- when :dropdown, :inline_dropdown, :default_dropdown, :slider, :repeater_dropdown
|
9
10
|
- r = response_for(@response_set, q, nil, rg)
|
10
11
|
- i = response_idx
|
11
12
|
= f.semantic_fields_for i, r do |ff|
|
12
13
|
= ff.quiet_input :question_id
|
13
14
|
= ff.quiet_input :response_group, :value => rg if g && g.display_type == "repeater"
|
14
15
|
= ff.quiet_input :id unless r.new_record?
|
15
|
-
= ff.input :answer_id, :as => :select, :collection => q.answers.map{|a| [a.text, a.id]}, :label => q.text
|
16
|
+
= ff.input :answer_id, :as => :select, :collection => q.answers.map{|a| [a.text, a.id]}, :label => q.text, :input_html => { :disabled => disabled }
|
16
17
|
- else # :default, :inline, :inline_default
|
17
18
|
- if q.pick == "one"
|
18
19
|
- r = response_for(@response_set, q, nil, rg)
|
@@ -22,4 +23,5 @@
|
|
22
23
|
= ff.quiet_input :response_group, :value => rg if g && g.display_type == "repeater"
|
23
24
|
= ff.quiet_input :id unless r.new_record?
|
24
25
|
- q.answers.each do |a|
|
25
|
-
|
26
|
+
- next if (q.pick == "one" or q.pick == "any") and disabled and @response_set.responses.where( :question_id => q.id, :answer_id => a.id).empty?
|
27
|
+
= render a.custom_renderer || '/partials/answer', :q => q, :a => a, :f => f, :rg => rg, :g => g, :disableFlag => disabled
|
@@ -1,6 +1,6 @@
|
|
1
1
|
- renderer = g.renderer
|
2
|
-
= f.inputs q_text(g), :id => "g_#{g.id}", :class => "g_#{renderer} #{g.css_class(@response_set)}" do
|
3
|
-
%li.help= g
|
2
|
+
= f.inputs q_text(g, @render_context), :id => "g_#{g.id}", :class => "g_#{renderer} #{g.css_class(@response_set)}" do
|
3
|
+
%li.help= render_help_text(g, @render_context)
|
4
4
|
- case renderer
|
5
5
|
- when :grid
|
6
6
|
%li
|
@@ -0,0 +1,75 @@
|
|
1
|
+
object @survey
|
2
|
+
attribute :title
|
3
|
+
attribute :api_id => :uuid
|
4
|
+
node(:description, :if => lambda {|s| !s.description.blank? }){|s| s.description }
|
5
|
+
node(:reference_identifier, :if => lambda {|s| !s.reference_identifier.blank? }){|s| s.reference_identifier }
|
6
|
+
|
7
|
+
child :sections => :sections do
|
8
|
+
attributes :title, :display_order
|
9
|
+
node(:description, :if => lambda {|s| !s.description.blank? }){|s| s.description }
|
10
|
+
node(:reference_identifier, :if => lambda {|s| !s.reference_identifier.blank? }){|s| s.reference_identifier }
|
11
|
+
|
12
|
+
child :questions_and_groups => :questions_and_groups do
|
13
|
+
# both questions and question_groups have uuid, text, help_text, reference_identifier, and type
|
14
|
+
attribute :api_id => :uuid
|
15
|
+
node(:text, :if => lambda { |q| q.is_a?(Question)}){ |q| q.split_text(:pre) }
|
16
|
+
node(:text, :if => lambda { |q| q.is_a?(QuestionGroup)}){ |q| q.text }
|
17
|
+
node(:help_text, :if => lambda { |q| !q.help_text.blank? }){ |q| q.help_text }
|
18
|
+
node(:reference_identifier, :if => lambda { |q| !q.reference_identifier.blank? }){ |q| q.reference_identifier }
|
19
|
+
node(:type, :if => lambda { |q| q.display_type != "default" }){ |q| q.display_type }
|
20
|
+
|
21
|
+
# only questions
|
22
|
+
node(:pick, :if => lambda { |q| q.is_a?(Question) && q.pick != "none" }){ |q| q.pick }
|
23
|
+
node(:post_text, :if => lambda { |q| q.is_a?(Question) && !q.split_text(:post).blank? }){ |q| q.split_text(:post) }
|
24
|
+
|
25
|
+
child :answers, :if => lambda { |q| q.is_a?(Question) && !q.answers.blank? } do
|
26
|
+
attribute :api_id => :uuid
|
27
|
+
node(:help_text, :if => lambda { |a| !a.help_text.blank? }){ |a| a.help_text }
|
28
|
+
node(:exclusive, :if => lambda { |a| a.is_exclusive }){ |a| a.is_exclusive }
|
29
|
+
node(:text){ |a| a.split_or_hidden_text(:pre) }
|
30
|
+
node(:post_text, :if => lambda { |a| !a.split_or_hidden_text(:post).blank? }){ |a| a.split_or_hidden_text(:post) }
|
31
|
+
node(:type, :if => lambda { |a| a.response_class != "answer" }){ |a| a.response_class }
|
32
|
+
end
|
33
|
+
|
34
|
+
# both questions and question_groups have dependencies
|
35
|
+
child :dependency, :if => lambda { |q| q.dependency } do
|
36
|
+
attributes :rule
|
37
|
+
child :dependency_conditions => :conditions do
|
38
|
+
attributes :rule_key, :operator
|
39
|
+
node(:question){ |d| d.question.api_id }
|
40
|
+
node(:answer, :if => lambda { |d| d.answer }){ |d| d.answer.api_id }
|
41
|
+
node(:value, :if => lambda { |d| d.answer && d.answer.response_class != "answer" && d.as(d.answer.response_class) }){ |d| d.as(d.answer.response_class)}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
child(:questions, :if => lambda{|x| x.is_a?(QuestionGroup)}) do
|
46
|
+
attributes :api_id => :uuid
|
47
|
+
node(:text){ |q| q.split_text(:pre) }
|
48
|
+
node(:post_text, :if => lambda { |q| !q.split_text(:post).blank? }){ |q| q.split_text(:post) }
|
49
|
+
node(:help_text, :if => lambda { |q| !q.help_text.blank? }){ |q| q.help_text }
|
50
|
+
node(:reference_identifier, :if => lambda { |q| !q.reference_identifier.blank? }){ |q| q.reference_identifier }
|
51
|
+
node(:type, :if => lambda { |q| q.display_type != "default" }){ |q| q.display_type }
|
52
|
+
node(:pick, :if => lambda { |q| q.pick != "none" }){ |q| q.pick }
|
53
|
+
|
54
|
+
child :answers, :if => lambda { |q| !q.answers.blank? } do
|
55
|
+
attributes :api_id => :uuid
|
56
|
+
node(:help_text, :if => lambda { |a| !a.help_text.blank? }){ |a| a.help_text }
|
57
|
+
node(:is_exclusive, :if => lambda { |a| a.is_exclusive }){ |a| a.is_exclusive }
|
58
|
+
node(:text){ |a| a.split_or_hidden_text(:pre) }
|
59
|
+
node(:post_text, :if => lambda { |a| !a.split_or_hidden_text(:post).blank? }){ |a| a.split_or_hidden_text(:post) }
|
60
|
+
node(:type, :if => lambda { |a| a.response_class != "answer" }){ |a| a.response_class }
|
61
|
+
end
|
62
|
+
|
63
|
+
child :dependency, :if => lambda { |q| q.dependency } do
|
64
|
+
attributes :rule
|
65
|
+
child :dependency_conditions => :conditions do
|
66
|
+
attributes :rule_key, :operator
|
67
|
+
node(:question){ |d| d.question.api_id }
|
68
|
+
node(:answer, :if => lambda { |d| d.answer }){ |d| d.answer.api_id }
|
69
|
+
node(:value, :if => lambda { |d| d.answer && d.answer.response_class != "answer" && d.as(d.answer.response_class) }){ |d| d.as(d.answer.response_class)}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -1,15 +1,77 @@
|
|
1
1
|
#surveyor
|
2
|
-
-
|
3
|
-
|
4
|
-
|
5
|
-
.
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
2
|
+
- unless (types = flash.keys.select{|k| [:notice, :error, :warning].include?(k)}).blank?
|
3
|
+
.surveyor_flash
|
4
|
+
= flash_messages(types)
|
5
|
+
.close
|
6
|
+
= semantic_form_for(@response_set, :as => :r, :url => update_my_survey_path, :html => {:id => "survey_form", :class => @survey.custom_class}) do |f|
|
7
|
+
.survey_title= @survey.title
|
8
|
+
- @survey.sections.each do |section|
|
9
|
+
= div_for section do
|
10
|
+
%span.title= strip_tags(section.title)
|
11
|
+
- group_questions = []
|
12
|
+
- answered_questions = []
|
13
|
+
- label = nil
|
14
|
+
- answered_count = 0
|
15
|
+
- (questions = section.questions).each_with_index do |q, i|
|
16
|
+
- if q.part_of_group?
|
17
|
+
- group_questions << q # gather up the group questions
|
18
|
+
- unless @response_set.responses.where( :question_id => q.id).empty?
|
19
|
+
- answered_questions << q
|
20
|
+
- answered_count = answered_count + 1
|
21
|
+
- if (i+1 >= questions.size) or (q.question_group_id != questions[i+1].question_group_id) # this is the last question of the section, or the group
|
22
|
+
- if answered_questions.length > 0 # there are answered questions in this section or group
|
23
|
+
- g = q.question_group
|
24
|
+
- renderer = g.renderer
|
25
|
+
|
26
|
+
- unless label.blank?
|
27
|
+
= render q.custom_renderer || "/partials/question", :q => label, :f => f, :disableFlag => true
|
28
|
+
- label = nil
|
29
|
+
= f.inputs q_text(g), :id => "g_#{g.id}", :class => "g_#{renderer} #{g.css_class(@response_set)}" do
|
30
|
+
%li.help= g.help_text
|
31
|
+
- case renderer
|
32
|
+
- when :grid
|
33
|
+
%li
|
34
|
+
%table
|
35
|
+
%col.pre
|
36
|
+
- group_questions.first.answers.each do |a|
|
37
|
+
%col{:class => cycle("odd", "even")}
|
38
|
+
%col.post
|
39
|
+
%tbody
|
40
|
+
- group_questions.each_slice(10) do |ten_questions| # header row every 10
|
41
|
+
%tr
|
42
|
+
%th
|
43
|
+
- ten_questions.first.answers.each do |a|
|
44
|
+
%th= a_text(a)
|
45
|
+
%th
|
46
|
+
- ten_questions.each_with_index do |q, j|
|
47
|
+
%tr{:id => "q_#{q.id}", :class => "q_#{renderer} #{q.css_class(@response_set)}"}
|
48
|
+
- if q.pick == "one"
|
49
|
+
- r = response_for(@response_set, q, nil, g)
|
50
|
+
- j = response_idx # increment the response index since the answer partial skips for q.pick == one
|
51
|
+
%th= q.split_text(:pre)
|
52
|
+
- q.answers.each do |a|
|
53
|
+
%td= render a.custom_renderer || '/partials/answer', :g => g, :q => q, :a => a, :f => f, :disableFlag => true
|
54
|
+
%th= q.split_text(:post)
|
55
|
+
- when :repeater
|
56
|
+
- (@response_set.count_group_responses(group_questions) + 1).times do |rg|
|
57
|
+
%li
|
58
|
+
- group_questions.each do |q|
|
59
|
+
= render q.custom_renderer || "/partials/question", :g => g, :rg => rg, :q => q, :f => f, :disableFlag => true
|
60
|
+
- else # :inline
|
61
|
+
- answered_questions.each do |q|
|
62
|
+
= render q.custom_renderer || "/partials/question", :g => g, :q => q, :f => f, :disableFlag => true
|
63
|
+
|
13
64
|
- group_questions = []
|
14
|
-
|
15
|
-
|
65
|
+
- answered_questions = []
|
66
|
+
- else
|
67
|
+
- if q.display_type == 'label'
|
68
|
+
- label = q
|
69
|
+
- unless @response_set.responses.where( :question_id => q.id).empty?
|
70
|
+
- unless label.blank?
|
71
|
+
= render q.custom_renderer || "/partials/question", :q => label, :f => f, :disableFlag => true
|
72
|
+
- label = nil
|
73
|
+
= render q.custom_renderer || "/partials/question", :q => q, :f => f, :disableFlag => true
|
74
|
+
- answered_count = answered_count + 1
|
75
|
+
- if (i+1 >= questions.size) and (answered_count == 0)
|
76
|
+
#{"--- No data ---"}
|
77
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
object @response_set
|
2
|
+
attribute :api_id => :uuid
|
3
|
+
attribute :created_at
|
4
|
+
attribute :completed_at
|
5
|
+
node(:survey_id){|rs| rs.survey.api_id }
|
6
|
+
|
7
|
+
child :responses do
|
8
|
+
attribute :api_id => :uuid
|
9
|
+
attribute :created_at
|
10
|
+
attribute :updated_at => :modified_at
|
11
|
+
node(:answer_id){|r| r.answer.api_id }
|
12
|
+
node(:question_id){|r| r.question.api_id }
|
13
|
+
node(:value, :if => lambda{|r| r.answer.response_class != "answer"}){|r| r.as(r.answer.response_class) }
|
14
|
+
end
|
data/config/routes.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
|
-
match 'results', :to => 'results#index', :as => 'results', :via => :get
|
3
|
-
match 'results/:survey_code', :to => 'results#show', :as => 'result', :via => :get
|
4
2
|
match 'surveys', :to => 'surveyor#new', :as => 'available_surveys', :via => :get
|
5
3
|
match 'surveys/:survey_code', :to => 'surveyor#create', :as => 'take_survey', :via => :post
|
4
|
+
match 'surveys/:survey_code', :to => 'surveyor#export', :as => 'export_survey', :via => :get
|
6
5
|
match 'surveys/:survey_code/:response_set_code', :to => 'surveyor#show', :as => 'view_my_survey', :via => :get
|
7
6
|
match 'surveys/:survey_code/:response_set_code/take', :to => 'surveyor#edit', :as => 'edit_my_survey', :via => :get
|
8
7
|
match 'surveys/:survey_code/:response_set_code', :to => 'surveyor#update', :as => 'update_my_survey', :via => :put
|
9
|
-
end
|
8
|
+
end
|