metadata_presenter 1.5.0 → 1.6.0

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