datashift_journey 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/datashift_journey/abandonments_controller.rb +4 -0
  3. data/app/controllers/datashift_journey/errors_controller.rb +2 -2
  4. data/app/controllers/datashift_journey/journey_plans_controller.rb +19 -46
  5. data/app/controllers/datashift_journey/reviews_controller.rb +1 -1
  6. data/app/forms/datashift_journey/collector/base_collector_form.rb +28 -3
  7. data/app/views/datashift_journey/errors/401.html.erb +0 -2
  8. data/app/views/datashift_journey/errors/403.html.erb +0 -2
  9. data/app/views/datashift_journey/errors/404.html.erb +0 -2
  10. data/app/views/datashift_journey/errors/422.html.erb +0 -2
  11. data/app/views/datashift_journey/errors/500.html.erb +0 -2
  12. data/app/views/datashift_journey/errors/503.html.erb +0 -2
  13. data/app/views/datashift_journey/errors/invalid_authenticity_token.html.erb +0 -2
  14. data/app/views/datashift_journey/journey_plans/_render_fields.html.erb +1 -1
  15. data/lib/datashift_journey/engine.rb +1 -0
  16. data/{app/forms/datashift_journey/concerns → lib/datashift_journey}/form_mixin.rb +11 -1
  17. data/lib/datashift_journey/prepare_data_for_review.rb +212 -216
  18. data/lib/datashift_journey/version.rb +1 -1
  19. data/lib/generators/datashift_journey/collector/templates/collector_migration.rb.tt +3 -1
  20. metadata +3 -7
  21. data/app/controllers/datashift_journey/abandon_enrollments_controller.rb +0 -14
  22. data/app/controllers/datashift_journey/page_states_controller.rb +0 -49
  23. data/app/serializers/datashift_journey/collector/page_state_serializer.rb +0 -9
  24. data/app/serializers/state_machines/state/state_serializer.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c69a2e39ef25608483ad7d2597251e7a3579c8b40cfb62c77bce84e51bceca9
4
- data.tar.gz: 272adc891084777add171f204ce3f39f7b768ed34effde573288ca7e3939cc0f
3
+ metadata.gz: 38960531f2efc930e4265265c45c32e6287ee5a85ae83769ad1c5017aa7ba35e
4
+ data.tar.gz: 472072a1e034aed32958819e0156721ecb2366228eb99460232b2b9e440d262d
5
5
  SHA512:
6
- metadata.gz: cf5f9ab13ff5643093f7daac5fcbcfc9cfb08f7e843b9e07cfa701978905e64a125f74d309e752cc600010e6feb222a274c274b4b0a1d2db5df3e13f7c5acafd
7
- data.tar.gz: 00c8c8b31b4094289182568be0a93e2f22942978105118dd41318aef9cdc07f9e9e0d5039180861c71245739f666b1233693e7350fc8dfb3342e07b9f6c27416
6
+ metadata.gz: 8e320a5ea4b6791988f29d866efd0e3f0304c32d79ebe3a3f2c6adf0c040169ee9c881b97b793e12b36276434f68619a56994f662d5e6597b2db1d945bc474e8
7
+ data.tar.gz: 60fb3beea2b19076906b53b1b70b0b2f792f96551f1b835a1e41430d902a706d435d5407ca1c14c9e525d3c294002f24f1c15ddb28e518ef8c7a14de897baeb1
@@ -10,6 +10,10 @@ module DatashiftJourney
10
10
 
11
11
  def show
12
12
  logger.info('User has abandoned')
13
+
14
+ # high voltage expects id => name of page
15
+ # params[:id] = params['page']
16
+
13
17
  super
14
18
  end
15
19
  end
@@ -1,7 +1,7 @@
1
1
  module DatashiftJourney
2
2
  class ErrorsController < ApplicationController
3
3
  def show
4
- @exception = env['action_dispatch.exception']
4
+ @exception = request.env['action_dispatch.exception']
5
5
  action = request.path[1..-1].gsub(/[^0-9]/, '')
6
6
  action = 500 if action.blank?
7
7
 
@@ -10,7 +10,7 @@ module DatashiftJourney
10
10
  trace = Rails.backtrace_cleaner.clean(@exception.backtrace)
11
11
  Rails.logger.fatal trace.join("#\n")
12
12
 
13
- ActionDispatch::ExceptionWrapper.new(env, @exception).status_code
13
+ ActionDispatch::ExceptionWrapper.new(request.env, @exception).status_code
14
14
  else
15
15
  action.to_i
16
16
  end
@@ -9,7 +9,7 @@ module DatashiftJourney
9
9
  # Run BEFORE other filters to ensure the current journey_plan has been selected from the DB
10
10
  prepend_before_action :set_journey_plan, only: [:new, :destroy, :back_a_state]
11
11
 
12
- prepend_before_action :set_reform_object, only: [:create, :edit, :update]
12
+ prepend_before_action :set_reform_object, only: [:edit, :update]
13
13
 
