alembic 0.1.0 → 0.2.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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -22
  3. data/app/assets/builds/alembic/page_builder.css +1 -1
  4. data/app/assets/builds/alembic/page_builder.js +3 -3
  5. data/app/controllers/alembic/application_controller.rb +0 -16
  6. data/app/controllers/alembic/flows_controller.rb +6 -90
  7. data/app/controllers/alembic/manage/base_controller.rb +1 -0
  8. data/app/controllers/alembic/manage/flows_controller.rb +7 -44
  9. data/app/controllers/alembic/manage/pages_controller.rb +8 -1
  10. data/app/controllers/alembic/manage/previews_controller.rb +4 -19
  11. data/app/controllers/alembic/pages_controller.rb +19 -0
  12. data/app/controllers/concerns/alembic/summarizes.rb +38 -0
  13. data/app/helpers/alembic/pages_helper.rb +39 -0
  14. data/app/models/alembic/flow/definition_summary.rb +9 -0
  15. data/app/models/alembic/flow/run_summary.rb +10 -0
  16. data/app/models/alembic/flow/summaries.rb +36 -5
  17. data/app/models/alembic/flow/summary_version.rb +1 -1
  18. data/app/models/alembic/outputs/grouped.rb +1 -1
  19. data/app/models/alembic/outputs/percentage.rb +1 -1
  20. data/app/models/alembic/outputs/weighted_sum.rb +1 -1
  21. data/app/models/alembic/page/drawing.rb +17 -0
  22. data/app/models/alembic/page/options.rb +46 -0
  23. data/app/models/alembic/page/version.rb +13 -0
  24. data/app/models/alembic/page.rb +32 -0
  25. data/app/views/alembic/flows/complete.html.erb +3 -3
  26. data/app/views/alembic/flows/show.html.erb +6 -6
  27. data/app/views/alembic/manage/flows/edit.html.erb +10 -10
  28. data/app/views/alembic/manage/pages/_block_content.html.erb +1 -1
  29. data/app/views/alembic/manage/pages/index.html.erb +4 -1
  30. data/app/views/alembic/manage/pages/show.html.erb +7 -1
  31. data/app/views/alembic/pages/show.html.erb +5 -0
  32. data/config/routes.rb +8 -19
  33. data/db/migrate/20260825224538_remove_published_version_from_alembic_diagnostics.rb +21 -1
  34. data/db/migrate/20260922120000_add_slug_to_alembic_pages.rb +6 -0
  35. data/db/migrate/20260922130000_create_alembic_page_versions.rb +16 -0
  36. data/db/migrate/20260924220000_move_flows_onto_easy_flow.rb +166 -0
  37. data/lib/alembic/engine.rb +2 -11
  38. data/lib/alembic/version.rb +1 -1
  39. data/lib/alembic.rb +30 -6
  40. metadata +35 -71
  41. data/app/assets/builds/alembic/canvas.js +0 -1
  42. data/app/controllers/alembic/manage/canvas_controller.rb +0 -183
  43. data/app/controllers/alembic/manage/definitions_controller.rb +0 -15
  44. data/app/controllers/alembic/manage/versions_controller.rb +0 -22
  45. data/app/controllers/concerns/alembic/manage/draws_canvas.rb +0 -35
  46. data/app/javascript/alembic/canvas/Canvas.jsx +0 -197
  47. data/app/javascript/alembic/canvas/Connector.jsx +0 -30
  48. data/app/javascript/alembic/canvas/ConnectorLayer.jsx +0 -31
  49. data/app/javascript/alembic/canvas/Control.jsx +0 -42
  50. data/app/javascript/alembic/canvas/Inspector.jsx +0 -44
  51. data/app/javascript/alembic/canvas/Panel.jsx +0 -67
  52. data/app/javascript/alembic/canvas/Placeholder.jsx +0 -24
  53. data/app/javascript/alembic/canvas/Port.jsx +0 -16
  54. data/app/javascript/alembic/canvas/Records.jsx +0 -34
  55. data/app/javascript/alembic/canvas/StepCard.jsx +0 -57
  56. data/app/javascript/alembic/canvas/Toolbar.jsx +0 -19
  57. data/app/javascript/alembic/canvas/TypePicker.jsx +0 -21
  58. data/app/javascript/alembic/canvas/changes.js +0 -5
  59. data/app/javascript/alembic/canvas/choices.js +0 -4
  60. data/app/javascript/alembic/canvas/flow.js +0 -7
  61. data/app/javascript/alembic/canvas/flowSender.js +0 -22
  62. data/app/javascript/alembic/canvas/ids.js +0 -7
  63. data/app/javascript/alembic/canvas/rows.js +0 -2
  64. data/app/javascript/alembic/canvas/styles.js +0 -3
  65. data/app/javascript/alembic/canvas/useConnectors.js +0 -75
  66. data/app/javascript/alembic/canvas/useFlow.js +0 -17
  67. data/app/javascript/alembic/canvas.jsx +0 -13
  68. data/app/models/alembic/asked.rb +0 -3
  69. data/app/models/alembic/choice.rb +0 -7
  70. data/app/models/alembic/flow/admission.rb +0 -19
  71. data/app/models/alembic/flow/canvas.rb +0 -167
  72. data/app/models/alembic/flow/change.rb +0 -18
  73. data/app/models/alembic/flow/condition.rb +0 -24
  74. data/app/models/alembic/flow/definition.rb +0 -132
  75. data/app/models/alembic/flow/digest.rb +0 -116
  76. data/app/models/alembic/flow/document.rb +0 -131
  77. data/app/models/alembic/flow/drawing.rb +0 -15
  78. data/app/models/alembic/flow/edge.rb +0 -9
  79. data/app/models/alembic/flow/edit_history.rb +0 -75
  80. data/app/models/alembic/flow/layout.rb +0 -88
  81. data/app/models/alembic/flow/name.rb +0 -15
  82. data/app/models/alembic/flow/node.rb +0 -5
  83. data/app/models/alembic/flow/output.rb +0 -23
  84. data/app/models/alembic/flow/progress/kept.rb +0 -38
  85. data/app/models/alembic/flow/progress/loose.rb +0 -43
  86. data/app/models/alembic/flow/progress.rb +0 -11
  87. data/app/models/alembic/flow/registry.rb +0 -25
  88. data/app/models/alembic/flow/run.rb +0 -54
  89. data/app/models/alembic/flow/runner.rb +0 -65
  90. data/app/models/alembic/flow/settings.rb +0 -80
  91. data/app/models/alembic/flow/start.rb +0 -13
  92. data/app/models/alembic/flow/step.rb +0 -42
  93. data/app/models/alembic/flow/step_type/declaration.rb +0 -118
  94. data/app/models/alembic/flow/step_type.rb +0 -69
  95. data/app/models/alembic/flow/switch.rb +0 -17
  96. data/app/models/alembic/flow/terminal.rb +0 -13
  97. data/app/models/alembic/flow/validator.rb +0 -171
  98. data/app/models/alembic/flow/version.rb +0 -26
  99. data/app/models/alembic/flow/violation.rb +0 -9
  100. data/app/models/alembic/flow.rb +0 -44
  101. data/app/models/alembic/runner.rb +0 -13
  102. data/app/models/alembic/steps/question.rb +0 -52
  103. data/app/views/alembic/flow/steps/_choosing.html.erb +0 -9
  104. data/app/views/alembic/flows/step.html.erb +0 -27
  105. data/app/views/alembic/manage/definitions/edit.html.erb +0 -13
  106. data/app/views/alembic/manage/flows/index.html.erb +0 -32
  107. data/app/views/alembic/manage/flows/show.html.erb +0 -26
  108. data/app/views/alembic/manage/versions/index.html.erb +0 -41
