datashift_journey 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.md +391 -0
- data/Rakefile +26 -0
- data/app/assets/stylesheets/datashift_journey/partials/_state_jumper_toolbar.scss.erb +27 -0
- data/app/controllers/concerns/datashift_journey/error_renderer.rb +9 -0
- data/app/controllers/concerns/datashift_journey/review_renderer.rb +21 -0
- data/app/controllers/concerns/datashift_journey/token_based_access.rb +23 -0
- data/app/controllers/concerns/datashift_journey/validate_state.rb +59 -0
- data/app/controllers/datashift_journey/abandon_enrollments_controller.rb +14 -0
- data/app/controllers/datashift_journey/abandonments_controller.rb +17 -0
- data/app/controllers/datashift_journey/api/v1/states_controller.rb +49 -0
- data/app/controllers/datashift_journey/application_controller.rb +53 -0
- data/app/controllers/datashift_journey/errors_controller.rb +24 -0
- data/app/controllers/datashift_journey/journey_ends_controller.rb +19 -0
- data/app/controllers/datashift_journey/journey_plans_controller.rb +166 -0
- data/app/controllers/datashift_journey/page_states_controller.rb +49 -0
- data/app/controllers/datashift_journey/reviews_controller.rb +32 -0
- data/app/controllers/datashift_journey/state_jumper_controller.rb +51 -0
- data/app/factories/datashift_journey/form_object_factory.rb +68 -0
- data/app/forms/datashift_journey/collector/base_collector_form.rb +60 -0
- data/app/forms/datashift_journey/concerns/form_mixin.rb +64 -0
- data/app/forms/datashift_journey/null_form.rb +20 -0
- data/app/helpers/datashift_journey/application_helper.rb +50 -0
- data/app/helpers/datashift_journey/back_link_helper.rb +9 -0
- data/app/models/datashift_journey/collector/data_node.rb +18 -0
- data/app/models/datashift_journey/collector/form_definition.rb +35 -0
- data/app/models/datashift_journey/collector/form_field.rb +61 -0
- data/app/models/datashift_journey/journey_review.rb +65 -0
- data/app/models/datashift_journey/review_data_section.rb +32 -0
- data/app/serializers/datashift_journey/collector/page_state_serializer.rb +9 -0
- data/app/serializers/state_machines/state/state_serializer.rb +5 -0
- data/app/views/datashift_journey/collector/_generic_form.html.erb +14 -0
- data/app/views/datashift_journey/errors/401.html.erb +13 -0
- data/app/views/datashift_journey/errors/403.html.erb +13 -0
- data/app/views/datashift_journey/errors/404.html.erb +13 -0
- data/app/views/datashift_journey/errors/422.html.erb +11 -0
- data/app/views/datashift_journey/errors/500.html.erb +13 -0
- data/app/views/datashift_journey/errors/503.html.erb +11 -0
- data/app/views/datashift_journey/errors/invalid_authenticity_token.html.erb +14 -0
- data/app/views/datashift_journey/journey_ends/new.html.erb +5 -0
- data/app/views/datashift_journey/journey_ends/show.html.erb +5 -0
- data/app/views/datashift_journey/journey_plans/_form.html.erb +14 -0
- data/app/views/datashift_journey/journey_plans/_render_fields.html.erb +24 -0
- data/app/views/datashift_journey/journey_plans/edit.html.erb +6 -0
- data/app/views/datashift_journey/journey_plans/new.html.erb +6 -0
- data/app/views/datashift_journey/shared/_default_actions.html.erb +6 -0
- data/app/views/datashift_journey/shared/_errors.html.erb +19 -0
- data/app/views/datashift_journey/shared/_submit_action.html.erb +5 -0
- data/app/views/datashift_journey/state_jumper/_toolbar.html.erb +16 -0
- data/config/brakeman.ignore +42 -0
- data/config/i18n-tasks.yml +103 -0
- data/config/initializers/exceptions_app.rb +3 -0
- data/config/initializers/mime_types.rb +1 -0
- data/config/initializers/rswag-api.rb +14 -0
- data/config/initializers/rswag-ui.rb +9 -0
- data/config/locales/en.yml +39 -0
- data/config/routes.rb +44 -0
- data/lib/datashift_journey/collector/field_snippet.rb +12 -0
- data/lib/datashift_journey/collector/page_state_snippet.rb +12 -0
- data/lib/datashift_journey/collector/snippet.rb +14 -0
- data/lib/datashift_journey/configuration.rb +103 -0
- data/lib/datashift_journey/engine.rb +38 -0
- data/lib/datashift_journey/exceptions.rb +26 -0
- data/lib/datashift_journey/helpers/back_link.rb +58 -0
- data/lib/datashift_journey/journey/machine_builder.rb +59 -0
- data/lib/datashift_journey/prepare_data_for_review.rb +219 -0
- data/lib/datashift_journey/reference_generator.rb +51 -0
- data/lib/datashift_journey/state_machines/branch_sequence_map.rb +35 -0
- data/lib/datashift_journey/state_machines/extensions.rb +40 -0
- data/lib/datashift_journey/state_machines/planner.rb +206 -0
- data/lib/datashift_journey/state_machines/sequence.rb +86 -0
- data/lib/datashift_journey/state_machines/state_machine_core_ext.rb +72 -0
- data/lib/datashift_journey/version.rb +3 -0
- data/lib/datashift_journey.rb +57 -0
- data/lib/generators/datashift_journey/collector/collector_generator.rb +43 -0
- data/lib/generators/datashift_journey/collector/install_collector_generator.rb +61 -0
- data/lib/generators/datashift_journey/collector/install_mongo_collector_generator.rb +44 -0
- data/lib/generators/datashift_journey/collector/templates/collector_concern.rb.tt +34 -0
- data/lib/generators/datashift_journey/collector/templates/collector_migration.rb.tt +46 -0
- data/lib/generators/datashift_journey/forms_generator.rb +45 -0
- data/lib/generators/datashift_journey/generate_common.rb +33 -0
- data/lib/generators/datashift_journey/setup/USAGE +12 -0
- data/lib/generators/datashift_journey/setup/setup_generator.rb +44 -0
- data/lib/generators/datashift_journey/setup/templates/initializer.rb.tt +17 -0
- data/lib/generators/datashift_journey/setup/templates/model_concern.rb.tt +37 -0
- data/lib/generators/datashift_journey/templates/base_form.rb.tt +7 -0
- data/lib/generators/datashift_journey/templates/collector_form.rb.tt +18 -0
- data/lib/generators/datashift_journey/templates/collector_view.rb.tt +15 -0
- data/lib/generators/datashift_journey/templates/journey_plan_form.rb.tt +23 -0
- data/lib/generators/datashift_journey/templates/journey_plan_view.rb.tt +15 -0
- data/lib/generators/datashift_journey/views_generator.rb +35 -0
- data/lib/tasks/state_machine.thor +48 -0
- data/spec/datashift_journey/complex_journey_spec.rb +132 -0
- data/spec/datashift_journey/machine_builder_spec.rb +268 -0
- data/spec/datashift_journey/planner_spec.rb +129 -0
- data/spec/datashift_journey/sequence_spec.rb +20 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +16 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/forms/base_form.rb +8 -0
- data/spec/dummy/app/forms/business_details_form.rb +17 -0
- data/spec/dummy/app/forms/business_type_form.rb +17 -0
- data/spec/dummy/app/forms/contact_details_form.rb +17 -0
- data/spec/dummy/app/forms/enter_reg_number_form.rb +17 -0
- data/spec/dummy/app/forms/new_or_renew_form.rb +17 -0
- data/spec/dummy/app/forms/postal_address_form.rb +17 -0
- data/spec/dummy/app/forms/question1_form.rb +9 -0
- data/spec/dummy/app/forms/question2_form.rb +12 -0
- data/spec/dummy/app/forms/sole_trader_name_form.rb +17 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/payment.rb +5 -0
- data/spec/dummy/app/services/datashift_journey/models/collector_journey.rb +51 -0
- data/spec/dummy/app/views/_question1.html.erb +13 -0
- data/spec/dummy/app/views/_question2.html.erb +9 -0
- data/spec/dummy/app/views/layouts/alternative.html.erb +14 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/pages/home.html.erb +6 -0
- data/spec/dummy/app/views/pages/start.html.erb +5 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config/application.rb +39 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +22 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +47 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +47 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/datashift_journey.rb +6 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +27 -0
- data/spec/dummy/config/routes.rb +28 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20160101091218_create_dummy_checkout.rb +43 -0
- data/spec/dummy/db/migrate/20161221100703_datashift_journey_create_collector.rb +56 -0
- data/spec/dummy/db/schema.rb +142 -0
- data/spec/dummy/lib/version.rb +1 -0
- data/spec/factories/collector_factory.rb +16 -0
- data/spec/factories/collector_snippet_factory.rb +9 -0
- data/spec/factories/collector_state_page_factory.rb +12 -0
- data/spec/factories/data_node_factory.rb +9 -0
- data/spec/factories/form_factory.rb +6 -0
- data/spec/features/basic_navigation_spec.rb +125 -0
- data/spec/helpers/application_helper_spec.rb +40 -0
- data/spec/integration/collector/page_state_spec.rb +45 -0
- data/spec/models/collector/collector_spec.rb +100 -0
- data/spec/models/collector/page_state_spec.rb +30 -0
- data/spec/rails_helper.rb +73 -0
- data/spec/requests/collector/api/v1/page_state_spec.rb +85 -0
- data/spec/requests/collector/api/v1/states_spec.rb +28 -0
- data/spec/spec_helper.rb +63 -0
- data/spec/support/asserts.rb +27 -0
- data/spec/support/mailer_macros.rb +25 -0
- data/spec/support/page_objects/base_page_object.rb +77 -0
- data/spec/swagger_helper.rb +25 -0
- metadata +425 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class DatashiftJourneyCreateCollector < ActiveRecord::Migration[<%= @migration_version %>]
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Metrics/MethodLength
|
|
4
|
+
|
|
5
|
+
def change
|
|
6
|
+
|
|
7
|
+
create_table :dsj_form_definitions do |t|
|
|
8
|
+
t.string :state, index: true, null: false
|
|
9
|
+
t.string :klass, index: true, null: false
|
|
10
|
+
t.timestamps null: false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
create_table :dsj_form_fields do |t|
|
|
14
|
+
t.references :form_definition, index: true, null: false
|
|
15
|
+
t.string :name, index: true, null: false, limit: 100
|
|
16
|
+
t.integer :category, index: true, null: false
|
|
17
|
+
t.text :presentation
|
|
18
|
+
t.timestamps null: false
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# The plan is an instance of a JourneyPlan class
|
|
22
|
+
create_table :dsj_data_nodes do |t|
|
|
23
|
+
t.references :plan, null: false, polymorphic: true
|
|
24
|
+
t.references :form_field, null: false
|
|
25
|
+
t.text :field_value
|
|
26
|
+
t.timestamps null: false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
create_table :dsj_snippets do |t|
|
|
30
|
+
t.text :raw_text
|
|
31
|
+
t.string :I18n_key, index: true
|
|
32
|
+
t.timestamps null: false
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
create_table :dsj_forms_snippets do |t|
|
|
36
|
+
t.references :form_model, null: false
|
|
37
|
+
t.references :snippet, null: false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
create_table :dsj_fields_snippets do |t|
|
|
41
|
+
t.references :form_field, null: false
|
|
42
|
+
t.references :snippet, null: false
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'datashift_journey/collector/base_collector_form'
|
|
2
|
+
|
|
3
|
+
module DatashiftJourney
|
|
4
|
+
|
|
5
|
+
class FormsGenerator < Rails::Generators::Base
|
|
6
|
+
|
|
7
|
+
attr_accessor :state
|
|
8
|
+
|
|
9
|
+
source_root File.expand_path('templates', __dir__)
|
|
10
|
+
|
|
11
|
+
class_option :base_class, type: :string, banner: "ClassName", desc: "Class to use as the Base class for generated Forms"
|
|
12
|
+
class_option :"no-collector", type: :boolean, default: false, desc: "Do not generate form to use inbuilt data Collector"
|
|
13
|
+
|
|
14
|
+
desc 'This generator creates an initializer and concern to setup and manage the journey Model'
|
|
15
|
+
|
|
16
|
+
def create_form_per_state
|
|
17
|
+
|
|
18
|
+
method_ptr = if options["no-collector"] == false || DatashiftJourney.journey_plan_class == DatashiftJourney::Collector::Collector
|
|
19
|
+
->() { state_forms_for_collector_definition }
|
|
20
|
+
else
|
|
21
|
+
->() { state_form_definition }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
DatashiftJourney.journey_plan_class.state_machine(:state).states.map(&:name).each do |state|
|
|
25
|
+
@state = state
|
|
26
|
+
method_ptr.call
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def state_forms_for_collector_definition
|
|
33
|
+
@datashift_journey_baseform = "DatashiftJourney::Collector::BaseCollectorForm"
|
|
34
|
+
template 'base_form.rb', "app/forms/base_form.rb"
|
|
35
|
+
template 'collector_form.rb', "app/forms/#{state}_form.rb"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def state_form_definition
|
|
39
|
+
@datashift_journey_baseform = "DatashiftJourney::BaseForm"
|
|
40
|
+
template 'base_form.rb', "app/forms/base_form.rb"
|
|
41
|
+
template 'journey_plan_form.rb', "app/forms/#{state}_form.rb"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module DatashiftJourney
|
|
2
|
+
|
|
3
|
+
module GenerateCommon
|
|
4
|
+
|
|
5
|
+
# Copied from https://github.com/rails/rails/blob/6-0-stable/activerecord/lib/rails/generators/active_record/migration.rb#L12-L16
|
|
6
|
+
|
|
7
|
+
# Implement the required interface for Rails::Generators::Migration.
|
|
8
|
+
def next_migration_number(dirname)
|
|
9
|
+
next_migration_number = current_migration_number(dirname) + 1
|
|
10
|
+
ActiveRecord::Migration.next_migration_number(next_migration_number)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def model_path
|
|
14
|
+
@model_path ||= File.join(destination_root, "app", "models", journey_plan_filename)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Module name = options[:journey_class]Journey
|
|
18
|
+
|
|
19
|
+
def journey_plan_filename
|
|
20
|
+
"#{DatashiftJourney.journey_plan_class.to_s.underscore}.rb"
|
|
21
|
+
end
|
|
22
|
+
#
|
|
23
|
+
# def concern_file(journey_class)
|
|
24
|
+
# "#{journey_class.underscore}_journey.rb"
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
# def decorator_file(journey_class)
|
|
28
|
+
# "#{journey_class.underscore}_decorator.rb"
|
|
29
|
+
# end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Description:
|
|
2
|
+
This generator will setup a full Datashift Journey Plan.
|
|
3
|
+
|
|
4
|
+
Creates a model file to hold the plan.
|
|
5
|
+
|
|
6
|
+
Creates an initializer file at config/initializers
|
|
7
|
+
|
|
8
|
+
Example:
|
|
9
|
+
bin/rails generate setup Model
|
|
10
|
+
|
|
11
|
+
This will create :
|
|
12
|
+
app/models/datashift_journey/model.rb
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module DatashiftJourney
|
|
2
|
+
class SetupGenerator < Rails::Generators::NamedBase
|
|
3
|
+
|
|
4
|
+
source_root File.expand_path('templates', __dir__)
|
|
5
|
+
|
|
6
|
+
class_option :migration, type: :boolean, default: true, aliases: '-m'
|
|
7
|
+
|
|
8
|
+
# This class automatically runs every method defined in it,
|
|
9
|
+
def generate_model
|
|
10
|
+
Rails::Generators.invoke "active_record:model", [name, 'state:string', 'reference:string:index:unique'], migration: options[:migration] unless model_exists? && behavior == :invoke
|
|
11
|
+
|
|
12
|
+
plan = File.open(File.join(SetupGenerator.source_root, "model_concern.rb.tt")).read
|
|
13
|
+
|
|
14
|
+
inject_into_file model_path, :after => /class.* < ApplicationRecord/ do
|
|
15
|
+
"\n\tinclude DatashiftJourney::ReferenceGenerator.new(prefix: 'C')\n\tvalidates_presence_of :reference\n\tvalidates_uniqueness_of :reference\n\n#{plan}"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def create_files
|
|
20
|
+
template 'initializer.rb', 'config/initializers/datashift_journey.rb'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def add_engine_to_routes
|
|
24
|
+
return if File.readlines(File.join(destination_root, "config/routes.rb")).grep(/mount DatashiftJourney::Engine =>/).present?
|
|
25
|
+
|
|
26
|
+
route("mount DatashiftJourney::Engine => '/journey'")
|
|
27
|
+
|
|
28
|
+
puts '*' * 50
|
|
29
|
+
puts "We added the following line to your application's config/routes.rb file:\n"
|
|
30
|
+
puts " mount DatashiftJourney::Engine => '/journey'"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def model_exists?
|
|
36
|
+
File.exist?(File.join(destination_root, model_path))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def model_path
|
|
40
|
+
@model_path ||= File.join(destination_root, "app", "models", "#{file_path}.rb")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
DatashiftJourney.journey_plan_class = '<%= class_name %>'
|
|
2
|
+
|
|
3
|
+
DatashiftJourney::Configuration.configure do |config|
|
|
4
|
+
config.partial_location = '<%= class_name.pluralize.underscore %>'
|
|
5
|
+
|
|
6
|
+
config.add_state_jumper_toolbar = false
|
|
7
|
+
|
|
8
|
+
config.state_jumper_states = {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# For Form validation options see - https://github.com/trailblazer/reform#installation
|
|
12
|
+
#
|
|
13
|
+
require "reform/form/dry"
|
|
14
|
+
|
|
15
|
+
Reform::Form.class_eval do
|
|
16
|
+
feature Reform::Form::Dry
|
|
17
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
DatashiftJourney::Journey::MachineBuilder.create_journey_plan(initial: :TO_DO_SET_INITIAL_STATE) do
|
|
3
|
+
|
|
4
|
+
=begin
|
|
5
|
+
The available API is defined in : datashift_journey/lib/datashift_journey/state_machines/planner.rb
|
|
6
|
+
|
|
7
|
+
A basic example with 2 simple steps, followed by one set of branches, which reconnect to another common
|
|
8
|
+
section starting at :review
|
|
9
|
+
|
|
10
|
+
DatashiftJourney::Journey::MachineBuilder.create_journey_plan(initial: :ship_address) do
|
|
11
|
+
|
|
12
|
+
# Two simple sequential steps
|
|
13
|
+
sequence [:ship_address, :bill_address]
|
|
14
|
+
|
|
15
|
+
# first define the sequences
|
|
16
|
+
branch_sequence :visa_sequence, [:visa_page1, :visa_page2]
|
|
17
|
+
|
|
18
|
+
branch_sequence :mastercard_sequence, [:page_mastercard1, :page_mastercard2, :page_mastercard3]
|
|
19
|
+
|
|
20
|
+
branch_sequence :paypal_sequence, []
|
|
21
|
+
|
|
22
|
+
# now define the parent state and the routing criteria to each sequence
|
|
23
|
+
# So after bill address we reach payment - then we split to a single step, depending on the card type entered
|
|
24
|
+
|
|
25
|
+
split_on_equality( :payment,
|
|
26
|
+
"payment_card", # Helper method on Checkout that returns card type from Payment
|
|
27
|
+
visa_sequence: 'visa',
|
|
28
|
+
mastercard_sequence: 'mastercard',
|
|
29
|
+
paypal_sequence: 'paypal'
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# All different card type branches, recombine here at review
|
|
33
|
+
sequence [:review, :complete ]
|
|
34
|
+
end
|
|
35
|
+
=end
|
|
36
|
+
|
|
37
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class <%= state.to_s.camelize %>Form < ::BaseForm
|
|
2
|
+
|
|
3
|
+
def params_key
|
|
4
|
+
:<%= state %>
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# Data collection performed by base class but if you need custom processing, the forms
|
|
8
|
+
# fields are represented as a series of DataNode objects, with the actual data saved in :field_value
|
|
9
|
+
#
|
|
10
|
+
# collection :data_nodes do
|
|
11
|
+
# property :field_value
|
|
12
|
+
# end
|
|
13
|
+
|
|
14
|
+
# Example basic validation - has field been filled in :
|
|
15
|
+
# validates :field_value, presence: true
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
You can access the Reform form object via local : form
|
|
3
|
+
You can access the Reform form model object via : form.model
|
|
4
|
+
You have access to main DSJ journey object via local : journey_plan
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
<header class="text">
|
|
8
|
+
<h1 class="form-title heading-large" id="groupLabel"><%%= t(".header") %></h1>
|
|
9
|
+
</header>
|
|
10
|
+
|
|
11
|
+
<fieldset>
|
|
12
|
+
<legend class="visuallyhidden"><%%= t(".legend") %></legend>
|
|
13
|
+
<%%= f.label :field_value, t(".field_value_label"), class: 'form-label' %>
|
|
14
|
+
<%%= f.text_field :field_value, class: 'form-control form-control-char-50' %>
|
|
15
|
+
</fieldset>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class <%= state.to_s.camelize %>Form < ::BaseForm
|
|
2
|
+
|
|
3
|
+
def self.factory(journey)
|
|
4
|
+
|
|
5
|
+
# Auto generated by DatashiftJourney - check the Model this Form is managing
|
|
6
|
+
|
|
7
|
+
# state_model = #{state.classify}.new
|
|
8
|
+
# new(state_model, journey)
|
|
9
|
+
|
|
10
|
+
# For example if this page concerned with collecting data for an Organisation model use :
|
|
11
|
+
|
|
12
|
+
# organisation = journey.organisation
|
|
13
|
+
# new(organisation, journey)
|
|
14
|
+
|
|
15
|
+
# If you have no separate model just use
|
|
16
|
+
new(journey)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def params_key
|
|
20
|
+
:<%= state %>
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
You can access the Reform form object via local : form
|
|
3
|
+
You can access the Reform form model object via : form.model
|
|
4
|
+
You have access to main DSJ journey object via local : journey_plan
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
<header class="text">
|
|
8
|
+
<h1 class="form-title heading-large" id="groupLabel"><%%= t(".header") %></h1>
|
|
9
|
+
</header>
|
|
10
|
+
|
|
11
|
+
<fieldset>
|
|
12
|
+
<legend class="visuallyhidden"><%%= t(".legend") %></legend>
|
|
13
|
+
<%%= f.label :field_value, t(".field_value_label"), class: 'form-label' %>
|
|
14
|
+
<%%= f.text_field :field_value, class: 'form-control form-control-char-50' %>
|
|
15
|
+
</fieldset>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module DatashiftJourney
|
|
2
|
+
|
|
3
|
+
class ViewsGenerator < Rails::Generators::Base
|
|
4
|
+
|
|
5
|
+
source_root File.expand_path('templates', __dir__)
|
|
6
|
+
|
|
7
|
+
desc 'This generator creates an initializer and concern to setup and manage the journey Model'
|
|
8
|
+
|
|
9
|
+
def create_form_per_state
|
|
10
|
+
method_ptr = if DatashiftJourney.journey_plan_class == DatashiftJourney::Collector::Collector
|
|
11
|
+
->(p) { view_for_collector_definition(p) }
|
|
12
|
+
else
|
|
13
|
+
->(p) { view_for_journey_plan_definition(p) }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
partial_location = DatashiftJourney::Configuration.call.partial_location
|
|
17
|
+
|
|
18
|
+
path = 'app/views'
|
|
19
|
+
path = File.join(path, partial_location) if partial_location.present?
|
|
20
|
+
|
|
21
|
+
DatashiftJourney.state_names.each { |state| method_ptr.call(state.to_s, File.join(path, "_#{state}.html.erb")) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def view_for_collector_definition(path)
|
|
27
|
+
template 'collector_view.rb', path
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def view_for_journey_plan_definition(path)
|
|
31
|
+
template 'journey_plan_view.rb', path
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require'datashift_journey'
|
|
2
|
+
require 'thor'
|
|
3
|
+
|
|
4
|
+
class StateMachine < Thor
|
|
5
|
+
|
|
6
|
+
desc "report", "Report on the states and transitions availblke for current DSJ Journey Plan"
|
|
7
|
+
|
|
8
|
+
def report
|
|
9
|
+
|
|
10
|
+
environment
|
|
11
|
+
|
|
12
|
+
journey_plan = DatashiftJourney.journey_plan_class.new
|
|
13
|
+
|
|
14
|
+
state_machine = DatashiftJourney.journey_plan_class.state_machine
|
|
15
|
+
|
|
16
|
+
puts "\nINITIAL STATE", journey_plan.state.inspect
|
|
17
|
+
|
|
18
|
+
puts "\nEVENTS",journey_plan.state_events.inspect
|
|
19
|
+
|
|
20
|
+
puts "\nSTATE PATHS",journey_plan.state_paths.inspect
|
|
21
|
+
|
|
22
|
+
puts "\nSTATES", state_machine.states.map(&:name).inspect
|
|
23
|
+
|
|
24
|
+
puts "\nEVENT KEYS", state_machine.events.keys.sort
|
|
25
|
+
|
|
26
|
+
puts "\nBACK", state_machine.events[:back].known_states.sort
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
no_commands do
|
|
30
|
+
|
|
31
|
+
def environment
|
|
32
|
+
|
|
33
|
+
if File.exist?(File.expand_path('config/environment.rb'))
|
|
34
|
+
begin
|
|
35
|
+
require File.expand_path('config/environment.rb')
|
|
36
|
+
rescue => e
|
|
37
|
+
puts ("Failed to initialise ActiveRecord : #{e.message}")
|
|
38
|
+
exit -1
|
|
39
|
+
#raise ConnectionError.new("Failed to initialise ActiveRecord : #{e.message}")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
else
|
|
43
|
+
raise PathError.new('No config/environment.rb found - cannot initialise ActiveRecord')
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
module DatashiftJourney
|
|
4
|
+
|
|
5
|
+
module Journey
|
|
6
|
+
|
|
7
|
+
RSpec.describe 'Complex Machine Builder Examples' do
|
|
8
|
+
before(:each) do
|
|
9
|
+
DatashiftJourney.use_default_journey_plan_class
|
|
10
|
+
# puts DatashiftJourney.journey_plan_class.state_machine.methods.sort
|
|
11
|
+
# puts DatashiftJourney.journey_plan_class.state_machine
|
|
12
|
+
|
|
13
|
+
# N.B This is bit of a hack cos DatashiftJourney.journey_plan_class.state_machines
|
|
14
|
+
# only available after at least one Machine defined
|
|
15
|
+
|
|
16
|
+
DatashiftJourney.journey_plan_class.state_machines.clear if DatashiftJourney.journey_plan_class.respond_to?(:state_machines)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
context 'Multiple Sequences' do
|
|
20
|
+
it 'reports that branches are missing when not defined' do
|
|
21
|
+
pending('create a test with a splitter but where some branch_sequences are not defined')
|
|
22
|
+
|
|
23
|
+
DatashiftJourney::Journey::MachineBuilder.create_journey_plan(initial: :splitter) do
|
|
24
|
+
branch_sequence :renew_sequence, [:business_type]
|
|
25
|
+
|
|
26
|
+
split_on_equality(:splitter,
|
|
27
|
+
'new_or_renew_value', # Helper method on Collector
|
|
28
|
+
new_sequence: 'new',
|
|
29
|
+
renew_sequence: 'renew')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
journey = DatashiftJourney.journey_plan_class.new
|
|
33
|
+
|
|
34
|
+
expect_state_matches(journey, :new_or_renew)
|
|
35
|
+
expect(journey.can_back?).to eq false # this is the initial state
|
|
36
|
+
|
|
37
|
+
journey.next!
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'enables the first state to be a branch splitter' do
|
|
41
|
+
DatashiftJourney::Journey::MachineBuilder.create_journey_plan(initial: :new_or_renew) do
|
|
42
|
+
branch_sequence :new_sequence, [:business_type]
|
|
43
|
+
|
|
44
|
+
branch_sequence :renew_sequence, [:enter_reg_number]
|
|
45
|
+
|
|
46
|
+
# now define the parent state and the routing criteria to each sequence
|
|
47
|
+
|
|
48
|
+
split_on_equality(:new_or_renew,
|
|
49
|
+
'new_or_renew_value', # Helper method on Collector
|
|
50
|
+
new_sequence: 'new',
|
|
51
|
+
renew_sequence: 'renew')
|
|
52
|
+
|
|
53
|
+
# Define the sequences for Business Type split
|
|
54
|
+
# Partnership Limited Company Public Body Charity Authority Other
|
|
55
|
+
|
|
56
|
+
split_on_equality(:business_type,
|
|
57
|
+
'business_type_value', # Helper method on Collector,
|
|
58
|
+
authority: 'authority',
|
|
59
|
+
other_sequence: 'other',
|
|
60
|
+
sole_trader_sequence: 'sole_trader',
|
|
61
|
+
partnership_sequence: 'partnership',
|
|
62
|
+
limited_company: 'limited_company',
|
|
63
|
+
public_body: 'public_body',
|
|
64
|
+
charity: 'charity')
|
|
65
|
+
|
|
66
|
+
# SOLE TRADER
|
|
67
|
+
branch_sequence :sole_trader_sequence, [:other_businesses, :service_provided]
|
|
68
|
+
|
|
69
|
+
split_on_equality(:service_provided,
|
|
70
|
+
'service_provided_value', # Helper method on Collector
|
|
71
|
+
service_provided_no_sequence: 'no',
|
|
72
|
+
service_provided_yes_sequence: 'yes')
|
|
73
|
+
|
|
74
|
+
branch_sequence :service_provided_no_sequence, [] # => construction_demolition
|
|
75
|
+
|
|
76
|
+
# OTHER
|
|
77
|
+
|
|
78
|
+
branch_sequence :other_sequence, [:other_business]
|
|
79
|
+
|
|
80
|
+
# Construction Demolition
|
|
81
|
+
|
|
82
|
+
split_on_equality(:construction_demolition,
|
|
83
|
+
:construction_demolition_value,
|
|
84
|
+
registration_type_sequence: 'yes') # => registration_type
|
|
85
|
+
|
|
86
|
+
# This branch may actually simplify down to just
|
|
87
|
+
# sequence [ :registration_type, :business_details]
|
|
88
|
+
|
|
89
|
+
split_on_equality(:registration_type,
|
|
90
|
+
:registration_type_value,
|
|
91
|
+
carrier_dealer_sequence: 'carrier_dealer',
|
|
92
|
+
broker_dealer_sequence: 'broker_dealer',
|
|
93
|
+
carrier_broker_dealer_sequence: 'carrier_broker_dealer')
|
|
94
|
+
|
|
95
|
+
branch_sequence :carrier_dealer_sequence, [:business_details]
|
|
96
|
+
branch_sequence :broker_dealer_sequence, [:business_details]
|
|
97
|
+
branch_sequence :carrier_broker_dealer_sequence, [:business_details]
|
|
98
|
+
|
|
99
|
+
# RESTART COMMON JOURNEY AFTER BUSINESS TYPES
|
|
100
|
+
|
|
101
|
+
sequence [
|
|
102
|
+
:contact_details,
|
|
103
|
+
:postal_address
|
|
104
|
+
]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
journey = DatashiftJourney.journey_plan_class.new(reference: 'UNIQUE_1234')
|
|
108
|
+
|
|
109
|
+
expect_state_matches(journey, :new_or_renew)
|
|
110
|
+
expect(journey.can_back?).to eq false # this is the initial state
|
|
111
|
+
expect(journey.can_next?).to eq true
|
|
112
|
+
journey.next!
|
|
113
|
+
|
|
114
|
+
expect_state_canback_cannext_and_next!(journey, :business_type)
|
|
115
|
+
|
|
116
|
+
# First state of a branch - We should be able to go back to the Split - based on same conditions
|
|
117
|
+
expect_state_matches(journey, :other_businesses)
|
|
118
|
+
expect(journey.can_back?).to eq true
|
|
119
|
+
journey.back!
|
|
120
|
+
|
|
121
|
+
expect_state_canback_cannext_and_next!(journey, :business_type)
|
|
122
|
+
|
|
123
|
+
# Now in Sole Trader branhc
|
|
124
|
+
expect_state_canback_cannext_and_next!(journey, :other_businesses)
|
|
125
|
+
expect_state_canback_cannext_and_next!(journey, :service_provided)
|
|
126
|
+
|
|
127
|
+
expect_state_matches(journey, :construction_demolition)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|