14
14
  # Validate state and state related params - covers certain edge cases such as browser refresh
15
15
  before_action :validate_state, only: [:edit, :update]
@@ -22,35 +22,12 @@ module DatashiftJourney
22
22
  end
23
23
 
24
24
  def create
25
- # TOFIX - Validation from params is now broken
26
- # NoMethodError (undefined method `each_with_index' for #<ActionController::Parameters:0x000055eacfa2c370>):
27
- # result = form.validate(params)
28
- # logger.debug("VALIDATION FAILED - Form Errors [#{form.errors.inspect}]") unless result
29
- journey_plan = journey_plan_class.new
25
+ set_journey_plan_class
26
+ @reform = FormObjectFactory.form_object_for(journey_plan_class.create!)
30
27
 
31
- form_fields_to_data_nodes
28
+ @reform.save(params)
32
29
 
33
- move_next(journey_plan)
34
- end
35
-
36
- def back_a_state
37
- respond_to do |format|
38
- logger.debug("BACK Requested - current [#{journey_plan.state}] - previous [#{journey_plan.previous_state_name}]")
39
-
40
- journey_plan.back!
41
-
42
- if journey_plan.save
43
-
44
- logger.debug("Successfully back a step - state now [#{journey_plan.state}]")
45
-
46
- format.html do
47
- redirect_to(datashift_journey.journey_plan_state_path(journey_plan.state, journey_plan)) && return
48
- end
49
-
50
- else
51
- format.html { render :edit }
52
- end
53
- end
30
+ move_next(@reform.journey_plan)
54
31
  end
55
32
 
56
33
  def edit
@@ -74,7 +51,7 @@ module DatashiftJourney
74
51
  # render :edit, locals: { journey_plan: journey_plan, form: form }
75
52
  # end
76
53
 
77
- form_fields_to_data_nodes
54
+ @reform.save(params)
78
55
 
79
56
  logger.debug("UPDATED Plan [#{journey_plan.inspect}] - Move to Next")
80
57
  puts journey_plan.inspect
@@ -82,26 +59,22 @@ module DatashiftJourney
82
59
  move_next(journey_plan) && return
83
60
  end # UPDATE
84
61
 
85
- def form_fields_to_data_nodes
86
- form_params = params.fetch(@reform.params_key, {})
87
-
88
- data_nodes = form_params["data_nodes"] # =>{"form_field"=>{"0"=>"name", "1"=>"namespace"}, "field_value"=>{"0"=>"dfsdf", "1"=>"ghfghf"}}}
62
+ def back_a_state
63
+ respond_to do |format|
64
+ logger.debug("BACK Requested - current [#{journey_plan.state}] - previous [#{journey_plan.previous_state_name}]")
89
65
 
90
- if data_nodes.present?
66
+ journey_plan.back!
91
67
 
92
- fields = data_nodes["form_field"]
93
- values = data_nodes["field_value"]
68
+ if journey_plan.save
94
69
 
95
- fields.each do |idx, name|
96
- ff = Collector::FormField.where(name: name, form_definition: @reform.definition).first
97
- next unless ff
70
+ logger.debug("Successfully back a step - state now [#{journey_plan.state}]")
98
71
 
99
- # Ensure when user goes back and changes a value we reflect the changed value
100
- Collector::DataNode.find_or_initialize_by(plan: journey_plan, form_field: ff).tap do |node|
101
- node.field_value = values[idx]
102
- node.save
72
+ format.html do
73
+ redirect_to(datashift_journey.journey_plan_state_path(journey_plan.state, journey_plan)) && return
103
74
  end
104
75
 
76
+ else
77
+ format.html { render :edit }
105
78
  end
106
79
  end
107
80
  end
@@ -114,13 +87,13 @@ module DatashiftJourney
114
87
  redirect_to(@reform.redirection_url) && return if @reform.redirect?
115
88
 
116
89
  if journey_plan.next_state_name.blank?
117
- logger.error("JOURNEY ENDED - no next transition - rendering 'journey_end'")
90
+ logger.info("JOURNEY ENDED - no skip_fwd transition - rendering 'journey_end'")
118
91
  redirect_to(datashift_journey.journey_end_path(journey_plan)) && return
119
92
  end
120
93
 
121
- # if there is no next event, state_machine dynamic helper can_next? not available
94
+ # if there is no skip_fwd event, state_machine dynamic helper skip_fwd? not available
122
95
  unless journey_plan.respond_to?('can_skip_fwd?') && journey_plan.can_skip_fwd?
123
- logger.error("JOURNEY Cannot proceed - no next transition - rendering 'journey_end'")
96
+ logger.info("JOURNEY ENDED - no skip_fwd transition to - rendering 'journey_end'")
124
97
  redirect_to(datashift_journey.journey_end_path(journey_plan)) && return
125
98
  end
126
99
 
@@ -7,7 +7,7 @@ module DatashiftJourney
7
7
  # We want this to run BEFORE other filters to ensure the current
