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,18 @@
|
|
|
1
|
+
module DatashiftJourney
|
|
2
|
+
module Collector
|
|
3
|
+
class DataNode < ActiveRecord::Base
|
|
4
|
+
|
|
5
|
+
self.table_name = 'dsj_data_nodes'
|
|
6
|
+
|
|
7
|
+
# Instance of the DatashiftJourney.journey_plan_class this data was collected for.
|
|
8
|
+
#
|
|
9
|
+
# Model holding the state machine Plan
|
|
10
|
+
belongs_to :plan, polymorphic: true
|
|
11
|
+
|
|
12
|
+
# generic definition of the field this data relates to - card type, street address, profile id etc
|
|
13
|
+
belongs_to :form_field, class_name: 'DatashiftJourney::Collector::FormField', foreign_key: :form_field_id
|
|
14
|
+
|
|
15
|
+
validates_presence_of :field_value
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module DatashiftJourney
|
|
2
|
+
module Collector
|
|
3
|
+
|
|
4
|
+
# Associated with a REFORM class - stores related Form definition data in the DB,
|
|
5
|
+
# such as the fields associated with this form.
|
|
6
|
+
#
|
|
7
|
+
# Each step or state in the plan will have an associated ReForm + FormDefinition
|
|
8
|
+
#
|
|
9
|
+
# Similar in intention to the Page Object Pattern, store and provide helpers for
|
|
10
|
+
# rendering forms and HTML in the associated state View
|
|
11
|
+
#
|
|
12
|
+
class FormDefinition < ActiveRecord::Base
|
|
13
|
+
|
|
14
|
+
self.table_name = 'dsj_form_definitions'
|
|
15
|
+
|
|
16
|
+
has_many :form_fields, class_name: 'DatashiftJourney::Collector::FormField', dependent: :destroy, foreign_key: :form_definition_id
|
|
17
|
+
accepts_nested_attributes_for :form_fields
|
|
18
|
+
|
|
19
|
+
validates_presence_of :state
|
|
20
|
+
validates_uniqueness_of :state
|
|
21
|
+
|
|
22
|
+
def field_ids
|
|
23
|
+
form_fields.collect(&:id)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
# N.B Validations are called BEFORE before_create or before_save
|
|
29
|
+
before_validation do |record|
|
|
30
|
+
record.state ||= DatashiftJourney::FormObjectFactory.state_name(self.klass)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module DatashiftJourney
|
|
2
|
+
module Collector
|
|
3
|
+
|
|
4
|
+
# This DEFINES a single Field in a Form, where a field is generally a form
|
|
5
|
+
# element that collects some kind of data
|
|
6
|
+
#
|
|
7
|
+
class FormField < ActiveRecord::Base
|
|
8
|
+
|
|
9
|
+
self.table_name = 'dsj_form_fields'
|
|
10
|
+
|
|
11
|
+
belongs_to :form_definition, class_name: 'FormDefinition', foreign_key: :form_definition_id
|
|
12
|
+
|
|
13
|
+
validates_presence_of :form_definition, :name, :category
|
|
14
|
+
|
|
15
|
+
# Notes:
|
|
16
|
+
#
|
|
17
|
+
# Cannot use "select" - keyword already defined by Active Record.
|
|
18
|
+
#
|
|
19
|
+
# When assigning a category of - :select_option - the form should also provide a helper method
|
|
20
|
+
# to populate the select dropdown as per https://api.rubyonrails.org/v6.0.3.4/classes/ActionView/Helpers/FormOptionsHelper.html
|
|
21
|
+
#
|
|
22
|
+
# The expected method format is : options_for_select_<field name>
|
|
23
|
+
#
|
|
24
|
+
# So a field definition :
|
|
25
|
+
#
|
|
26
|
+
# journey_plan_form_field name: :run_time, category: :select_option
|
|
27
|
+
#
|
|
28
|
+
# Would also require a select dropdown helper method called options_for_select_run_time, for example,
|
|
29
|
+
# in our Form we could do something like:
|
|
30
|
+
#
|
|
31
|
+
# def options_for_select_run_time
|
|
32
|
+
# options_for_select(run_times, run_times)
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# private
|
|
36
|
+
#
|
|
37
|
+
# def run_times
|
|
38
|
+
# @run_times ||= %w[PyTorch TensorFlow TensorRT]
|
|
39
|
+
# end
|
|
40
|
+
#
|
|
41
|
+
enum category: [:string, :select_option, :text_area, :number, :date ]
|
|
42
|
+
# :check_box, :radio_button, password range date time datetime_local month week search email telephone url color }
|
|
43
|
+
|
|
44
|
+
scope :for_form_and_field, ->(form_name, field_name) {
|
|
45
|
+
page_state = DatashiftJourney::Collector::FormDefinition.where('state = ?', form_name).first
|
|
46
|
+
return nil unless page_state
|
|
47
|
+
page_state.form_fields.where('name = ?', field_name).first
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# TODO - revisit snippets
|
|
51
|
+
#
|
|
52
|
+
# many :snippets, class_name: 'FieldSnippet', foreign_key: :form_field_id, dependent: :destroy
|
|
53
|
+
# has_many :field_snippets, foreign_key: :form_field_id
|
|
54
|
+
# has_many :snippets, through: :field_snippets # , foreign_key: :page_state_id
|
|
55
|
+
# def question
|
|
56
|
+
# Snippet.to_sentance(snippets)
|
|
57
|
+
# end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module DatashiftJourney
|
|
2
|
+
# This handles supplying data for a SUMMARY or REVIEW page or e.g. an email contaning a summary,
|
|
3
|
+
# usually as the key/value data, associated with an Enrollment state.
|
|
4
|
+
#
|
|
5
|
+
# N.B - Our state engine collector the state of the journey (not essentially the state of the journey_plan), hence a state
|
|
6
|
+
# is more analogous to Page
|
|
7
|
+
# So here review data is assigned for DATA collected DURING a particular state - effectively the data
|
|
8
|
+
# saved during the UPDATE on that State
|
|
9
|
+
#
|
|
10
|
+
class JourneyReview
|
|
11
|
+
|
|
12
|
+
extend PrepareDataForReview
|
|
13
|
+
include PrepareDataForReview
|
|
14
|
+
|
|
15
|
+
attr_reader :journey_plan, :root_i18n_scope
|
|
16
|
+
delegate :state, :state_name, to: :journey_plans
|
|
17
|
+
|
|
18
|
+
# This class can be reused anywhere that requires yaml-parsed summary data for an journey_plan.
|
|
19
|
+
# Hence the root_i18n_scope specifies the scope under which there must be a :common key at
|
|
20
|
+
# least. It is recommended that the root_i18n_scopeis a folder under a config/locales
|
|
21
|
+
# directory containing at least a common.en.yml file, and probably organisation-
|
|
22
|
+
# specific yml files too, which override common sections (see #prepare_review_data_list).
|
|
23
|
+
def initialize(journey_plan, root_i18n_scope = '.journey_plan_review')
|
|
24
|
+
@journey_plan = journey_plan
|
|
25
|
+
@root_i18n_scope = root_i18n_scope
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Merge common 'sections' in the review data with any app-specific
|
|
29
|
+
# sections; if an app-specific section matches by heading (title) then it replaces
|
|
30
|
+
# the standard one. In this way apps can override discrete sections
|
|
31
|
+
# in the summary data.
|
|
32
|
+
#
|
|
33
|
+
def prepare_review_data_list
|
|
34
|
+
merged_sections = common_sections.each_with_index do |common_section, idx|
|
|
35
|
+
replacement = organisation_specific_sections.find do |org_specific_section|
|
|
36
|
+
org_specific_section.heading == common_section.heading
|
|
37
|
+
end
|
|
38
|
+
common_sections[idx] = replacement if replacement
|
|
39
|
+
end
|
|
40
|
+
merged_sections
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def common_sections
|
|
46
|
+
@common_sections ||= prepare_from_locale(journey_plan, common_i18n_key)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def app_specific_sections
|
|
50
|
+
@app_specific_review_data ||= begin
|
|
51
|
+
prepare_from_locale(journey_plan, app_type_i18n_key)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# e.g. ".journey_plan_review"
|
|
56
|
+
def common_i18n_key
|
|
57
|
+
root_i18n_scope.to_s
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# e.g. ".journey_plan_review.limited_company"
|
|
61
|
+
def app_type_i18n_key
|
|
62
|
+
"#{root_i18n_scope}.#{@journey_plan.app.type_name}"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module DatashiftJourney
|
|
2
|
+
|
|
3
|
+
class ReviewDataSection
|
|
4
|
+
|
|
5
|
+
attr_accessor :heading
|
|
6
|
+
attr_accessor :rows
|
|
7
|
+
|
|
8
|
+
# :link_state - The target url for Change This. If not specified, defaults to the section page/state
|
|
9
|
+
# Supports :none to leave column empty
|
|
10
|
+
#
|
|
11
|
+
Struct.new('ReviewDataRow', :title, :data, :link_state, :link_title, :heading) do
|
|
12
|
+
def target(journey_plan)
|
|
13
|
+
return nil if link_state.to_sym == :none
|
|
14
|
+
DatashiftJourney::Engine.routes.url_helpers.review_state_path(link_state, journey_plan)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def initialize(heading)
|
|
19
|
+
@heading = heading
|
|
20
|
+
@rows = []
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Add a new row to this Section. Returns the ReviewDataRow created
|
|
24
|
+
def add(title, data, link_state, link_title)
|
|
25
|
+
rows << Struct::ReviewDataRow.new(title, data, link_state, link_title, heading)
|
|
26
|
+
rows.last
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
delegate :size, :empty?, to: :rows
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<header class="text">
|
|
2
|
+
<h1 class="form-title heading-large" id="groupLabel"><%= form.model.header %></h1>
|
|
3
|
+
</header>
|
|
4
|
+
|
|
5
|
+
<fieldset>
|
|
6
|
+
|
|
7
|
+
<% form.model.form_fields.each do |ff| %>
|
|
8
|
+
<%= fields_for :data_nodes do |d| %>
|
|
9
|
+
<legend class="visuallyhidden"><%= ff.question %></legend>
|
|
10
|
+
<%= d.label ff.field, ff.question, class: 'form-label' %>
|
|
11
|
+
<%= d.text_field :field, class: 'form-control form-control-char-50' %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<% end %>
|
|
14
|
+
</fieldset>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<% content_for :page_title, create_title('global.401_unauthorized.heading') + " (#{response.status})" %>
|
|
2
|
+
|
|
3
|
+
<%= yield :error_header %>
|
|
4
|
+
|
|
5
|
+
<header>
|
|
6
|
+
<h1 style="font-size: 48px; font-weight:bold; margin-top:30px; margin-bottom:15px;">
|
|
7
|
+
<%=t 'global.401_unauthorized.heading'%>
|
|
8
|
+
</h1>
|
|
9
|
+
</header>
|
|
10
|
+
|
|
11
|
+
<p style="max-width: 30em;"><%= t 'global.401_unauthorized.message1' %></p>
|
|
12
|
+
|
|
13
|
+
<p style="max-width: 30em;"><%=t 'global.401_unauthorized.message2'%></p>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<% content_for :page_title, create_title('global.403_forbidden.heading') + " (#{response.status})" %>
|
|
2
|
+
|
|
3
|
+
<%= yield :error_header %>
|
|
4
|
+
|
|
5
|
+
<header>
|
|
6
|
+
<h1 style="font-size: 48px; font-weight:bold; margin-top:30px; margin-bottom:15px;">
|
|
7
|
+
<%=t 'global.403_forbidden.heading'%>
|
|
8
|
+
</h1>
|
|
9
|
+
</header>
|
|
10
|
+
|
|
11
|
+
<p style="max-width: 30em;"><%=t 'global.403_forbidden.message1'%></p>
|
|
12
|
+
|
|
13
|
+
<p style="max-width: 30em;"><%=t 'global.403_forbidden.message2'%></p>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<% content_for :page_title, create_title('global.404_notfound.heading') + " (#{response.status})" %>
|
|
2
|
+
|
|
3
|
+
<%= yield :error_header %>
|
|
4
|
+
|
|
5
|
+
<header>
|
|
6
|
+
<h1 style="font-size: 48px; font-weight:bold; margin-top:30px; margin-bottom:15px;">
|
|
7
|
+
<%=t 'global.404_notfound.heading'%>
|
|
8
|
+
</h1>
|
|
9
|
+
</header>
|
|
10
|
+
|
|
11
|
+
<p style="max-width: 30em;"><%=t 'global.404_notfound.message1'%></p>
|
|
12
|
+
|
|
13
|
+
<p style="max-width: 30em;"><%=t 'global.404_notfound.message2'%></p>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<% content_for :page_title, create_title('global.422_unprocessable_entity.heading') + " (#{response.status})" %>
|
|
2
|
+
|
|
3
|
+
<%= yield :error_header %>
|
|
4
|
+
|
|
5
|
+
<header>
|
|
6
|
+
<h1 style="font-size: 48px; font-weight:bold; margin-top:30px; margin-bottom:15px;">
|
|
7
|
+
<%=t 'global.422_unprocessable_entity.heading'%>
|
|
8
|
+
</h1>
|
|
9
|
+
</header>
|
|
10
|
+
|
|
11
|
+
<p style="max-width: 30em;"><%=t 'global.422_unprocessable_entity.message1'%></p>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<% content_for :page_title, create_title('global.500_internal_server_error.heading') + " (#{response.status})" %>
|
|
2
|
+
|
|
3
|
+
<%= yield :error_header %>
|
|
4
|
+
|
|
5
|
+
<header>
|
|
6
|
+
<h1 style="font-size: 48px; font-weight:bold; margin-top:30px; margin-bottom:15px;">
|
|
7
|
+
<%=t 'global.500_internal_server_error.heading'%>
|
|
8
|
+
</h1>
|
|
9
|
+
</header>
|
|
10
|
+
|
|
11
|
+
<p style="max-width: 30em;"><%=t 'global.500_internal_server_error.message1'%></p>
|
|
12
|
+
|
|
13
|
+
<p style="max-width: 30em;"><%=t 'global.500_internal_server_error.message2'%></p>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<% content_for :page_title, create_title('global.503_bad_gateway.heading') + " (#{response.status})" %>
|
|
2
|
+
|
|
3
|
+
<%= yield :error_header %>
|
|
4
|
+
|
|
5
|
+
<header>
|
|
6
|
+
<h1 style="font-size: 48px; font-weight:bold; margin-top:30px; margin-bottom:15px;">
|
|
7
|
+
<%=t 'global.503_bad_gateway.heading'%>
|
|
8
|
+
</h1>
|
|
9
|
+
</header>
|
|
10
|
+
|
|
11
|
+
<p style="max-width: 30em;"><%=t 'global.503_bad_gateway.message1'%></p>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<% content_for :page_title, create_title('global.invalid_authenticity_token.heading') %>
|
|
2
|
+
|
|
3
|
+
<%= yield :error_header %>
|
|
4
|
+
|
|
5
|
+
<header>
|
|
6
|
+
<h1 style="font-size: 48px; font-weight:bold; margin-top: 30px; margin-bottom: 15px;">
|
|
7
|
+
<%=t 'global.invalid_authenticity_token.heading'%>
|
|
8
|
+
</h1>
|
|
9
|
+
</header>
|
|
10
|
+
|
|
11
|
+
<p>
|
|
12
|
+
<%= t 'global.invalid_authenticity_token.message_html',
|
|
13
|
+
link: link_to('cookies', main_app.page_path('cookies')) %>
|
|
14
|
+
</p>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<%= render 'datashift_journey/shared/errors', form: form %>
|
|
2
|
+
<%= render 'datashift_journey/state_jumper/toolbar' %>
|
|
3
|
+
|
|
4
|
+
<% state = journey_plan.state %>
|
|
5
|
+
|
|
6
|
+
<% url = local_assigns[:form_url] ? form_url : datashift_journey.edit_journey_plan_path %>
|
|
7
|
+
<% method = local_assigns[:form_method] ? form_method : :post %>
|
|
8
|
+
|
|
9
|
+
<%= form_for form, as: state, url: url, method: method, class: 'form' do |f| %>
|
|
10
|
+
|
|
11
|
+
<%= hidden_field_tag "rendered_state", local_assigns[:rendered_state] || state %>
|
|
12
|
+
|
|
13
|
+
<%= render_if_exists state, form: form, f: f, journey_plan: journey_plan %>
|
|
14
|
+
<% end %>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<% ids = form.definition.field_ids %>
|
|
2
|
+
|
|
3
|
+
<% key = form.params_key %>
|
|
4
|
+
|
|
5
|
+
<% form.journey_plan.data_nodes.select { |dn| ids.include?(dn.form_field_id) }.sort.each_with_index do |data_node, i| %>
|
|
6
|
+
<%= f.fields_for :data_nodes, data_node do |a| %>
|
|
7
|
+
|
|
8
|
+
<% name = data_node.form_field.name %>
|
|
9
|
+
|
|
10
|
+
<div class="form-group">
|
|
11
|
+
<%= a.label name %>
|
|
12
|
+
<%= hidden_field_tag "#{key}[data_nodes][form_field][#{i}]", name %>
|
|
13
|
+
|
|
14
|
+
<% if data_node.form_field.select_option? %>
|
|
15
|
+
<%= select_tag "#{key}[data_nodes][field_value][#{i}]", form.send("options_for_select_#{name}"), { class: 'form-control', required: true } %>
|
|
16
|
+
<% elsif data_node.form_field.number? %>
|
|
17
|
+
<%= number_field_tag "#{key}[data_nodes][field_value][#{i}]", data_node.field_value, { class: 'form-control', required: true } %>
|
|
18
|
+
<% else %>
|
|
19
|
+
<%= text_field_tag "#{key}[data_nodes][field_value][#{i}]", data_node.field_value, size: "64", class: "form-control", required: true %>
|
|
20
|
+
<% end %>
|
|
21
|
+
|
|
22
|
+
</div>
|
|
23
|
+
<% end %>
|
|
24
|
+
<% end %>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<% errors = form.errors || [] %>
|
|
2
|
+
|
|
3
|
+
<% if errors.size > 0 %>
|
|
4
|
+
<div class="error-summary" role="group" aria-labelledby="groupLabel" tabindex="-1">
|
|
5
|
+
|
|
6
|
+
<h1 class="heading-medium error-summary-heading" id="error-summary-heading">
|
|
7
|
+
<%= t '.you_have' %> <%= pluralize(errors.count, "error") %>
|
|
8
|
+
</h1>
|
|
9
|
+
|
|
10
|
+
<ul class="error-summary-list">
|
|
11
|
+
<% errors.each do |attr, msg| %>
|
|
12
|
+
<li>
|
|
13
|
+
<%= link_to msg.html_safe, "##{error_link_id(attr)}", class: "error-text" %>
|
|
14
|
+
</li>
|
|
15
|
+
<% end %>
|
|
16
|
+
</ul>
|
|
17
|
+
</div>
|
|
18
|
+
<% end %>
|
|
19
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<%
|
|
2
|
+
if( Rails.env.development? &&
|
|
3
|
+
DatashiftJourney::Configuration.call.add_state_jumper_toolbar &&
|
|
4
|
+
DatashiftJourney::Configuration.call.state_jumper_states.size > 0)
|
|
5
|
+
%>
|
|
6
|
+
<%- content_for :datashift_journey_state_jumper do %>
|
|
7
|
+
<div id="datashift_journey_state_jumper">
|
|
8
|
+
<ul>
|
|
9
|
+
<li>DS Journey State Jumper: </li>
|
|
10
|
+
<% DatashiftJourney::Configuration.call.state_jumper_states.each do |entry| %>
|
|
11
|
+
<li> <%= link_to entry.display, datashift_journey.build_and_display_path(entry.state, entry.factory) %></li>
|
|
12
|
+
<% end %>
|
|
13
|
+
</ul>
|
|
14
|
+
</div>
|
|
15
|
+
<% end %>
|
|
16
|
+
<% end %>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ignored_warnings": [
|
|
3
|
+
{
|
|
4
|
+
"warning_type": "Cross Site Scripting",
|
|
5
|
+
"warning_code": 4,
|
|
6
|
+
"fingerprint": "f1fc7068ce25236b1c6f9b137081e044d819fbbc32cb0a5100e86720cd10ba96",
|
|
7
|
+
"message": "Unsafe parameter value in link_to href",
|
|
8
|
+
"file": "app/views/datashift_journey/addresses/edit.html.erb",
|
|
9
|
+
"line": 4,
|
|
10
|
+
"link": "http://brakemanscanner.org/docs/warning_types/link_to_href",
|
|
11
|
+
"code": "link_to(\"Show\", datashift_journey.address_path(DatashiftJourney::Address.find(params[:id])))",
|
|
12
|
+
"render_path": ["DatashiftJourney::AddressesController#edit"],
|
|
13
|
+
"location": {
|
|
14
|
+
"type": "template",
|
|
15
|
+
"template": "datashift_journey/addresses/edit (DatashiftJourney::AddressesController#edit)"
|
|
16
|
+
},
|
|
17
|
+
"user_input": "params",
|
|
18
|
+
"confidence": "Medium",
|
|
19
|
+
"note": "Ideally we would pass the instance of @address directly to link_to however because of the namespacing we have to call address_path passing the instance to that. It is still not a user entered value hence this is a false positive by brakeman."
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"warning_type": "Cross Site Scripting",
|
|
23
|
+
"warning_code": 4,
|
|
24
|
+
"fingerprint": "49f08e33accfe24201463ed567cc259387b05b215fdab284d03697d01e013ca1",
|
|
25
|
+
"message": "Unsafe parameter value in link_to href",
|
|
26
|
+
"file": "app/views/datashift_journey/addresses/show.html.erb",
|
|
27
|
+
"line": 2,
|
|
28
|
+
"link": "http://brakemanscanner.org/docs/warning_types/link_to_href",
|
|
29
|
+
"code": "link_to(\"Edit\", datashift_journey.edit_address_path(DatashiftJourney::Address.find(params[:id])))",
|
|
30
|
+
"render_path": ["DatashiftJourney::AddressesController#show"],
|
|
31
|
+
"location": {
|
|
32
|
+
"type": "template",
|
|
33
|
+
"template": "datashift_journey/addresses/show (DatashiftJourney::AddressesController#show)"
|
|
34
|
+
},
|
|
35
|
+
"user_input": "params",
|
|
36
|
+
"confidence": "Medium",
|
|
37
|
+
"note": "Ideally we would pass the instance of @address directly to link_to however because of the namespacing we have to call address_path passing the instance to that. It is still not a user entered value hence this is a false positive by brakeman."
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
"updated": "2015-06-26 15:03:34 +0100",
|
|
41
|
+
"brakeman_version": "3.0.3"
|
|
42
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks
|
|
2
|
+
|
|
3
|
+
# The "main" locale.
|
|
4
|
+
base_locale: en
|
|
5
|
+
## All available locales are inferred from the data by default. Alternatively, specify them explicitly:
|
|
6
|
+
# locales: [es, fr]
|
|
7
|
+
## Reporting locale, default: en. Available: en, ru.
|
|
8
|
+
# internal_locale: en
|
|
9
|
+
|
|
10
|
+
# Read and write translations.
|
|
11
|
+
data:
|
|
12
|
+
## Translations are read from the file system. Supported format: YAML, JSON.
|
|
13
|
+
## Provide a custom adapter:
|
|
14
|
+
# adapter: I18n::Tasks::Data::FileSystem
|
|
15
|
+
|
|
16
|
+
# Locale files or `File.find` patterns where translations are read from:
|
|
17
|
+
read:
|
|
18
|
+
## Default:
|
|
19
|
+
- config/locales/%{locale}.yml
|
|
20
|
+
## More files:
|
|
21
|
+
- config/locales/**/*.%{locale}.yml
|
|
22
|
+
- spec/dummy/config/locales/%{locale}.yml
|
|
23
|
+
## Another gem:
|
|
24
|
+
# - "<%= %x[bundle show vagrant].chomp %>/templates/locales/%{locale}.yml"
|
|
25
|
+
|
|
26
|
+
# Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom:
|
|
27
|
+
# `i18n-tasks normalize -p` will force move the keys according to these rules
|
|
28
|
+
write:
|
|
29
|
+
## For example, write devise and simple form keys to their respective files:
|
|
30
|
+
# - ['{devise, simple_form}.*', 'config/locales/\1.%{locale}.yml']
|
|
31
|
+
## Catch-all default:
|
|
32
|
+
# - config/locales/%{locale}.yml
|
|
33
|
+
|
|
34
|
+
## Specify the router (see Readme for details). Valid values: conservative_router, pattern_router, or a custom class.
|
|
35
|
+
# router: convervative_router
|
|
36
|
+
|
|
37
|
+
yaml:
|
|
38
|
+
write:
|
|
39
|
+
# do not wrap lines at 80 characters
|
|
40
|
+
line_width: -1
|
|
41
|
+
|
|
42
|
+
## Pretty-print JSON:
|
|
43
|
+
# json:
|
|
44
|
+
# write:
|
|
45
|
+
# indent: ' '
|
|
46
|
+
# space: ' '
|
|
47
|
+
# object_nl: "\n"
|
|
48
|
+
# array_nl: "\n"
|
|
49
|
+
|
|
50
|
+
# Find translate calls
|
|
51
|
+
search:
|
|
52
|
+
## Paths or `File.find` patterns to search in:
|
|
53
|
+
# paths:
|
|
54
|
+
# - app/
|
|
55
|
+
|
|
56
|
+
## Root directories for relative keys resolution.
|
|
57
|
+
# relative_roots:
|
|
58
|
+
# - app/views
|
|
59
|
+
# - app/controllers
|
|
60
|
+
# - app/helpers
|
|
61
|
+
# - app/presenters
|
|
62
|
+
|
|
63
|
+
## Files or `File.fnmatch` patterns to exclude from search. Some files are always excluded regardless of this setting:
|
|
64
|
+
## %w(*.jpg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less *.yml *.json)
|
|
65
|
+
exclude:
|
|
66
|
+
- app/assets/images
|
|
67
|
+
- app/assets/fonts
|
|
68
|
+
|
|
69
|
+
## Alternatively, the only files or `File.fnmatch patterns` to search in `paths`:
|
|
70
|
+
## If specified, this settings takes priority over `exclude`, but `exclude` still applies.
|
|
71
|
+
# include: ["*.rb", "*.html.slim"]
|
|
72
|
+
|
|
73
|
+
## Default scanner finds t() and I18n.t() calls.
|
|
74
|
+
# scanner: I18n::Tasks::Scanners::PatternWithScopeScanner
|
|
75
|
+
|
|
76
|
+
## Google Translate
|
|
77
|
+
# translation:
|
|
78
|
+
# # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate
|
|
79
|
+
# api_key: "AbC-dEf5"
|
|
80
|
+
|
|
81
|
+
## Do not consider these keys missing:
|
|
82
|
+
# ignore_missing:
|
|
83
|
+
# - 'errors.messages.{accepted,blank,invalid,too_short,too_long}'
|
|
84
|
+
# - '{devise,simple_form}.*'
|
|
85
|
+
|
|
86
|
+
## Consider these keys used:
|
|
87
|
+
# ignore_unused:
|
|
88
|
+
# - 'activerecord.attributes.*'
|
|
89
|
+
# - '{devise,kaminari,will_paginate}.*'
|
|
90
|
+
# - 'simple_form.{yes,no}'
|
|
91
|
+
# - 'simple_form.{placeholders,hints,labels}.*'
|
|
92
|
+
# - 'simple_form.{error_notification,required}.:'
|
|
93
|
+
|
|
94
|
+
## Exclude these keys from the `i18n-tasks eq-base' report:
|
|
95
|
+
# ignore_eq_base:
|
|
96
|
+
# all:
|
|
97
|
+
# - common.ok
|
|
98
|
+
# fr,es:
|
|
99
|
+
# - common.brand
|
|
100
|
+
|
|
101
|
+
## Ignore these keys completely:
|
|
102
|
+
# ignore:
|
|
103
|
+
# - kaminari.*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Mime::Type.register "application/vnd.api+json", :json
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Rswag::Api.configure do |c|
|
|
2
|
+
|
|
3
|
+
# Specify a root folder where Swagger JSON files are located
|
|
4
|
+
# This is used by the Swagger middleware to serve requests for API descriptions
|
|
5
|
+
# NOTE: We are using rswag-specs to generate Swagger, sp this PATH is duplicated in spec/swagger_helper.rb
|
|
6
|
+
|
|
7
|
+
c.swagger_root = File.join(DatashiftJourney::Engine.root, 'spec', 'swagger')
|
|
8
|
+
|
|
9
|
+
# Inject a lamda function to alter the returned Swagger prior to serialization
|
|
10
|
+
# The function will have access to the rack env for the current request
|
|
11
|
+
# For example, you could leverage this to dynamically assign the "host" property
|
|
12
|
+
#
|
|
13
|
+
#c.swagger_filter = lambda { |swagger, env| swagger['host'] = env['HTTP_HOST'] }
|
|
14
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Rswag::Ui.configure do |c|
|
|
2
|
+
|
|
3
|
+
# List the Swagger endpoints that you want to be documented through the swagger-ui
|
|
4
|
+
# The first parameter is the path (absolute or relative to the UI host) to the corresponding
|
|
5
|
+
# JSON endpoint and the second is a title that will be displayed in the document selector
|
|
6
|
+
# NOTE: If you're using rspec-api to expose Swagger files (under swagger_root) as JSON endpoints,
|
|
7
|
+
# then the list below should correspond to the relative paths for those endpoints
|
|
8
|
+
c.swagger_endpoint '/api-docs/v1/swagger.json', 'API V1 Docs'
|
|
9
|
+
end
|