surveyor 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +0 -6
  3. data/README.md +40 -14
  4. data/app/helpers/surveyor_helper.rb +1 -85
  5. data/app/views/partials/_answer.html.haml +5 -4
  6. data/app/views/partials/_question.html.haml +7 -5
  7. data/app/views/partials/_question_group.html.haml +2 -2
  8. data/app/views/surveyor/export.json.rabl +75 -0
  9. data/app/views/surveyor/show.html.haml +75 -13
  10. data/app/views/surveyor/show.json.rabl +14 -0
  11. data/config/routes.rb +2 -3
  12. data/doc/surveyor reject or delete decision matrix.png +0 -0
  13. data/features/export_to_json.feature +96 -0
  14. data/features/show_survey.feature +42 -0
  15. data/features/step_definitions/{common_setps.rb → common_steps.rb} +0 -0
  16. data/features/step_definitions/surveyor_steps.rb +46 -12
  17. data/features/step_definitions/web_steps.rb +15 -5
  18. data/features/support/paths.rb +2 -1
  19. data/features/surveyor.feature +192 -41
  20. data/features/surveyor_parser.feature +10 -10
  21. data/features/{redcap_parser.feature → z_redcap_parser.feature} +9 -6
  22. data/lib/formtastic/surveyor_builder.rb +1 -4
  23. data/lib/generators/surveyor/install_generator.rb +6 -5
  24. data/lib/generators/surveyor/templates/db/migrate/add_api_id_to_question_groups.rb +9 -0
  25. data/lib/generators/surveyor/templates/db/migrate/add_api_ids_to_response_sets_and_responses.rb +11 -0
  26. data/lib/generators/surveyor/templates/public/javascripts/surveyor/jquery-ui-timepicker-addon.js +1277 -0
  27. data/lib/generators/surveyor/templates/public/javascripts/surveyor/jquery-ui.js +11729 -0
  28. data/lib/generators/surveyor/templates/public/javascripts/surveyor/jquery.surveyor.js +54 -10
  29. data/lib/generators/surveyor/templates/public/stylesheets/sass/surveyor.sass +1 -1
  30. data/lib/generators/surveyor/templates/public/stylesheets/surveyor/jquery-ui-timepicker-addon.css +6 -0
  31. data/lib/generators/surveyor/templates/public/stylesheets/surveyor/jquery-ui.custom.css +572 -0
  32. data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  33. data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  34. data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-bg_glass_65_ffffff_1x400.png +0 -0
  35. data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  36. data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  37. data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-icons_ef8c08_256x240.png +0 -0
  38. data/lib/generators/surveyor/templates/public/stylesheets/surveyor/ui-icons_ffffff_256x240.png +0 -0
  39. data/lib/generators/surveyor/templates/surveys/EXTENDING_SURVEYOR.md +14 -0
  40. data/lib/generators/surveyor/templates/surveys/MODIFYING_SURVEYOR.md +91 -0
  41. data/lib/generators/surveyor/templates/surveys/date_survey.rb +15 -0
  42. data/lib/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +2 -2
  43. data/lib/surveyor/common.rb +31 -4
  44. data/lib/surveyor/helpers/surveyor_helper_methods.rb +99 -0
  45. data/lib/surveyor/models/answer_methods.rb +6 -5
  46. data/lib/surveyor/models/dependency_condition_methods.rb +0 -1
  47. data/lib/surveyor/models/dependency_methods.rb +1 -1
  48. data/lib/surveyor/models/question_group_methods.rb +5 -0
  49. data/lib/surveyor/models/question_methods.rb +5 -2
  50. data/lib/surveyor/models/response_methods.rb +44 -3
  51. data/lib/surveyor/models/response_set_methods.rb +14 -4
  52. data/lib/surveyor/models/survey_methods.rb +8 -2
  53. data/lib/surveyor/models/survey_section_methods.rb +13 -1
  54. data/lib/surveyor/parser.rb +18 -11
  55. data/lib/surveyor/render_text.rb +19 -0
  56. data/lib/surveyor/surveyor_controller_methods.rb +19 -1
  57. data/lib/surveyor/unparser.rb +1 -1
  58. data/lib/surveyor/version.rb +1 -1
  59. data/lib/tasks/surveyor_tasks.rake +1 -1
  60. data/spec/controllers/surveyor_controller_spec.rb +7 -3
  61. data/spec/helpers/surveyor_helper_spec.rb +104 -9
  62. data/spec/lib/chinese_survey.rb +14 -0
  63. data/spec/lib/common_spec.rb +52 -1
  64. data/spec/lib/rake_kitchen_sink.rb +40 -0
  65. data/spec/models/answer_spec.rb +11 -0
  66. data/spec/models/question_spec.rb +15 -0
  67. data/spec/models/response_set_spec.rb +45 -1
  68. data/spec/models/response_spec.rb +7 -4
  69. data/surveyor.gemspec +4 -2
  70. metadata +99 -40
  71. data/app/controllers/results_controller.rb +0 -13
  72. data/app/views/results/index.html.erb +0 -17
  73. data/app/views/results/show.html.erb +0 -25
data/.gitignore CHANGED
@@ -24,3 +24,4 @@ reports
24
24
  testbed
25
25
  surveys/fixtures/*.yml
26
26
  .rvmrc
27
+ .sass-cache/**/*.sassc
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 (add add haml too if you haven't already):
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
- `bundle install`
64
+ bundle install
66
65
 
67
66
  2. Generate assets, run migrations:
68
67
 
69
- `script/rails generate surveyor:install`
70
- `rake db:migrate`
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
- `rake surveyor FILE=surveys/kitchen_sink_survey.rb`
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 for removing (only surveys without responses) and un-parsing (from db to DSL file) surveys:
79
+ There are two other useful rake tasks:
83
80
 
84
- `rake surveyor:remove`
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.x
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
- # Layout: stylsheets and javascripts
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
- "&nbsp;&nbsp;You answered &quot;#{trigger_responses.join("&quot; and &quot;")}&quot; to the question &quot;#{dependent_questions.map(&:text).join("&quot;,&quot;")}&quot;"
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? ? "&nbsp;" : text.split("|")[0], :postfix => text.split("|")[1] || "&nbsp;"}
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
- = f.inputs q_text(q), :id => rg ? "q_#{q.id}_#{rg}" : "q_#{q.id}", :class => "q_#{renderer} #{q.css_class(@response_set)}" do
5
- %span.help= q.help_text
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
- = render a.custom_renderer || '/partials/answer', :q => q, :a => a, :f => f, :rg => rg, :g => g
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.help_text
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
- - @survey.sections.each do |section|
3
- - div_for section do
4
- .title= section.title
5
- .questions
6
- - group_questions ||= []
7
- - section.questions.each_with_index do |question, index|
8
- - if question.part_of_group?
9
- - group_questions << question
10
- - if (index + 1 >= section.questions.size) or (question.question_group_id != section.questions[index + 1].question_group_id)
11
- - # skip to the last question of the section, or the last question of the group
12
- = render(:partial => "/partials/question_group", :locals => {:question_group => question.question_group, :response_set => @response_set, :group_questions => group_questions})
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 &nbsp;
43
+ - ten_questions.first.answers.each do |a|
44
+ %th= a_text(a)
45
+ %th &nbsp;
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
- - else
15
- = render(:partial => "/partials/question", :locals => {:question => question, :response_set => @response_set})
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