8
8
  # journey_plan object has been selected from the DB
9
9
 
10
- prepend_before_filter :set_journey_plan, only: [:edit]
10
+ prepend_before_action :set_journey_plan, only: [:edit]
11
11
 
12
12
  def edit
13
13
  logger.info("Sent from REVIEW [#{params.inspect}]")
@@ -1,5 +1,3 @@
1
- require_relative '../concerns/form_mixin'
2
-
3
1
  module DatashiftJourney
4
2
  module Collector
5
3
 
@@ -16,7 +14,7 @@ module DatashiftJourney
16
14
  #
17
15
  class BaseCollectorForm < Reform::Form
18
16
 
19
- include DatashiftJourney::FormMixin
17
+ include ::DatashiftJourney::FormMixin
20
18
 
21
19
  feature Reform::Form::Dry # override the default.
22
20
 
@@ -45,6 +43,33 @@ module DatashiftJourney
45
43
 
46
44
  end
47
45
 
46
+ def save(params)
47
+ form_params = params.fetch(params_key, {})
48
+
49
+ data_nodes = form_params["data_nodes"] # =>{"form_field"=>{"0"=>"name", "1"=>"namespace"}, "field_value"=>{"0"=>"dfsdf", "1"=>"ghfghf"}}}
50
+
51
+ if data_nodes.present?
52
+
53
+ fields = data_nodes["form_field"]
54
+ values = data_nodes["field_value"]
55
+
56
+ fields.each do |idx, name|
57
+ ff = Collector::FormField.where(name: name, form_definition: definition).first
58
+ next unless ff
59
+
60
+ # Ensure when user goes back and changes a value we reflect the changed value
61
+
62
+ pp journey_plan
63
+
64
+ Collector::DataNode.find_or_initialize_by(plan: journey_plan, form_field: ff).tap do |node|
65
+ node.field_value = values[idx]
66
+ node.save
67
+ end
68
+
69
+ end
70
+ end
71
+ end
72
+
48
73
  # Over ride in your form if your view forms have non standard key field.
49
74
  #
50
75
  # The default naming format for form elements in the view is : "#{params_key}[data_nodes][field_value][#{i}]"
@@ -1,5 +1,3 @@
1
- <% content_for :page_title, create_title('global.401_unauthorized.heading') + " (#{response.status})" %>
2
-
3
1
  <%= yield :error_header %>
4
2
 
5
3
  <header>
@@ -1,5 +1,3 @@
1
- <% content_for :page_title, create_title('global.403_forbidden.heading') + " (#{response.status})" %>
2
-
3
1
  <%= yield :error_header %>
4
2
 
5
3
  <header>
@@ -1,5 +1,3 @@
1
- <% content_for :page_title, create_title('global.404_notfound.heading') + " (#{response.status})" %>
2
-
3
1
  <%= yield :error_header %>
4
2
 
5
3
  <header>
@@ -1,5 +1,3 @@
1
- <% content_for :page_title, create_title('global.422_unprocessable_entity.heading') + " (#{response.status})" %>
2
-
3
1
  <%= yield :error_header %>
4
2
 
5
3
  <header>
@@ -1,5 +1,3 @@
1
- <% content_for :page_title, create_title('global.500_internal_server_error.heading') + " (#{response.status})" %>
2
-
3
1
  <%= yield :error_header %>
4
2
 
5
3
  <header>
@@ -1,5 +1,3 @@
1
- <% content_for :page_title, create_title('global.503_bad_gateway.heading') + " (#{response.status})" %>
2
-
3
1
  <%= yield :error_header %>
4
2
 
5
3
  <header>
@@ -1,5 +1,3 @@
1
- <% content_for :page_title, create_title('global.invalid_authenticity_token.heading') %>
2
-
3
1
  <%= yield :error_header %>
4
2
 
5
3
  <header>
@@ -16,7 +16,7 @@
16
16
  <% elsif data_node.form_field.number? %>
17
17
  <%= number_field_tag "#{key}[data_nodes][field_value][#{i}]", data_node.field_value, { class: 'form-control', required: true } %>
18
18
  <% else %>
19
- <%= text_field_tag "#{key}[data_nodes][field_value][#{i}]", data_node.field_value, size: "64", class: "form-control", required: true %>
19
+ <%= text_field_tag "#{key}[data_nodes][field_value][#{i}]", data_node.field_value, { size: "64", class: "form-control", required: true } %>
20
20
  <% end %>
21
21
 
22
22
  </div>
@@ -2,6 +2,7 @@ begin
2
2
  require_relative 'exceptions'
3
3
  require_relative 'configuration'
4
4
  require_relative 'journey/machine_builder'
5
+ require_relative 'form_mixin'
5
6
 
6
7
  require_relative 'reference_generator'
7
8
  require_relative 'helpers/back_link'
@@ -27,7 +27,12 @@ module DatashiftJourney
27
27
 
