metadata_presenter 1.5.0 → 1.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aaea9e08a797416b551fd731c80db49d05f02f75f4ac61ecf68c5861d55af9a3
4
- data.tar.gz: e3938447849a5197cc3567c55caacdf0eea2e80e1e4eb05b42e175850d9b34cd
3
+ metadata.gz: 37dfa1fbf4a8bd66310d1fa2e21f6c7a537806298a4cbc9b036f4a3af841262b
4
+ data.tar.gz: cd9ccaf657f85e4c5ac9b5513b74d3d956be16435958e55deb9bae9d7079a2cf
5
5
  SHA512:
6
- metadata.gz: 4f9ac675b0c24ca6ea9a1a9556b13a1151d499750e8aa16d3fbfc5981ac2a93cb99acc03939a188886eaf1254930bcdc1634fd44461b4345ec029a0243bd4d73
7
- data.tar.gz: bf12bf7eefe0f0376fe67801fa74507d0a8267c08106b8c0198023f09999a093090127d4f6b3e8360d2e570cc90a49a36f4263ed77b63dc2e56587ad605a95fd
6
+ metadata.gz: dbc2c13d435a9ab81a7a09d6e68a1a0ba782f0fbbffa6e9704b696bf69c54ce7518d6254b0ce918a651c96985087a90e5caac7b56968c42eb89e60bb8a2d82c6
7
+ data.tar.gz: 9829ce7cd18ba363aad94ec5d785cbcd5eb22edd13e41fd8bbe76f1f882db7778223971ef4e53dc31bae23a17a91033c9926bd4d256156f95d4993b2df6ced32
data/README.md CHANGED
@@ -83,3 +83,15 @@ service.
83
83
  ## Generate documentation
84
84
 
85
85
  Run `rake doc` and open the doc/index.html
86
+
87
+ ## Flow diagrams
88
+
89
+ You can generate flow diagrams calling a rake task:
90
+
91
+ ```
92
+ brew install graphviz
93
+ SERVICE_METADATA="some-form-metadata" rails metadata:flow
94
+ ```
95
+
96
+ This will generate an image with the flow for that metadata. Open that image
97
+ and profit!
@@ -28,6 +28,7 @@ module MetadataPresenter
28
28
  next_page = NextPage.new(
29
29
  service: service,
30
30
  session: session,
31
+ user_data: load_user_data,
31
32
  current_page_url: page_url
32
33
  ).find
33
34
 
@@ -1,7 +1,7 @@
1
1
  module MetadataPresenter
2
2
  class ChangeAnswerController < EngineController
3
3
  def create
4
- session[:return_to_check_you_answer] = true
4
+ session[:return_to_check_your_answer] = true
5
5
  redirect_to_page params[:url]
6
6
  end
7
7
  end
@@ -6,14 +6,19 @@ module MetadataPresenter
6
6
  default_form_builder GOVUKDesignSystemFormBuilder::FormBuilder
7
7
 
8
8
  def back_link
9
- return if @page.blank?
10
-
11
- previous_page = service.previous_page(
9
+ previous_page = PreviousPage.new(
10
+ service: service,
11
+ user_data: load_user_data,
12
12
  current_page: @page,
13
- referrer: request.referer
14
- )&.url
15
-
16
- @back_link ||= File.join(request.script_name, previous_page) if previous_page
13
+ referrer: request.referrer
14
+ ).page
15
+
16
+ if previous_page
17
+ @back_link ||= File.join(
18
+ request.script_name,
19
+ previous_page.url
20
+ )
21
+ end
17
22
  end
18
23
  helper_method :back_link
19
24
 
@@ -13,5 +13,9 @@ module MetadataPresenter
13
13
  Condition.new(condition_metadata)
14
14
  end
15
15
  end
16
+
17
+ def group_by_page
18
+ conditions.group_by(&:next)
19
+ end
16
20
  end
17
21
  end
@@ -1,10 +1,10 @@
1
1
  module MetadataPresenter
2
2
  class NextPage
3
3
  include ActiveModel::Model
4
- attr_accessor :service, :session, :current_page_url
4
+ attr_accessor :service, :session, :user_data, :current_page_url
5
5
 
6
6
  def find
7
- return check_answers_page if return_to_check_you_answer?
7
+ return check_answers_page if return_to_check_your_answer?
8
8
 
9
9
  if conditions?
10
10
  evaluate_conditions
@@ -18,12 +18,12 @@ module MetadataPresenter
18
18
  private
19
19
 
20
20
  def check_answers_page
21
- session[:return_to_check_you_answer] = nil
21
+ session[:return_to_check_your_answer] = nil
22
22
  service.pages.find { |page| page.type == 'page.checkanswers' }
23
23
  end
24
24
 
25
- def return_to_check_you_answer?
26
- session[:return_to_check_you_answer].present?
25
+ def return_to_check_your_answer?
26
+ session[:return_to_check_your_answer].present?
27
27
  end
28
28
 
29
29
  def conditions?
@@ -36,7 +36,7 @@ module MetadataPresenter
36
36
  EvaluateConditions.new(
37
37
  service: service,
38
38
  flow: next_flow,
39
- user_data: session[:user_data]
39
+ user_data: user_data
40
40
  ).page
