datashift_journey 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|