28
28
  def form_definition
29
29
  # In this situation self is the class of the including form eg PaymentForm, AddressFrom
30
- @form_definition ||= DatashiftJourney::Collector::FormDefinition.find_or_create_by!(klass: self.name)
30
+ begin
31
+ @form_definition ||= DatashiftJourney::Collector::FormDefinition.find_or_create_by(klass: self.name)
32
+ rescue
33
+ Rails.logger.error "Could not find or create FormDefinition [#{x}]"
34
+ nil
35
+ end
31
36
  end
32
37
 
33
38
  # Form helper to add fields inside a class definition
@@ -42,7 +47,12 @@ module DatashiftJourney
42
47
  # journey_plan_form_field name: :memory, category: :number
43
48
  #
44
49
  def journey_plan_form_field(name:, category:)
50
+ begin
45
51
  DatashiftJourney::Collector::FormField.find_or_create_by!(form_definition: form_definition, name: name, category: category)
52
+ rescue => x
53
+ Rails.logger.error "Could not find or create FormField [#{x}]"
54
+ nil
55
+ end
46
56
  end
47
57
  end
48
58
 
@@ -1,219 +1,215 @@
1
1
  module DatashiftJourney
2
2
 
3
- # module PrepareDataForReview
4
- #
5
- # extend ActiveSupport::Concern
6
- #
7
- # def self.included(base)
8
- # base.send :include, InstanceMethods
9
- # end
10
- #
11
- # module InstanceMethods
12
- #
13
- # # You can build your review page within a YAML config file (locale file)
14
- # # It supports a simple DSL in below format.
15
- # #
16
- # # SYNTAX :
17
- # # Indentation, usually 2 spaces, or a 2 space TAB, is very important
18
- # # <> are used to illustrate the elements that accept free text
19
- # #
20
- # # ROW :
21
- # #
22
- # # Each ReviewDataRow has upto 3 elements
23
- # #
24
- # # :title: The string for Column 1, the row header
25
- # #
26
- # # :method: The actual database data for Column2, method to call on the model, or the association object
27
- # #
28
- # # :link_state: The state the change me links, jumps back to.
29
- # # Optional, if unspecified, uses the section block (state)
30
- # #
31
- # # FULL DSL :
32
- # #
33
- # # <key>:
34
- # # sections:
35
- # # <section_block - usually a state>: # The Link target defaults to this, if no explicit state set
36
- # # section_heading: "Farming data" # The section title - that spans the 3 columns
37
- # # direct: # Non association data i.e directly on the parent model
38
- # # - :title: "Activity is on a farm" # Column title. The - indicates a list, each mini block is a row
39
- # # :method: on_a_farm # Method called on association to get real (DB) data to display
40
- # # - :title: "Registrant is a farmer" # Next mini block - Each section can have multiple rows
41
- # # :method: is_a_farmer
42
- # # <next section_block - choosing_site_address>:
43
- # # section_heading: Waste Activity Location
44
- # # associations:
45
- # # <association> # As well as direct, supports Rails associations, on supplied model
46
- # # - :title: "1st Column"
47
- # # :method: full_name # Ruby method called on association, returns real (DB) data to display
48
- # # :link_state: state # The link target - i.e state to JUMP to, in order to EDIT the data
49
- # # site_address: # Again, section can contain multiple rows, from multiple associations
50
- # # - :title: "Address"
51
- # # :method: # No method supplied, data will be WHOLE associated object
52
- # #
53
- # # EXAMPLE:
54
- # #
55
- # # journey_plan_review:
56
- # # sections:
57
- # # choosing_farming_data:
58
- # # section_heading: "Farming data"
59
- # # direct:
60
- # # - :title: "Activity is on a farm"
61
- # # :method: on_a_farm
62
- # # - :title: "Registrant is a farmer"
63
- # # :method: is_a_farmer
64
- # # choosing_site_address:
65
- # # section_heading: Waste Activity Location
66
- # # associations:
67
- # # site_address:
68
- # # - :title: "Address"
69
- # # :method: # No state cos Partial can render WHOLE Address object
70
- # # - :title: "Grid reference"
71
- # # :method: grid_reference
72
- # # choosing_exemption:
73
- # # section_heading: Waste Exemption Codes
74
- # # associations:
75
- # # exemption:
76
- # # - :title: "Waste Exemptions"
77
- # # :method: code
78
- # #
79
- # # NOTES
80
- # #
81
- # # Method can be left blank, in this case the data is the association object, so this must be display-able
82
- # #
83
- # # For example, this will cause @journey_plan.site_address to be sent to the review partial, which we know has
84
- # # special use case for Address, which renders a display address partial
85
- # #
86
- # # site_address:
87
- # # - :title: "Address"
88
- # # :method:
89
- # #
90
- # attr_reader :review_data
91
- #
92
- # # rubocop:disable Metrics/MethodLength
93
- #
94
- # def prepare_from_locale(model, locale_key = '.journey_plan_review')
95
- # sections = I18n.t("#{locale_key}.sections", default: {})
96
- #
97
- # Rails.logger.debug("Review Sections: #{sections.inspect}")
98
- #
99
- # unless sections.is_a?(Hash)
100
- # Rails.logger.error("Bad syntax in your review YAML - Expect a 'sections' Hash element")
101
- # raise "Bad syntax in your review YAML - Expect a 'sections' Hash element"
102
- # end
103
- #
104
- # @model_object = model
105
- #
106
- # # Return a collection of Sections (ReviewData), each section has multiple rows
107
- #
108
- # sections.collect do |section, data|
109
- # next unless data[:section_heading]
110
- #
111
- # @current_section = section
112
- #
113
- # @review_data = ReviewDataSection.new(data[:section_heading])
114
- #
115
- # # Possible Enhancement required :
116
- # # As it stands this will NOT preserve the Order as defined exactly in the YAML as it's a HASH
117
- # # with keys - for direct & association sections - which are unordered.
118
- # # So currently had to make arbitrary decision to process direct first, then associations
119
- #
120
- # # Direct data on parent Model, where key is - direct:
121
- # key = "#{locale_key}.sections.#{section}.direct"
122
- #
123
- # I18n.t(key).each { |column| row_to_review_data(model_object, column) } if I18n.exists?(key)
124
- #
125
- # # Associated data - children of parent
126
- # key = "#{locale_key}.sections.#{current_section}.associations"
127
- #
128
- # if I18n.exists?(key)
129
- #
130
- # association_list = I18n.t("#{locale_key}.sections.#{current_section}.associations", default: [])
131
- #
132
- # association_list.each do |association_data|
133
- # unless association_data.size == 2
134
- # Rails.logger.error('Bad syntax in your review YAML - expect each association to have name and fields')
135
- # next
136
- # end
137
- #
138
- # # Each association should have a row defined as a list i.e Array
139
- # # - :title: Business trading name
140
- # # :name: full_name
141
- # #
142
- # unless association_data[1].respond_to?(:each)
143
- # Rails.logger.error('Bad syntax in review YAML - each row needs a title, method and optional link')
144
- # next
145
- # end
146
- #
147
- # # The first element is the association name or chain,
148
- # # i.e method(s) to call on the parent model to reach child with the actual data
149
- # association_method = association_data[0].to_s
150
- #
151
- # review_object = begin
152
- # find_association(association_method)
153
- # rescue => e
154
- # Rails.logger.error(e.message)
155
- # Rails.logger.error("Bad syntax in review YAML - Could not load associated object #{association_method}")
156
- # next
157
- # end
158
- #
159
- # unless review_object
160
- # Rails.logger.error("Nil association for #{association_method} on #{model} - no review data available")
161
- # next
162
- # end
163
- #
164
- # # The second element is a list of rows, made up of title, method to call on association and the state link
165
- # association_data[1].each { |column| row_to_review_data(review_object, column) }
166
- # end
167
- # end
168
- #
169
- # review_data
170
- # end
171
- # end
172
- #
173
- # private
174
- #
175
- # attr_accessor :current_section, :current_review_object, :review_data
176
- #
177
- # attr_accessor :model_object
178
- #
179
- # def row_to_review_data(review_object, row)
180
- # # The section name, can be used as the state, for linking whole section, rather than at field level
181
- # link_state = row[:link_state] || current_section
182
- # link_title = row[:link_title]
183
- #
184
- # @current_review_object = review_object
185
- #
186
- # # The review partial can support whole objects, or low level data from method call defined in the DSL
187
- # if row[:method].blank?
188
- # review_data.add(row[:title], review_object, link_state.to_s, link_title)
189
- # else
190
- # # rubocop:disable Style/IfInsideElse
191
- # if review_object.respond_to?(:each)
192
- # review_object.each do |o|
193
- # @current_review_object = o
194
- # review_data.add(row[:title], send_chain(row[:method]), link_state.to_s, link_title)
195
- # end
196
- # else
197
- # review_data.add(row[:title], send_chain(row[:method]), link_state.to_s, link_title)
198
- # end
199
- #
200
- # end
201
- # end
202
- #
203
- # def find_association(method_chain)
204
- # method_chain.to_s.split('.').inject(model_object) { |a, e| a.send(e) }
205
- # end
206
- #
207
- # def send_chain(method_chain)
208
- # arr = method_chain.to_s.split('.')
209
- # begin
210
- # arr.inject(current_review_object) { |a, e| a.send(e) }
211
- # rescue => e
212
- # Rails.logger.error("Failed to process method chain #{method_chain} : #{e.message}")
213
- # return I18n.t('.journey_plan_review.missing_data')
214
- # end
215
- # end
216
- #
217
- # end
218
- # end
3
+ module PrepareDataForReview
4
+ extend ActiveSupport::Concern
5
+
6
+
7
+ # module InstanceMethods
8
+ #
9
+ # # You can build your review page within a YAML config file (locale file)
10
+ # # It supports a simple DSL in below format.
11
+ # #
12
+ # # SYNTAX :
13
+ # # Indentation, usually 2 spaces, or a 2 space TAB, is very important
14
+ # # <> are used to illustrate the elements that accept free text
15
+ # #
16
+ # # ROW :
17
+ # #
18
+ # # Each ReviewDataRow has upto 3 elements
19
+ # #
20
+ # # :title: The string for Column 1, the row header
21
+ # #
22
+ # # :method: The actual database data for Column2, method to call on the model, or the association object
23
+ # #
24
+ # # :link_state: The state the change me links, jumps back to.
25
+ # # Optional, if unspecified, uses the section block (state)
26
+ # #
27
+ # # FULL DSL :
28
+ # #
29
+ # # <key>:
30
+ # # sections:
31
+ # # <section_block - usually a state>: # The Link target defaults to this, if no explicit state set
32
+ # # section_heading: "Farming data" # The section title - that spans the 3 columns
33
+ # # direct: # Non association data i.e directly on the parent model
34
+ # # - :title: "Activity is on a farm" # Column title. The - indicates a list, each mini block is a row
35
+ # # :method: on_a_farm # Method called on association to get real (DB) data to display
36
+ # # - :title: "Registrant is a farmer" # Next mini block - Each section can have multiple rows
37
+ # # :method: is_a_farmer
38
+ # # <next section_block - choosing_site_address>:
39
+ # # section_heading: Waste Activity Location
40
+ # # associations:
41
+ # # <association> # As well as direct, supports Rails associations, on supplied model
42
+ # # - :title: "1st Column"
43
+ # # :method: full_name # Ruby method called on association, returns real (DB) data to display
44
+ # # :link_state: state # The link target - i.e state to JUMP to, in order to EDIT the data
45
+ # # site_address: # Again, section can contain multiple rows, from multiple associations
46
+ # # - :title: "Address"
47
+ # # :method: # No method supplied, data will be WHOLE associated object
48
+ # #
49
+ # # EXAMPLE:
50
+ # #
51
+ # # journey_plan_review:
52
+ # # sections:
53
+ # # choosing_farming_data:
54
+ # # section_heading: "Farming data"
55
+ # # direct:
56
+ # # - :title: "Activity is on a farm"
57
+ # # :method: on_a_farm
58
+ # # - :title: "Registrant is a farmer"
59
+ # # :method: is_a_farmer
60
+ # # choosing_site_address:
61
+ # # section_heading: Waste Activity Location
62
+ # # associations:
63
+ # # site_address:
64
+ # # - :title: "Address"
65
+ # # :method: # No state cos Partial can render WHOLE Address object
66
+ # # - :title: "Grid reference"
67
+ # # :method: grid_reference
68
+ # # choosing_exemption:
69
+ # # section_heading: Waste Exemption Codes
70
+ # # associations:
71
+ # # exemption:
72
+ # # - :title: "Waste Exemptions"
73
+ # # :method: code
74
+ # #
75
+ # # NOTES
76
+ # #
77
+ # # Method can be left blank, in this case the data is the association object, so this must be display-able
78
+ # #
79
+ # # For example, this will cause @journey_plan.site_address to be sent to the review partial, which we know has
80
+ # # special use case for Address, which renders a display address partial
81
+ # #
82
+ # # site_address:
83
+ # # - :title: "Address"
84
+ # # :method:
85
+ # #
86
+ # attr_reader :review_data
87
+ #
88
+ # # rubocop:disable Metrics/MethodLength
89
+ #
90
+ # def prepare_from_locale(model, locale_key = '.journey_plan_review')
91
+ # sections = I18n.t("#{locale_key}.sections", default: {})
92
+ #
93
+ # Rails.logger.debug("Review Sections: #{sections.inspect}")
94
+ #
95
+ # unless sections.is_a?(Hash)
96
+ # Rails.logger.error("Bad syntax in your review YAML - Expect a 'sections' Hash element")
97
+ # raise "Bad syntax in your review YAML - Expect a 'sections' Hash element"
98
+ # end
99
+ #
100
+ # @model_object = model
101
+ #
102
+ # # Return a collection of Sections (ReviewData), each section has multiple rows
103
+ #
104
+ # sections.collect do |section, data|
105
+ # next unless data[:section_heading]
106
+ #
107
+ # @current_section = section
108
+ #
109
+ # @review_data = ReviewDataSection.new(data[:section_heading])
110
+ #
111
+ # # Possible Enhancement required :
112
+ # # As it stands this will NOT preserve the Order as defined exactly in the YAML as it's a HASH
113
+ # # with keys - for direct & association sections - which are unordered.
114
+ # # So currently had to make arbitrary decision to process direct first, then associations
115
+ #
116
+ # # Direct data on parent Model, where key is - direct:
117
+ # key = "#{locale_key}.sections.#{section}.direct"
118
+ #
119
+ # I18n.t(key).each { |column| row_to_review_data(model_object, column) } if I18n.exists?(key)
120
+ #
121
+ # # Associated data - children of parent
122
+ # key = "#{locale_key}.sections.#{current_section}.associations"
123
+ #
124
+ # if I18n.exists?(key)
125
+ #
126
+ # association_list = I18n.t("#{locale_key}.sections.#{current_section}.associations", default: [])
127
+ #
128
+ # association_list.each do |association_data|
129
+ # unless association_data.size == 2
130
+ # Rails.logger.error('Bad syntax in your review YAML - expect each association to have name and fields')
131
+ # next
132
+ # end
133
+ #
134
+ # # Each association should have a row defined as a list i.e Array
135
+ # # - :title: Business trading name
136
+ # # :name: full_name
137
+ # #
138
+ # unless association_data[1].respond_to?(:each)
139
+ # Rails.logger.error('Bad syntax in review YAML - each row needs a title, method and optional link')
140
+ # next
141
+ # end
142
+ #
143
+ # # The first element is the association name or chain,
144
+ # # i.e method(s) to call on the parent model to reach child with the actual data
145
+ # association_method = association_data[0].to_s
146
+ #
147
+ # review_object = begin
148
+ # find_association(association_method)
149
+ # rescue => e
150
+ # Rails.logger.error(e.message)
151
+ # Rails.logger.error("Bad syntax in review YAML - Could not load associated object #{association_method}")
152
+ # next
153
+ # end
154
+ #
155
+ # unless review_object
156
+ # Rails.logger.error("Nil association for #{association_method} on #{model} - no review data available")
157
+ # next
158
+ # end
159
+ #
160
+ # # The second element is a list of rows, made up of title, method to call on association and the state link
161
+ # association_data[1].each { |column| row_to_review_data(review_object, column) }
162
+ # end
163
+ # end
164
+ #
165
+ # review_data
166
+ # end
167
+ # end
168
+ #
169
+ # private
170
+ #
171
+ # attr_accessor :current_section, :current_review_object, :review_data
172
+ #
173
+ # attr_accessor :model_object
174
+ #
175
+ # def row_to_review_data(review_object, row)
176
+ # # The section name, can be used as the state, for linking whole section, rather than at field level
177
+ # link_state = row[:link_state] || current_section
178
+ # link_title = row[:link_title]
179
+ #
180
+ # @current_review_object = review_object
181
+ #
182
+ # # The review partial can support whole objects, or low level data from method call defined in the DSL
183
+ # if row[:method].blank?
184
+ # review_data.add(row[:title], review_object, link_state.to_s, link_title)
185
+ # else
186
+ # # rubocop:disable Style/IfInsideElse
187
+ # if review_object.respond_to?(:each)
188
+ # review_object.each do |o|
189
+ # @current_review_object = o
190
+ # review_data.add(row[:title], send_chain(row[:method]), link_state.to_s, link_title)
191
+ # end
192
+ # else
193
+ # review_data.add(row[:title], send_chain(row[:method]), link_state.to_s, link_title)
194
+ # end
195
+ #
196
+ # end
197
+ # end
198
+ #
199
+ # def find_association(method_chain)
200
+ # method_chain.to_s.split('.').inject(model_object) { |a, e| a.send(e) }
201
+ # end
202
+ #
203
+ # def send_chain(method_chain)
204
+ # arr = method_chain.to_s.split('.')
205
+ # begin
206
+ # arr.inject(current_review_object) { |a, e| a.send(e) }
207
+ # rescue => e
208
+ # Rails.logger.error("Failed to process method chain #{method_chain} : #{e.message}")
209
+ # return I18n.t('.journey_plan_review.missing_data')
210
+ # end
211
+ # end
212
+ #
213
+ # end
214
+ end
219
215
  end