41
41
  end
42
42
 
@@ -62,6 +62,10 @@ module MetadataPresenter
62
62
  components.select(&:upload?)
63
63
  end
64
64
 
65
+ def standalone?
66
+ type == 'page.standalone'
67
+ end
68
+
65
69
  private
66
70
 
67
71
  def to_components(node_components, collection:)
@@ -0,0 +1,38 @@
1
+ module MetadataPresenter
2
+ class PreviousPage
3
+ include ActiveModel::Model
4
+ attr_accessor :service, :user_data, :current_page, :referrer
5
+
6
+ def page
7
+ # what happens when a user enters in the middle of the flow
8
+ return if no_current_or_referrer_pages? || service.no_back_link?(current_page)
9
+
10
+ if flow.present?
11
+ return referrer_page if return_to_referrer?
12
+
13
+ TraversedPages.new(service, user_data, current_page).last
14
+ else
15
+ service.previous_page(current_page: current_page, referrer: referrer)
16
+ end
17
+ end
18
+
19
+ def flow
20
+ service.metadata['flow']
21
+ end
22
+
23
+ private
24
+
25
+ def referrer_page
26
+ @referrer_page ||= service.find_page_by_url(URI(referrer).path)
27
+ end
28
+
29
+ def return_to_referrer?
30
+ current_page.standalone? ||
31
+ (referrer_page && referrer_page.standalone?)
32
+ end
33
+
34
+ def no_current_or_referrer_pages?
35
+ current_page.blank? || referrer.nil?
36
+ end
37
+ end
38
+ end
@@ -39,6 +39,8 @@ class MetadataPresenter::Service < MetadataPresenter::Metadata
39
39
  end
40
40
 
41
41
  def previous_page(current_page:, referrer:)
42
+ return if current_page.nil? || referrer.nil?
43
+
42
44
  unless no_back_link?(current_page)
43
45
  flow_page(current_page) || referrer_page(referrer)
44
46
  end
@@ -54,16 +56,16 @@ class MetadataPresenter::Service < MetadataPresenter::Metadata
54
56
  MetadataPresenter::Meta.new(configuration['meta'])
55
57
  end
56
58
 
59
+ def no_back_link?(current_page)
60
+ current_page == start_page || current_page == confirmation_page
61
+ end
62
+
57
63
  private
58
64
 
59
65
  def all_pages
60
66
  @all_pages ||= pages + standalone_pages
61
67
  end
62
68
 
63
- def no_back_link?(current_page)
64
- current_page == start_page || current_page == confirmation_page
65
- end
66
-
67
69
  def flow_page(current_page)
68
70
  page_index = pages.index(current_page)
69
71
  pages[page_index - 1] if page_index.present?
@@ -0,0 +1,40 @@
1
+ module MetadataPresenter
2
+ class TraversedPages
3
+ attr_reader :service, :user_data, :current_page
4
+
5
+ def initialize(service, user_data, current_page)
6
+ @service = service
7
+ @user_data = user_data
8
+ @pages = [service.start_page]
9
+ @current_page = current_page
10
+ end
11
+
12
+ delegate :last, to: :all
13
+
14
+ def all
15
+ page_uuid = service.start_page.uuid
16
+
17
+ service.metadata['flow'].size.times do
18
+ break if page_uuid == current_page.uuid
19
+
20
+ flow_object = service.flow(page_uuid)
21
+
22
+ if flow_object.branch?
23
+ page = EvaluateConditions.new(
24
+ service: service,
25
+ flow: flow_object,
26
+ user_data: user_data
27
+ ).page
28
+ page_uuid = page.uuid
29
+ else
30
+ page_uuid = flow_object.default_next
31
+ page = service.find_page_by_uuid(page_uuid)
32
+ end
33
+
34
+ @pages.push(page) if page && page.uuid != current_page.uuid
35
+ end
36
+
37
+ @pages
38
+ end
39
+ end
40
+ end
@@ -820,7 +820,7 @@
820
820
  "created_by": "099d5bf5-5f7b-444c-86ee-9e189cc1a369",
821
821
  "service_id": "488edccd-8411-4ffb-a38b-6a96c6ac28d6",
822
822
  "version_id": "27dc30c9-f7b8-4dec-973a-bd153f6797df",
