datashift_journey 0.1.2 → 0.1.3

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.
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