@@ -1,3 +1,3 @@
1
1
  module DatashiftJourney
2
- VERSION = '0.1.2'
2
+ VERSION = '0.1.3'
3
3
  end
@@ -14,10 +14,12 @@ class DatashiftJourneyCreateCollector < ActiveRecord::Migration[<%= @migration_v
14
14
  t.references :form_definition, index: true, null: false
15
15
  t.string :name, index: true, null: false, limit: 100
16
16
  t.integer :category, index: true, null: false
17
- t.text :presentation
17
+ t.jsonb :options, null: false, default: {}
18
18
  t.timestamps null: false
19
19
  end
20
20
 
21
+ add_index :dsj_form_fields, :options, using: :gin # see GIN vs GiST
22
+
21
23
  # The plan is an instance of a JourneyPlan class
22
24
  create_table :dsj_data_nodes do |t|
23
25
  t.references :plan, null: false, polymorphic: true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datashift_journey
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - tom statter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-16 00:00:00.000000000 Z
11
+ date: 2020-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -168,19 +168,16 @@ files:
168
168
  - app/controllers/concerns/datashift_journey/review_renderer.rb
169
169
  - app/controllers/concerns/datashift_journey/token_based_access.rb
170
170
  - app/controllers/concerns/datashift_journey/validate_state.rb
171
- - app/controllers/datashift_journey/abandon_enrollments_controller.rb
172
171
  - app/controllers/datashift_journey/abandonments_controller.rb
173
172
  - app/controllers/datashift_journey/api/v1/states_controller.rb
174
173
  - app/controllers/datashift_journey/application_controller.rb
175
174
  - app/controllers/datashift_journey/errors_controller.rb
176
175
  - app/controllers/datashift_journey/journey_ends_controller.rb
177
176
  - app/controllers/datashift_journey/journey_plans_controller.rb
178
- - app/controllers/datashift_journey/page_states_controller.rb
179
177
  - app/controllers/datashift_journey/reviews_controller.rb
180
178
  - app/controllers/datashift_journey/state_jumper_controller.rb
181
179
  - app/factories/datashift_journey/form_object_factory.rb
182
180
  - app/forms/datashift_journey/collector/base_collector_form.rb
183
- - app/forms/datashift_journey/concerns/form_mixin.rb
184
181
  - app/forms/datashift_journey/null_form.rb
185
182
  - app/helpers/datashift_journey/application_helper.rb
186
183
  - app/helpers/datashift_journey/back_link_helper.rb
@@ -189,8 +186,6 @@ files:
189
186
  - app/models/datashift_journey/collector/form_field.rb
190
187
  - app/models/datashift_journey/journey_review.rb
191
188
  - app/models/datashift_journey/review_data_section.rb
192
- - app/serializers/datashift_journey/collector/page_state_serializer.rb
193
- - app/serializers/state_machines/state/state_serializer.rb
194
189
  - app/views/datashift_journey/collector/_generic_form.html.erb
195
190
  - app/views/datashift_journey/errors/401.html.erb
196
191
  - app/views/datashift_journey/errors/403.html.erb
@@ -224,6 +219,7 @@ files:
224
219
  - lib/datashift_journey/configuration.rb
225
220
  - lib/datashift_journey/engine.rb
226
221
  - lib/datashift_journey/exceptions.rb
222
+ - lib/datashift_journey/form_mixin.rb
227
223
  - lib/datashift_journey/helpers/back_link.rb
228
224
  - lib/datashift_journey/journey/machine_builder.rb
229
225
  - lib/datashift_journey/prepare_data_for_review.rb
@@ -1,14 +0,0 @@
1
- module DatashiftJourney
2
- class AbandonEnrollmentsController < DatashiftJourney::AbandonmentsController
3
- # journey_plan object should been selected from the DB
4
- prepend_before_filter :set_journey_plan, only: [:show]
5
-
6
- def show
7
- logger.info("User has abandoned #{params}")
8
-
9
- # high voltage expects id => name of page
10
- params[:id] = params['page']
11
- super
12
- end
13
- end
14
- end
@@ -1,49 +0,0 @@
1
- module DatashiftJourney
2
- class FormsController < ActionController::API
3
-
4
- include DatashiftJourney::ErrorRenderer
5
-
6
- before_action :set_user, only: [:show, :update, :destroy]
7
-
8
- # PageState contains details for rendering and storing a Page related to a single State
9
- #
10
- def index
11
- @collector_forms = Collector::FormDefinition.all
12
-
13
- render json: @collector_forms, status: :ok
14
- end
15
-
16
- def create
17
- @collector_form = Collector::FormDefinition.new(page_state_params)
18
-
19
- if @collector_form.save
20
- render json: @collector_form, status: :created
21
- else
22
- render_error(@collector_form, :unprocessable_entity) and return
23
- #render json: { errors: @collector_form.errors }, status: :unprocessable_entity
24
- end
25
- end
26
-
27
- def show
28
- render json: @collector_form
29
- end
30
-
31
- private
32
-
33
- # Only allow a trusted parameter "white list" through.
34
- def page_state_params
35
- params.fetch(:page_state, {}).permit(:form_name)
36
- end
37
-
38
- def set_user
39
- begin
40
- @collector_form = Collector::FormDefinition.find params[:id]
41
- rescue ActiveRecord::RecordNotFound
42
- collector_form = Collector::FormDefinition.new
43
- collector_form.errors.add(:id, "Wrong ID provided")
44
- render_error(collector_form, 404) and return
45
- end
46
- end
47
-
48
- end
49
- end
@@ -1,9 +0,0 @@
1
- module DatashiftJourney
2
- module Collector
3
- class PageStateSerializer < ActiveModel::Serializer
4
- attributes :id, :form_name, :created_at
5
-
6
- link(:self) {page_state_url(object) }
7
- end
8
- end
9
- end
@@ -1,5 +0,0 @@
1
- module StateMachines
2
- class StateSerializer < ActiveModel::Serializer
3
- attributes :name, :value, :initial
4
- end
5
- end