823
- "service_name": "Version Fixture",
823
+ "service_name": "Branching Fixture",
824
824
  "configuration": {
825
825
  "meta": {
826
826
  "_id": "config.meta",
@@ -1,3 +1,3 @@
1
1
  module MetadataPresenter
2
- VERSION = '1.5.0'.freeze
2
+ VERSION = '1.6.0'.freeze
3
3
  end
@@ -5,48 +5,86 @@ namespace :metadata do
5
5
 
6
6
  desc 'Represent the flow objects in human readable form'
7
7
  task flow: :environment do
8
- service = MetadataPresenter::Service.new(metadata_fixture('branching'))
9
-
10
- start_page = service.start_page
11
- flow = service.flow(start_page.uuid)
12
- first_page = service.find_page_by_uuid(flow.default_next)
13
-
14
- humanized_flow = {}
15
-
16
- humanized_flow[start_page.url] = {
17
- next: first_page.url
18
- }
19
-
20
- service.metadata['flow'].each do |id, _metadata|
21
- flow = service.flow(id)
22
-
23
- if flow.branch?
24
- page = service.find_page_by_uuid(flow.default_next)
25
- humanized_flow[page.url] = {
26
- conditions: flow.conditions.map do |condition|
27
- {
28
- condition_type: condition.condition_type,
29
- criterias: condition.criterias.map do |criteria|
30
- criteria.service = service
31
- {
32
- operator: criteria.operator,
33
- page: criteria.criteria_page.url,
34
- component: criteria.criteria_component.humanised_title,
35
- field: criteria.field_label
36
- }
37
- end
38
- }
8
+ metadata = ENV['SERVICE_METADATA'] || metadata_fixture('branching')
9
+ service = MetadataPresenter::Service.new(metadata)
10
+
11
+ graph = MetadataPresenter::Graph.new(service)
12
+
13
+ graph.draw.generate_image
14
+ puts "Generated file #{graph.filename}"
15
+ system("open #{graph.filename}")
16
+ end
17
+ end
18
+
19
+ require 'ruby-graphviz'
20
+
21
+ module MetadataPresenter
22
+ class Graph
23
+ attr_reader :service, :filename, :nodes
24
+
25
+ delegate :metadata, :start_page, :find_page_by_uuid, :service_slug, to: :service
26
+
27
+ def initialize(service)
28
+ @service = service
29
+ @graphviz = GraphViz.new(:G, type: :digraph)
30
+ @filename = Rails.root.join('tmp', "#{service_slug}.png")
31
+ @nodes = {}
32
+ end
33
+
34
+ def draw
35
+ draw_nodes
36
+ draw_edges
37
+
38
+ self
39
+ end
40
+
41
+ def generate_image
42
+ @graphviz.output(png: filename)
43
+ end
44
+
45
+ private
46
+
47
+ def draw_nodes
48
+ flow.each do |id, _value|
49
+ flow_object = service.flow(id)
50
+
51
+ if flow_object.branch?
52
+ full_description = flow_object.conditions.map do |condition|
53
+ condition.criterias.map do |criteria|
54
+ criteria.service = service
55
+
56
+ "if #{criteria.criteria_component.humanised_title} #{criteria.operator} #{criteria.field_label}"
57
+ end
39
58
  end
40
- }
41
- else
42
- page = service.find_page_by_uuid(id)
43
- next_page = service.find_page_by_uuid(flow.default_next)
44
- if next_page
45
- humanized_flow[page.url] = { next: next_page.url }
59
+ nodes[id] = @graphviz.add_nodes(full_description.flatten.join(' - '))
60
+ else
61
+ current_page = find_page_by_uuid(id)
62
+ nodes[id] = @graphviz.add_nodes(current_page.url)
46
63
  end
47
64
  end
48
65
  end
49
66
 
50
- pp humanized_flow
67
+ def draw_edges
68
+ flow.each do |id, _value|
69
+ flow_object = service.flow(id)
70
+ current_node = nodes[id]
71
+ node_next = nodes[flow_object.default_next]
72
+
73
+ if flow_object.branch?
74
+ @graphviz.add_edges(current_node, node_next, label: 'Conditions are not met', labelfontsize: 8) if node_next
75
+
76
+ flow_object.group_by_page.each do |page_uuid, _conditions|
77
+ conditions_node = nodes[page_uuid]
78
+ @graphviz.add_edges(current_node, conditions_node, label: 'Conditions are met', labelfontsize: 8) if conditions_node
79
+ end
80
+ elsif node_next
81
+ @graphviz.add_edges(current_node, node_next)
82
+ end
83
+ end
84
+ end
85
+
86
+ def flow
87
+ metadata['flow']
88
+ end
51
89
  end
52
90
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metadata_presenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - MoJ Online
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-29 00:00:00.000000000 Z
11
+ date: 2021-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: govuk_design_system_formbuilder
@@ -128,6 +128,20 @@ dependencies:
128
128
  - - ">="
129
129
  - !ruby/object:Gem::Version
130
130
  version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: ruby-graphviz
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
131
145
  - !ruby/object:Gem::Dependency
132
146
  name: rspec-rails
133
147
  requirement: !ruby/object:Gem::Requirement
@@ -277,7 +291,9 @@ files:
277
291
  - app/models/metadata_presenter/offline_upload_adapter.rb
278
292
  - app/models/metadata_presenter/page.rb
279
293
  - app/models/metadata_presenter/page_answers.rb
294
+ - app/models/metadata_presenter/previous_page.rb
280
295
  - app/models/metadata_presenter/service.rb
296
+ - app/models/metadata_presenter/traversed_pages.rb
281
297
  - app/models/metadata_presenter/uploaded_file.rb
282
298
  - app/operators/metadata_presenter/base_operator.rb
283
299
  - app/operators/metadata_presenter/is_answered_operator.rb