@@ -1,24 +0,0 @@
1
- module Alembic
2
- module Flow
3
- class Condition
4
- include Step
5
-
6
- step_name "Condition"
7
-
8
- setting :step, type: :previous_step
9
- setting :output, outputs_of: :step, required: true
10
- setting :comparison, type: :select, options: [ "is", "is not" ], required: true
11
- setting :answer, from: :output, required: true
12
-
13
- output :result, type: :boolean, values: [ true, false ]
14
-
15
- names_by { |node| node.config.values_at("step", "comparison", "answer").compact_blank.join(" ").presence }
16
-
17
- def route(node, state)
18
- matched = state[node.config["step"]] == node.config["answer"]
19
-
20
- node.config["comparison"] == "is not" ? !matched : matched
21
- end
22
- end
23
- end
24
- end
@@ -1,132 +0,0 @@
1
- module Alembic
2
- module Flow
3
- class Definition < ApplicationRecord
4
- self.table_name = "alembic_flows"
5
-
6
- enum :status, { active: "active", hidden: "hidden", inactive: "inactive" }
7
- enum :kind, { scored: "scored", guide: "guide" }
8
- enum :persists, { unsaved: "unsaved", each_step: "each_step", on_finish: "on_finish" }
9
-
10
- validates :slug, presence: true
11
-
12
- after_initialize :begin_the_flow, if: :new_record?
13
-
14
- scope :listable, -> { active }
15
-
16
- # Declared before :definition_versions so responses clear first, otherwise
17
- # destroying a diagnostic trips the responses -> definition_versions FK.
18
- has_many :runs, class_name: "Alembic::Flow::Run", foreign_key: :flow_id, dependent: :destroy
19
- has_many :definition_versions, class_name: "Alembic::Flow::Version", foreign_key: :flow_id, dependent: :destroy
20
- has_many :summary_versions, class_name: "Alembic::Flow::SummaryVersion", foreign_key: :flow_id, dependent: :destroy
21
-
22
- def self.upsert_definition(definition)
23
- find_or_initialize_by(slug: definition["slug"]).tap do |diagnostic|
24
- diagnostic.save!
25
- diagnostic.record_definition(definition) unless diagnostic.definition == definition
26
- end
27
- end
28
-
29
- def definition
30
- current_definition_version&.definition
31
- end
32
-
33
- def current_definition_version
34
- definition_versions.find_by(number: cursor)
35
- end
36
-
37
- def edit_history
38
- @edit_history ||= EditHistory.new(self)
39
- end
40
-
41
- def summaries
42
- @summaries ||= Summaries.new(self)
43
- end
44
-
45
- def publish
46
- create_version
47
-
48
- publish_version(current_definition_version)
49
- end
50
-
51
- def return_to(version)
52
- raise ActiveRecord::RecordNotFound unless definition_versions.exists?(version.id)
53
- raise OutOfService if version.out_of_service?
54
-
55
- update!(document: version.definition, undone_changes: [],
56
- changes_since_version: changes_since_version.to_a + [ returning_to(version) ])
57
- end
58
-
59
- def create_version
60
- record_definition(document, changes_since_version.to_a) unless versioned?
61
-
62
- update!(undo_history: edit_history.undoable, changes_since_version: [], undone_changes: [])
63
- end
64
-
65
- def returning_to(version)
66
- { "action" => "returned", "steps" => [], "named" => [],
67
- "detail" => "version #{version.number}", "before" => document }
68
- end
69
-
70
- def versioned?
71
- document == definition
72
- end
73
-
74
- def record_definition(payload, captured = [])
75
- definition_versions.create!(number: next_definition_number, definition: payload,
76
- changes_captured: captured.map { |change| change.except("before") })
77
- .tap { |version| update!(definition_cursor: version.number, document: payload) }
78
- end
79
-
80
- def publish_version(version)
81
- raise OutOfService if version.out_of_service?
82
- return if live_version == version
83
-
84
- live_version&.update!(status: :superseded)
85
- version.update!(status: :live)
86
- end
87
-
88
- def available?
89
- !inactive?
90
- end
91
-
92
- def retire_version(version)
93
- version.update!(status: :retired)
94
- end
95
-
96
- def withdraw_version(version)
97
- version.update!(status: :withdrawn)
98
- end
99
-
100
- def live_version
101
- definition_versions.find_by(status: :live)
102
- end
103
-
104
- def live_definition
105
- live_version&.definition
106
- end
107
-
108
- def runner
109
- Runner.new(live_definition)
110
- end
111
-
112
- private
113
-
114
- def begin_the_flow
115
- self.document ||= { "nodes" => [ { "id" => "start", "type" => "start" }, { "id" => "end", "type" => "terminal" } ],
116
- "edges" => [ { "from" => "start", "to" => "end" } ] }
117
- end
118
-
119
- def cursor
120
- definition_cursor || recorded_numbers.max
121
- end
122
-
123
- def recorded_numbers
124
- definition_versions.pluck(:number)
125
- end
126
-
127
- def next_definition_number
128
- (definition_versions.maximum(:number) || 0) + 1
129
- end
130
- end
131
- end
132
- end
@@ -1,116 +0,0 @@
1
- module Alembic
2
- module Flow
3
- class Digest
4
- def initialize(document, registry: Flow.registry)
5
- @document = document
6
- @registry = registry
7
- end
8
-
9
- def entry
10
- @document.node(@document.entry)
11
- end
12
-
13
- def step(id)
14
- @document.node(id)
15
- end
16
-
17
- def steps
18
- @document.nodes
19
- end
20
-
21
- def preceding(id)
22
- return [] unless @document.reachable.include?(id)
23
-
24
- @document.nodes.map(&:id).uniq
25
- .reject { |other| other == id || @document.reachable(without: other).include?(id) }
26
- end
27
-
28
- def routing_values(id)
29
- named = step(id)
30
- return [] unless named && step_type(named)&.routes?
31
-
32
- step_type(named).outputs.flat_map { |output| values_taken(output, named) }.map { |value| value["value"].to_s }
33
- end
34
-
35
- def values_taken(output, node)
36
- return output.values_for(node) unless output.from
37
-
38
- values_out_of(node.config[output.from.to_s])
39
- end
40
-
41
- def values_of(id, output_name)
42
- named = step(id)
43
- return [] unless named && output_name.present?
44
-
45
- step_type(named)&.values_of(output_name, named).to_a
46
- end
47
-
48
- def outputs_of(id)
49
- named = step(id)
50
- return [] unless named
51
-
52
- step_type(named)&.outputs.to_a.map { |output| { "value" => output.name.to_s, "label" => output.label } }
53
- end
54
-
55
- def values_out_of(id)
56
- named = step(id)
57
- return [] unless named
58
-
59
- step_type(named)&.outputs.to_a.flat_map { |output| output.values_for(named) }
60
- end
61
-
62
- def requirements(id)
63
- node = step(id)
64
- step_type(node)&.settings&.requirements_for(node.config).to_a
65
- end
66
-
67
- def next_step(state)
68
- walk(state).last
69
- end
70
-
71
- def state_on_path(state)
72
- state.slice(*walk(state).first)
73
- end
74
-
75
- private
76
-
77
- def walk(state)
78
- recorded = []
79
- visited = []
80
- cursor = entry
81
-
82
- while cursor && !visited.include?(cursor.id)
83
- return [ recorded, cursor ] if pending?(cursor, state)
84
-
85
- recorded << cursor.id if state.key?(cursor.id)
86
- visited << cursor.id
87
- cursor = successor(cursor, state)
88
- end
89
-
90
- [ recorded, nil ]
91
- end
92
-
93
- def pending?(node, state)
94
- return false if state.key?(node.id)
95
-
96
- step_type(node)&.awaits_input? || acts?(node)
97
- end
98
-
99
- def acts?(node)
100
- step_type(node)&.acts? || false
101
- end
102
-
103
- def successor(node, state)
104
- leaving = @document.edges_from(node.id)
105
- port = step_type(node)&.route(node, state)
106
- taken = port.nil? ? leaving.first : leaving.find { |edge| edge.on.to_s == port.to_s }
107
-
108
- taken && @document.node(taken.to)
109
- end
110
-
111
- def step_type(node)
112
- @registry.fetch(node.type) if node && @registry.registered?(node.type)
113
- end
114
- end
115
- end
116
- end
@@ -1,131 +0,0 @@
1
- module Alembic
2
- module Flow
3
- class Document
4
- def initialize(document, registry: Flow.registry)
5
- @document = document
6
- @registry = registry
7
- end
8
-
9
- def nodes
10
- Array(@document["nodes"]).map { |node| Node.new(id: node["id"], type: node["type"], config: node.except("id", "type")) }
11
- end
12
-
13
- def edges
14
- Array(@document["edges"]).map { |edge| Edge.new(from: edge["from"], to: edge["to"], on: edge["on"]) }
15
- end
16
-
17
- def entry
18
- beginnings.first
19
- end
20
-
21
- def beginnings
22
- nodes.select { |node| begins_here?(node) }.map(&:id)
23
- end
24
-
25
- def begins_here?(node)
26
- @registry.registered?(node.type) && @registry.fetch(node.type).begins_here?
27
- end
28
-
29
- def node(id)
30
- nodes.find { |node| node.id == id }
31
- end
32
-
33
- def edges_from(id)
34
- edges.select { |edge| edge.from == id }
35
- end
36
-
37
- def reachable(without: nil)
38
- found = []
39
- frontier = [ entry ]
40
-
41
- while (id = frontier.shift)
42
- next if found.include?(id) || id == without
43
-
44
- found << id
45
- frontier.concat(edges_from(id).map(&:to))
46
- end
47
-
48
- found
49
- end
50
-
51
- def to_h
52
- @document
53
- end
54
-
55
- def insert(node, on:, leaving: nil)
56
- source, target = on
57
- replaced = raw_edges.find { |edge| edge["from"] == source && edge["to"] == target }
58
- bridged = [ { "from" => source, "to" => node["id"], "on" => replaced&.fetch("on", nil) }.compact,
59
- { "from" => node["id"], "to" => target, "on" => leaving }.compact ]
60
-
61
- with(nodes: raw_nodes + [ node ], edges: (raw_edges - [ replaced ]) + bridged)
62
- end
63
-
64
- def add(node)
65
- with(nodes: raw_nodes + [ node ], edges: raw_edges)
66
- end
67
-
68
- def connect(from:, to:, on: nil)
69
- with(nodes: raw_nodes, edges: raw_edges + [ { "from" => from, "to" => to, "on" => on }.compact ])
70
- end
71
-
72
- def disconnect(from:, to:)
73
- with(nodes: raw_nodes, edges: raw_edges.reject { |edge| edge["from"] == from && edge["to"] == to })
74
- end
75
-
76
- def move(id, on:, leaving: nil)
77
- step = raw_nodes.find { |node| node["id"] == id }
78
- return self unless step
79
-
80
- remove(id).insert(step, on: on, leaving: leaving)
81
- end
82
-
83
- def configure(id, config)
84
- reconfigured = raw_nodes.map do |node|
85
- node["id"] == id ? node.slice("id", "type").merge(config) : node
86
- end
87
-
88
- with(nodes: reconfigured, edges: raw_edges)
89
- end
90
-
91
- def rewire(from:, to:, target:)
92
- rewritten = raw_edges.map do |edge|
93
- edge["from"] == from && edge["to"] == to ? edge.merge("to" => target) : edge
94
- end
95
-
96
- with(nodes: raw_nodes, edges: rewritten)
97
- end
98
-
99
- def remove(id)
100
- incoming = raw_edges.select { |edge| edge["to"] == id }
101
- outgoing = raw_edges.select { |edge| edge["from"] == id }
102
-
103
- with(nodes: raw_nodes.reject { |node| node["id"] == id },
104
- edges: (raw_edges - incoming - outgoing) + bridges(incoming, outgoing))
105
- end
106
-
107
- private
108
-
109
- def bridges(incoming, outgoing)
110
- incoming.product(outgoing).map do |arriving, leaving|
111
- { "from" => arriving["from"], "to" => leaving["to"], "on" => arriving["on"] }.compact
112
- end
113
- end
114
-
115
- def raw_nodes
116
- Array(@document["nodes"])
117
- end
118
-
119
- def raw_edges
120
- Array(@document["edges"])
121
- end
122
-
123
- def with(nodes:, edges:)
124
- Document.new(@document.merge("nodes" => nodes, "edges" => edges), registry: @registry).tap do |edited|
125
- broken = Validator.new(edited, registry: @registry).malformations
126
- raise InvalidEdit, broken.map { |violation| "#{violation.node}: #{violation.problem}" }.join(", ") if broken.any?
127
- end
128
- end
129
- end
130
- end
131
- end
@@ -1,15 +0,0 @@
1
- module Alembic
2
- module Flow
3
- module Drawing
4
- def self.of(node, registry = Flow.registry)
5
- named(node, registry).presence || Flow.drawing
6
- end
7
-
8
- def self.named(node, registry)
9
- return unless node && registry.registered?(node.type)
10
-
11
- registry.fetch(node.type).drawn_by
12
- end
13
- end
14
- end
15
- end
@@ -1,9 +0,0 @@
1
- module Alembic
2
- module Flow
3
- Edge = Data.define(:from, :to, :on) do
4
- def initialize(from:, to:, on: nil)
5
- super
6
- end
7
- end
8
- end
9
- end
@@ -1,75 +0,0 @@
1
- module Alembic
2
- module Flow
3
- class EditHistory
4
- def initialize(flow)
5
- @flow = flow
6
- end
7
-
8
- def undoable?
9
- undoable.any?
10
- end
11
-
12
- def redoable?
13
- undone.any?
14
- end
15
-
16
- def undoable
17
- @flow.undo_history.to_a + @flow.changes_since_version.to_a
18
- end
19
-
20
- def undo_change
21
- undone_change = undoable.last
22
- return unless undone_change
23
-
24
- @flow.update!(document: undone_change["before"],
25
- undone_changes: undone + [ undone_change.merge("after" => @flow.document) ],
26
- undo_history: @flow.undo_history.to_a[0...-1],
27
- changes_since_version: @flow.changes_since_version.to_a[0...-1])
28
- end
29
-
30
- def redo_change
31
- redone = undone.last
32
- return unless redone
33
-
34
- @flow.update!(document: redone["after"], undone_changes: undone[0...-1],
35
- changes_since_version: @flow.changes_since_version.to_a + [ redone.except("after") ])
36
- end
37
-
38
- def record(edited, action, steps, before)
39
- @flow.update!(document: edited.to_h, undone_changes: [],
40
- changes_since_version: with(edited, action, steps, before))
41
- end
42
-
43
- def edit_document(payload)
44
- @flow.update!(document: payload, undone_changes: [],
45
- changes_since_version: @flow.changes_since_version.to_a + [ edited_by_hand ])
46
- end
47
-
48
- private
49
-
50
- def with(edited, action, steps, before)
51
- return @flow.changes_since_version.to_a unless action
52
-
53
- @flow.changes_since_version.to_a +
54
- [ { "action" => action.to_s, "steps" => steps.map(&:to_s),
55
- "named" => steps.map { |id| named(edited, id) }, "before" => before } ]
56
- end
57
-
58
- def named(edited, id)
59
- Name.of(edited.node(id.to_s) || document.node(id.to_s))
60
- end
61
-
62
- def document
63
- Document.new(@flow.document || @flow.definition || {})
64
- end
65
-
66
- def undone
67
- @flow.undone_changes.to_a
68
- end
69
-
70
- def edited_by_hand
71
- { "action" => "edited", "steps" => [], "named" => [ "the definition" ], "before" => @flow.document }
72
- end
73
- end
74
- end
75
- end
@@ -1,88 +0,0 @@
1
- module Alembic
2
- module Flow
3
- class Layout
4
- SPREAD = 2
5
-
6
- def initialize(document)
7
- @document = document
8
- end
9
-
10
- def positions
11
- rows = depths
12
- columns = columns_for(rows)
13
-
14
- rows.to_h { |id, row| [ id, { "row" => row, "column" => columns[id] } ] }
15
- end
16
-
17
- private
18
-
19
- def depths
20
- walked = walk_from_entry
21
-
22
- walked.merge(stranded(walked).index_with(next_row(walked)))
23
- end
24
-
25
- def walk_from_entry
26
- seen = {}
27
- frontier = starting_points.map { |id| [ id, 0 ] }
28
-
29
- until frontier.empty?
30
- id, depth = frontier.shift
31
- next if seen.key?(id)
32
-
33
- seen[id] = depth
34
- @document.edges_from(id).each { |edge| frontier << [ edge.to, depth + 1 ] if known?(edge.to) }
35
- end
36
-
37
- seen
38
- end
39
-
40
- def starting_points
41
- return [ @document.entry ] if known?(@document.entry)
42
-
43
- arrived = @document.edges.map(&:to)
44
- @document.nodes.map(&:id).reject { |id| arrived.include?(id) }
45
- end
46
-
47
- def columns_for(rows)
48
- @columns = {}
49
- @next_leaf = 0
50
- rows.keys.each { |id| place(id, branches(rows)) }
51
- @columns
52
- end
53
-
54
- def branches(rows)
55
- claimed = {}
56
-
57
- rows.keys.to_h do |id|
58
- mine = @document.edges_from(id).map(&:to).uniq
59
- .select { |child| rows[child] == rows[id] + 1 && !claimed.key?(child) }
60
- mine.each { |child| claimed[child] = true }
61
- [ id, mine ]
62
- end
63
- end
64
-
65
- def place(id, branches)
66
- return @columns[id] if @columns.key?(id)
67
-
68
- mine = branches[id].to_a
69
- return @columns[id] = (@next_leaf += SPREAD) - SPREAD if mine.empty?
70
-
71
- spans = mine.map { |child| place(child, branches) }
72
- @columns[id] = (spans.min + spans.max) / 2
73
- end
74
-
75
- def stranded(walked)
76
- @document.nodes.map(&:id).uniq - walked.keys
77
- end
78
-
79
- def next_row(walked)
80
- (walked.values.max || -1) + 1
81
- end
82
-
83
- def known?(id)
84
- @document.node(id).present?
85
- end
86
- end
87
- end
88
- end
@@ -1,15 +0,0 @@
1
- module Alembic
2
- module Flow
3
- module Name
4
- def self.of(node, registry = Flow.registry)
5
- return "" unless node
6
-
7
- named(node, registry) || node.id
8
- end
9
-
10
- def self.named(node, registry)
11
- registry.fetch(node.type).name_of(node) if registry.registered?(node.type)
12
- end
13
- end
14
- end
15
- end
@@ -1,5 +0,0 @@
1
- module Alembic
2
- module Flow
3
- Node = Data.define(:id, :type, :config)
4
- end
5
- end
@@ -1,23 +0,0 @@
1
- module Alembic
2
- module Flow
3
- Output = Data.define(:name, :label, :type, :values, :from) do
4
- def initialize(name:, label: nil, type: :string, values: nil, from: nil)
5
- raise UnknownOutputType, "#{type} is not one of #{OUTPUT_TYPES.join(', ')}" unless OUTPUT_TYPES.include?(type)
6
-
7
- super(name: name, label: label.presence || name.to_s.humanize, type: type, values: values, from: from)
8
- end
9
-
10
- def values_for(node)
11
- Array(values.respond_to?(:call) ? values.call(node) : values).map { |value| taken(value) }
12
- end
13
-
14
- private
15
-
16
- def taken(value)
17
- return value if value.is_a?(Hash)
18
-
19
- { "value" => value, "label" => value.to_s }
20
- end
21
- end
22
- end
23
- end
@@ -1,38 +0,0 @@
1
- module Alembic
2
- module Flow
3
- module Progress
4
- class Kept
5
- def initialize(run)
6
- @run = run
7
- end
8
-
9
- def definition
10
- @run.pinned_definition
11
- end
12
-
13
- def summary_of(state)
14
- return [] if @run.pinned_summary.blank?
15
-
16
- Summary::Report.new(@run.pinned_summary)
17
- .results(Summary::Run.new(state: state, steps: @run.pinned_steps))
18
- end
19
-
20
- def recorded
21
- @run.recorded
22
- end
23
-
24
- def record(id, value)
25
- @run.record(id.to_sym, value)
26
- end
27
-
28
- def finish(_state)
29
- @run
30
- end
31
-
32
- def discard_last
33
- @run.discard_last
34
- end
35
- end
36
- end
37
- end
38
- end