alembic 0.1.0 → 0.3.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 (123) 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 +1 -16
  6. data/app/controllers/alembic/flows_controller.rb +6 -90
  7. data/app/controllers/alembic/manage/base_controller.rb +2 -0
  8. data/app/controllers/alembic/manage/flows_controller.rb +12 -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 +59 -0
  13. data/app/helpers/alembic/application_helper.rb +2 -2
  14. data/app/helpers/alembic/pages_helper.rb +40 -0
  15. data/app/helpers/alembic/result_blocks_helper.rb +45 -0
  16. data/app/models/alembic/flow/definition_summary.rb +10 -0
  17. data/app/models/alembic/flow/run_summary.rb +10 -0
  18. data/app/models/alembic/flow/summaries.rb +44 -5
  19. data/app/models/alembic/flow/summary_version.rb +1 -1
  20. data/app/models/alembic/outputs/band.rb +1 -1
  21. data/app/models/alembic/outputs/grouped.rb +1 -1
  22. data/app/models/alembic/outputs/lowest.rb +5 -3
  23. data/app/models/alembic/outputs/percentage.rb +1 -1
  24. data/app/models/alembic/outputs/weighted_sum.rb +1 -1
  25. data/app/models/alembic/page/drawing.rb +17 -0
  26. data/app/models/alembic/page/options.rb +53 -0
  27. data/app/models/alembic/page/version.rb +13 -0
  28. data/app/models/alembic/page.rb +32 -0
  29. data/app/models/alembic/result_blocks.rb +29 -0
  30. data/app/models/alembic/summary/report.rb +1 -1
  31. data/app/models/alembic/summary/result.rb +1 -1
  32. data/app/views/alembic/blocks/_answers.html.erb +11 -0
  33. data/app/views/alembic/blocks/_band.html.erb +6 -0
  34. data/app/views/alembic/blocks/_categories.html.erb +11 -0
  35. data/app/views/alembic/blocks/_lead.html.erb +15 -0
  36. data/app/views/alembic/blocks/_score.html.erb +7 -0
  37. data/app/views/alembic/blocks/_weakest.html.erb +12 -0
  38. data/app/views/alembic/flows/complete.html.erb +12 -6
  39. data/app/views/alembic/flows/show.html.erb +6 -6
  40. data/app/views/alembic/flows/summary_page.html.erb +5 -0
  41. data/app/views/alembic/manage/flows/edit.html.erb +16 -10
  42. data/app/views/alembic/manage/pages/_block_content.html.erb +1 -1
  43. data/app/views/alembic/manage/pages/index.html.erb +4 -1
  44. data/app/views/alembic/manage/pages/show.html.erb +7 -1
  45. data/app/views/alembic/pages/show.html.erb +5 -0
  46. data/config/routes.rb +8 -19
  47. data/db/migrate/20260825224538_remove_published_version_from_alembic_diagnostics.rb +21 -1
  48. data/db/migrate/20260922120000_add_slug_to_alembic_pages.rb +6 -0
  49. data/db/migrate/20260922130000_create_alembic_page_versions.rb +16 -0
  50. data/db/migrate/20260924220000_move_flows_onto_easy_flow.rb +166 -0
  51. data/db/migrate/20260930120000_add_summary_page_to_alembic_flow_definition_summaries.rb +6 -0
  52. data/lib/alembic/engine.rb +6 -11
  53. data/lib/alembic/version.rb +1 -1
  54. data/lib/alembic.rb +34 -6
  55. metadata +45 -71
  56. data/app/assets/builds/alembic/canvas.js +0 -1
  57. data/app/controllers/alembic/manage/canvas_controller.rb +0 -183
  58. data/app/controllers/alembic/manage/definitions_controller.rb +0 -15
  59. data/app/controllers/alembic/manage/versions_controller.rb +0 -22
  60. data/app/controllers/concerns/alembic/manage/draws_canvas.rb +0 -35
  61. data/app/javascript/alembic/canvas/Canvas.jsx +0 -197
  62. data/app/javascript/alembic/canvas/Connector.jsx +0 -30
  63. data/app/javascript/alembic/canvas/ConnectorLayer.jsx +0 -31
  64. data/app/javascript/alembic/canvas/Control.jsx +0 -42
  65. data/app/javascript/alembic/canvas/Inspector.jsx +0 -44
  66. data/app/javascript/alembic/canvas/Panel.jsx +0 -67
  67. data/app/javascript/alembic/canvas/Placeholder.jsx +0 -24
  68. data/app/javascript/alembic/canvas/Port.jsx +0 -16
  69. data/app/javascript/alembic/canvas/Records.jsx +0 -34
  70. data/app/javascript/alembic/canvas/StepCard.jsx +0 -57
  71. data/app/javascript/alembic/canvas/Toolbar.jsx +0 -19
  72. data/app/javascript/alembic/canvas/TypePicker.jsx +0 -21
  73. data/app/javascript/alembic/canvas/changes.js +0 -5
  74. data/app/javascript/alembic/canvas/choices.js +0 -4
  75. data/app/javascript/alembic/canvas/flow.js +0 -7
  76. data/app/javascript/alembic/canvas/flowSender.js +0 -22
  77. data/app/javascript/alembic/canvas/ids.js +0 -7
  78. data/app/javascript/alembic/canvas/rows.js +0 -2
  79. data/app/javascript/alembic/canvas/styles.js +0 -3
  80. data/app/javascript/alembic/canvas/useConnectors.js +0 -75
  81. data/app/javascript/alembic/canvas/useFlow.js +0 -17
  82. data/app/javascript/alembic/canvas.jsx +0 -13
  83. data/app/models/alembic/asked.rb +0 -3
  84. data/app/models/alembic/choice.rb +0 -7
  85. data/app/models/alembic/flow/admission.rb +0 -19
  86. data/app/models/alembic/flow/canvas.rb +0 -167
  87. data/app/models/alembic/flow/change.rb +0 -18
  88. data/app/models/alembic/flow/condition.rb +0 -24
  89. data/app/models/alembic/flow/definition.rb +0 -132
  90. data/app/models/alembic/flow/digest.rb +0 -116
  91. data/app/models/alembic/flow/document.rb +0 -131
  92. data/app/models/alembic/flow/drawing.rb +0 -15
  93. data/app/models/alembic/flow/edge.rb +0 -9
  94. data/app/models/alembic/flow/edit_history.rb +0 -75
  95. data/app/models/alembic/flow/layout.rb +0 -88
  96. data/app/models/alembic/flow/name.rb +0 -15
  97. data/app/models/alembic/flow/node.rb +0 -5
  98. data/app/models/alembic/flow/output.rb +0 -23
  99. data/app/models/alembic/flow/progress/kept.rb +0 -38
  100. data/app/models/alembic/flow/progress/loose.rb +0 -43
  101. data/app/models/alembic/flow/progress.rb +0 -11
  102. data/app/models/alembic/flow/registry.rb +0 -25
  103. data/app/models/alembic/flow/run.rb +0 -54
  104. data/app/models/alembic/flow/runner.rb +0 -65
  105. data/app/models/alembic/flow/settings.rb +0 -80
  106. data/app/models/alembic/flow/start.rb +0 -13
  107. data/app/models/alembic/flow/step.rb +0 -42
  108. data/app/models/alembic/flow/step_type/declaration.rb +0 -118
  109. data/app/models/alembic/flow/step_type.rb +0 -69
  110. data/app/models/alembic/flow/switch.rb +0 -17
  111. data/app/models/alembic/flow/terminal.rb +0 -13
  112. data/app/models/alembic/flow/validator.rb +0 -171
  113. data/app/models/alembic/flow/version.rb +0 -26
  114. data/app/models/alembic/flow/violation.rb +0 -9
  115. data/app/models/alembic/flow.rb +0 -44
  116. data/app/models/alembic/runner.rb +0 -13
  117. data/app/models/alembic/steps/question.rb +0 -52
  118. data/app/views/alembic/flow/steps/_choosing.html.erb +0 -9
  119. data/app/views/alembic/flows/step.html.erb +0 -27
  120. data/app/views/alembic/manage/definitions/edit.html.erb +0 -13
  121. data/app/views/alembic/manage/flows/index.html.erb +0 -32
  122. data/app/views/alembic/manage/flows/show.html.erb +0 -26
  123. data/app/views/alembic/manage/versions/index.html.erb +0 -41
data/lib/alembic.rb CHANGED
@@ -3,14 +3,40 @@ require "alembic/version"
3
3
  require "alembic/engine"
4
4
 
5
5
  module Alembic
6
- class NotPublished < StandardError; end
7
- class NotPermitted < StandardError; end
8
- class OutOfService < StandardError; end
9
- class Withdrawn < StandardError; end
6
+ NotPublished = EasyFlow::NotPublished
7
+ NotPermitted = EasyFlow::NotPermitted
8
+ OutOfService = EasyFlow::OutOfService
9
+ Withdrawn = EasyFlow::Withdrawn
10
+
11
+ FLOW_HOST = :alembic
12
+ FLOW_HOST_SETTINGS = %i[layout admin_layout admin_authentication_method
13
+ visitor_authorization_method refusal_method].freeze
10
14
 
11
15
  class << self
12
- attr_writer :layout, :base_controller, :admin_layout
13
- attr_accessor :lead_partial, :admin_authentication_method, :visitor_authorization_method, :refusal_method
16
+ attr_accessor :lead_address, :lead_fields_partial, :lead_note
17
+ attr_reader :admin_authentication_method, :visitor_authorization_method, :refusal_method
18
+
19
+ FLOW_HOST_SETTINGS.each do |name|
20
+ define_method(:"#{name}=") do |value|
21
+ instance_variable_set(:"@#{name}", value)
22
+ set_up_flow_host
23
+ end
24
+ end
25
+
26
+ def set_up_flow_host
27
+ EasyFlow.host(FLOW_HOST) do |host|
28
+ FLOW_HOST_SETTINGS.each { |name| host.public_send(:"#{name}=", public_send(name)) }
29
+ end
30
+ end
31
+
32
+ def lead_partial=(_partial)
33
+ warn "Alembic.lead_partial no longer exists and draws nothing. Set Alembic.lead_address to where the lead block posts."
34
+ end
35
+
36
+ def base_controller=(value)
37
+ @base_controller = value
38
+ EasyFlow.base_controller = value
39
+ end
14
40
 
15
41
  # The host app sets this to render the engine inside its own layout
16
42
  # (e.g. "marketing"). Defaults to the engine's own layout.
@@ -31,4 +57,6 @@ module Alembic
31
57
  @admin_layout || "application"
32
58
  end
33
59
  end
60
+
61
+ set_up_flow_host
34
62
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alembic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tylercschneider
@@ -43,14 +43,34 @@ dependencies:
43
43
  requirements:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 0.2.0
46
+ version: 0.7.0
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: 0.2.0
53
+ version: 0.7.0
54
+ - !ruby/object:Gem::Dependency
55
+ name: easy_flow
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.4'
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 0.4.1
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '0.4'
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 0.4.1
54
74
  description: Alembic builds and runs data-driven interactive diagnostics — scored
55
75
  assessments and branching guides — that place a visitor on an outcome and capture
56
76
  the result. A runtime engine plus a UI builder.
@@ -63,85 +83,31 @@ files:
63
83
  - MIT-LICENSE
64
84
  - README.md
65
85
  - Rakefile
66
- - app/assets/builds/alembic/canvas.js
67
86
  - app/assets/builds/alembic/page_builder.css
68
87
  - app/assets/builds/alembic/page_builder.js
69
88
  - app/assets/stylesheets/alembic/application.css
70
89
  - app/controllers/alembic/application_controller.rb
71
90
  - app/controllers/alembic/flows_controller.rb
72
91
  - app/controllers/alembic/manage/base_controller.rb
73
- - app/controllers/alembic/manage/canvas_controller.rb
74
- - app/controllers/alembic/manage/definitions_controller.rb
75
92
  - app/controllers/alembic/manage/flows_controller.rb
76
93
  - app/controllers/alembic/manage/page_blocks_controller.rb
77
94
  - app/controllers/alembic/manage/pages_controller.rb
78
95
  - app/controllers/alembic/manage/previews_controller.rb
79
- - app/controllers/alembic/manage/versions_controller.rb
96
+ - app/controllers/alembic/pages_controller.rb
80
97
  - app/controllers/concerns/alembic/manage/authenticates_admin.rb
81
- - app/controllers/concerns/alembic/manage/draws_canvas.rb
98
+ - app/controllers/concerns/alembic/summarizes.rb
82
99
  - app/helpers/alembic/application_helper.rb
83
- - app/javascript/alembic/canvas.jsx
84
- - app/javascript/alembic/canvas/Canvas.jsx
85
- - app/javascript/alembic/canvas/Connector.jsx
86
- - app/javascript/alembic/canvas/ConnectorLayer.jsx
87
- - app/javascript/alembic/canvas/Control.jsx
88
- - app/javascript/alembic/canvas/Inspector.jsx
89
- - app/javascript/alembic/canvas/Panel.jsx
90
- - app/javascript/alembic/canvas/Placeholder.jsx
91
- - app/javascript/alembic/canvas/Port.jsx
92
- - app/javascript/alembic/canvas/Records.jsx
93
- - app/javascript/alembic/canvas/StepCard.jsx
94
- - app/javascript/alembic/canvas/Toolbar.jsx
95
- - app/javascript/alembic/canvas/TypePicker.jsx
96
- - app/javascript/alembic/canvas/changes.js
97
- - app/javascript/alembic/canvas/choices.js
98
- - app/javascript/alembic/canvas/flow.js
99
- - app/javascript/alembic/canvas/flowSender.js
100
- - app/javascript/alembic/canvas/ids.js
101
- - app/javascript/alembic/canvas/rows.js
102
- - app/javascript/alembic/canvas/styles.js
103
- - app/javascript/alembic/canvas/useConnectors.js
104
- - app/javascript/alembic/canvas/useFlow.js
100
+ - app/helpers/alembic/pages_helper.rb
101
+ - app/helpers/alembic/result_blocks_helper.rb
105
102
  - app/javascript/alembic/page_builder.jsx
106
103
  - app/javascript/alembic/page_builder/PageBuilder.jsx
107
104
  - app/jobs/alembic/application_job.rb
108
105
  - app/mailers/alembic/application_mailer.rb
109
106
  - app/models/alembic/application_record.rb
110
- - app/models/alembic/asked.rb
111
- - app/models/alembic/choice.rb
112
- - app/models/alembic/flow.rb
113
- - app/models/alembic/flow/admission.rb
114
- - app/models/alembic/flow/canvas.rb
115
- - app/models/alembic/flow/change.rb
116
- - app/models/alembic/flow/condition.rb
117
- - app/models/alembic/flow/definition.rb
118
- - app/models/alembic/flow/digest.rb
119
- - app/models/alembic/flow/document.rb
120
- - app/models/alembic/flow/drawing.rb
121
- - app/models/alembic/flow/edge.rb
122
- - app/models/alembic/flow/edit_history.rb
123
- - app/models/alembic/flow/layout.rb
124
- - app/models/alembic/flow/name.rb
125
- - app/models/alembic/flow/node.rb
126
- - app/models/alembic/flow/output.rb
127
- - app/models/alembic/flow/progress.rb
128
- - app/models/alembic/flow/progress/kept.rb
129
- - app/models/alembic/flow/progress/loose.rb
130
- - app/models/alembic/flow/registry.rb
131
- - app/models/alembic/flow/run.rb
132
- - app/models/alembic/flow/runner.rb
133
- - app/models/alembic/flow/settings.rb
134
- - app/models/alembic/flow/start.rb
135
- - app/models/alembic/flow/step.rb
136
- - app/models/alembic/flow/step_type.rb
137
- - app/models/alembic/flow/step_type/declaration.rb
107
+ - app/models/alembic/flow/definition_summary.rb
108
+ - app/models/alembic/flow/run_summary.rb
138
109
  - app/models/alembic/flow/summaries.rb
139
110
  - app/models/alembic/flow/summary_version.rb
140
- - app/models/alembic/flow/switch.rb
141
- - app/models/alembic/flow/terminal.rb
142
- - app/models/alembic/flow/validator.rb
143
- - app/models/alembic/flow/version.rb
144
- - app/models/alembic/flow/violation.rb
145
111
  - app/models/alembic/outputs/band.rb
146
112
  - app/models/alembic/outputs/grouped.rb
147
113
  - app/models/alembic/outputs/lowest.rb
@@ -149,26 +115,30 @@ files:
149
115
  - app/models/alembic/outputs/tally.rb
150
116
  - app/models/alembic/outputs/weighted_sum.rb
151
117
  - app/models/alembic/page.rb
152
- - app/models/alembic/runner.rb
153
- - app/models/alembic/steps/question.rb
118
+ - app/models/alembic/page/drawing.rb
119
+ - app/models/alembic/page/options.rb
120
+ - app/models/alembic/page/version.rb
121
+ - app/models/alembic/result_blocks.rb
154
122
  - app/models/alembic/summary.rb
155
123
  - app/models/alembic/summary/output_type.rb
156
124
  - app/models/alembic/summary/registry.rb
157
125
  - app/models/alembic/summary/report.rb
158
126
  - app/models/alembic/summary/result.rb
159
127
  - app/models/alembic/summary/run.rb
160
- - app/views/alembic/flow/steps/_choosing.html.erb
128
+ - app/views/alembic/blocks/_answers.html.erb
129
+ - app/views/alembic/blocks/_band.html.erb
130
+ - app/views/alembic/blocks/_categories.html.erb
131
+ - app/views/alembic/blocks/_lead.html.erb
132
+ - app/views/alembic/blocks/_score.html.erb
133
+ - app/views/alembic/blocks/_weakest.html.erb
161
134
  - app/views/alembic/flows/complete.html.erb
162
135
  - app/views/alembic/flows/show.html.erb
163
- - app/views/alembic/flows/step.html.erb
164
- - app/views/alembic/manage/definitions/edit.html.erb
136
+ - app/views/alembic/flows/summary_page.html.erb
165
137
  - app/views/alembic/manage/flows/edit.html.erb
166
- - app/views/alembic/manage/flows/index.html.erb
167
- - app/views/alembic/manage/flows/show.html.erb
168
138
  - app/views/alembic/manage/pages/_block_content.html.erb
169
139
  - app/views/alembic/manage/pages/index.html.erb
170
140
  - app/views/alembic/manage/pages/show.html.erb
171
- - app/views/alembic/manage/versions/index.html.erb
141
+ - app/views/alembic/pages/show.html.erb
172
142
  - app/views/layouts/alembic/application.html.erb
173
143
  - config/routes.rb
174
144
  - db/migrate/20260604215031_create_alembic_diagnostics.rb
@@ -221,6 +191,10 @@ files:
221
191
  - db/migrate/20260831000000_add_persists_to_alembic_flows.rb
222
192
  - db/migrate/20260914120000_create_alembic_pages.rb
223
193
  - db/migrate/20260915120000_add_blocks_to_alembic_pages.rb
194
+ - db/migrate/20260922120000_add_slug_to_alembic_pages.rb
195
+ - db/migrate/20260922130000_create_alembic_page_versions.rb
196
+ - db/migrate/20260924220000_move_flows_onto_easy_flow.rb
197
+ - db/migrate/20260930120000_add_summary_page_to_alembic_flow_definition_summaries.rb
224
198
  - lib/alembic.rb
225
199
  - lib/alembic/engine.rb
226
200
  - lib/alembic/leftover_stylesheet.rb
@@ -1 +0,0 @@
1
- (()=>{var Dt=globalThis.ReactDOM;var{createPortal:ze,createRoot:K,flushSync:Be,hydrateRoot:Ee,preconnect:Te,prefetchDNS:$e,preinit:Ae,preinitModule:De,preload:Pe,preloadModule:Le,requestFormReset:Ie,unstable_batchedUpdates:Me,useFormState:_e,useFormStatus:Oe,version:He}=Dt;var Z=globalThis.React,e=Z,{Children:Fe,Component:Ve,Fragment:We,PureComponent:Ye,StrictMode:Ue,Suspense:Xe,cloneElement:Ge,createContext:qe,createElement:Je,createRef:Ke,forwardRef:Ze,isValidElement:Qe,lazy:Re,memo:to,startTransition:eo,useCallback:oo,useContext:ro,useDebugValue:no,useDeferredValue:so,useEffect:E,useId:ao,useImperativeHandle:lo,useLayoutEffect:Q,useMemo:P,useReducer:io,useRef:j,useState:b,useSyncExternalStore:co,useTransition:mo}=Z;var R=new Map,L=new Map,tt=(t,o)=>R.set(t,o),et=()=>{L.forEach(t=>t.unmount()),L.clear()},ot=(t,o)=>t.querySelectorAll("[data-react-ui]").forEach(s=>{if(L.has(s))return;let r=R.get(s.dataset.reactUi),a=o(s);L.set(s,a),a.render(e.createElement(r,JSON.parse(s.dataset.props)))});var rt=(t,o)=>{let s=()=>ot(t,o);t.addEventListener("turbo:load",s),t.addEventListener("turbo:frame-load",s),t.addEventListener("turbo:before-cache",et),t.readyState==="loading"?t.addEventListener("DOMContentLoaded",s):s()};var Pt="border border-amber-500 bg-white text-amber-700 dark:bg-zinc-900 dark:text-amber-400",Lt="border border-gray-300 bg-white text-gray-500 dark:border-zinc-600 dark:bg-zinc-900 dark:text-gray-400",It="border border-accent-600 bg-accent-600 text-white",Mt=({name:t,connected:o,armed:s,onArm:r,connecting:a})=>e.createElement("button",{onClick:l=>{a||(l.stopPropagation(),r(l))},title:s?"Now choose a step to connect to":"Connect this branch",className:s?It:o?Lt:Pt,style:{padding:"1px 8px",marginRight:4,borderRadius:999,fontSize:11,cursor:"pointer"}},t||"next"),nt=Mt;var _t={width:240,boxSizing:"border-box",borderRadius:8},Ot={padding:"8px 14px",textAlign:"center",fontWeight:600},Ht={fontWeight:600,lineHeight:1.3},jt=(t,o,s)=>{let r=s?"ring-4 ring-accent-600/15":"shadow-sm";return t||s&&!o?`border-accent-600 ${r}`:o?`border-red-600 ${r}`:"border-gray-300 shadow-sm dark:border-zinc-700"},Ft=({node:t,selected:o,armed:s,connecting:r,onSelect:a,onArm:l,onDragEnd:i,onDragStart:f})=>{let m=t.begins_here||t.ends_here,d=t.begins_here,p=t.ends_here?[]:t.ports,u=r&&!d;return e.createElement("div",{ref:t.ref,"data-step":t.id,draggable:!d,onDragStart:c=>{c.dataTransfer.effectAllowed="move",c.dataTransfer.setData("text/plain",t.id),f()},onDragEnd:i,onClick:a,className:`bg-white border-2 dark:bg-zinc-900 ${jt(u,t.violations.length>0,o)}`,style:{..._t,padding:m?0:"12px 14px",cursor:d?"default":r?"crosshair":"grab"}},m&&e.createElement("div",{className:"text-gray-500 dark:text-gray-400",style:Ot},t.label),!m&&e.createElement("div",{style:Ht},t.label),!m&&e.createElement("div",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:11,marginTop:2}},t.type),t.violations.map(c=>e.createElement("div",{key:c.problem+c.detail,className:"text-red-600 dark:text-red-400",style:{fontSize:11,padding:"0 14px 6px"}},c.problem.replace(/_/g," "),c.detail?`: ${c.detail}`:"")),p.length>0&&e.createElement("div",{style:{padding:t.begins_here?"0 14px 8px":"10px 0 0"}},p.map(c=>e.createElement(nt,{key:c,name:c,connected:t.connected.includes(c),connecting:r,armed:s===c,onArm:x=>l(c,x)}))))},F=Ft;var st=(t,o)=>t.includes(o)?t.filter(s=>s!==o):[...t,o],at=(t,o)=>({...o?.choices||{},...t?.choices||{}});var k=(...t)=>t.filter(Boolean).join(" ");var Vt=({as:t="input",disabled:o,className:s,...r})=>e.createElement(t,{...r,disabled:o,className:k("ks-input",o&&"ks-input-disabled",s)}),w=Vt;var Wt=t=>e.createElement(w,{...t,as:"select"}),lt=Wt;var Yt=({className:t,...o})=>e.createElement("input",{type:"checkbox",...o,className:k("ks-checkbox",t)}),V=Yt;var Ut=t=>(t||[]).map(o=>typeof o=="object"?o:{value:o,label:o}),Xt=({type:t,value:o,choices:s,onChange:r,onSettle:a})=>{if(t==="boolean")return e.createElement(V,{checked:!!o,onChange:l=>a(l.target.checked)});if(t==="select"||t==="previous_step"||t==="from_step")return e.createElement(lt,{className:"mb-3",value:o??"",onChange:l=>a(l.target.value)},e.createElement("option",{value:""}),Ut(s).map(l=>e.createElement("option",{key:l.value,value:l.value},l.label)));if(t==="multi_select"){let l=Array.isArray(o)?o:[],i=f=>a(st(l,f));return e.createElement("div",{style:{display:"flex",flexWrap:"wrap",gap:8}},(s||[]).map(f=>e.createElement("label",{key:f,style:{display:"inline-flex",alignItems:"center",gap:4}},e.createElement(V,{checked:l.includes(f),onChange:()=>i(f)}),e.createElement("span",null,f))))}return t==="integer"||t==="float"?e.createElement(w,{className:"mb-3",type:"number",step:t==="integer"?"1":"any",value:o??"",onChange:l=>r(l.target.value),onBlur:l=>a(l.target.value)}):e.createElement(w,{className:"mb-3",type:"text",value:o??"",onChange:l=>r(l.target.value),onBlur:l=>a(l.target.value)})},I=Xt;var it=(t,o,s,r)=>t.map((a,l)=>l===o?{...a,[s]:r}:a);var Gt={primary:"ks-button-primary",secondary:"ks-button-secondary",danger:"ks-button-danger"},qt={sm:"ks-button-sm",md:"ks-button-md",lg:"ks-button-lg"},Jt=({variant:t="primary",size:o="md",className:s,children:r,...a})=>{let l=a.href?"a":"button";return e.createElement(l,{...a,className:k("ks-button",Gt[t],qt[o],s)},r)},y=Jt;var Kt=({holds:t,labels:o,rows:s,onChange:r,onSettle:a})=>{let l=Array.isArray(s)?s:[],i=(f,m,d,p)=>{let u=it(l,f,m,d);p?a(u):r(u)};return e.createElement("div",{style:{marginBottom:12}},l.map((f,m)=>e.createElement("div",{key:m,className:"rounded-md border border-gray-200 dark:border-zinc-700",style:{padding:"8px 8px 2px",marginBottom:6}},Object.entries(t).map(([d,p])=>e.createElement("label",{key:d,style:{display:"block"}},e.createElement("span",{className:"text-gray-500 dark:text-gray-400",style:{display:"block",marginBottom:2,fontSize:11}},(o||{})[d]||d),e.createElement(I,{type:p,value:f[d],onChange:u=>i(m,d,u,!1),onSettle:u=>i(m,d,u,!0)}))),e.createElement(y,{variant:"secondary",size:"sm",className:"mb-1.5",onClick:()=>a(l.filter((d,p)=>p!==m))},"Remove"))),e.createElement(y,{variant:"secondary",size:"sm",className:"w-full",onClick:()=>a([...l,{}])},"Add"))},dt=Kt;var Zt=({as:t="div",className:o,children:s,...r})=>e.createElement(t,{...r,className:k("ks-panel",o)},s),$=Zt;var M=(t,o)=>({className:s,children:r,...a})=>e.createElement(t,{...a,className:k(o,s)},r),A=M("label","ks-label"),er=M("p","ks-hint"),or=M("p","ks-error"),rr=M("span","ks-required");var Qt={width:280,padding:20,overflowY:"auto"},Rt=({node:t,fields:o,holds:s,labels:r,recordLabels:a,choices:l,onSave:i,onDelete:f,onClose:m})=>{let[d,p]=b(t.config);E(()=>p(t.config),[t.id,t.config]);let u=c=>{p(c),JSON.stringify(c)!==JSON.stringify(t.config)&&i(c)};return e.createElement($,{as:"aside",style:Qt,"data-inspector":!0},e.createElement("div",{style:{display:"flex",alignItems:"start",justifyContent:"space-between",gap:8}},e.createElement("h2",{style:{fontWeight:600,marginBottom:2}},t.label),e.createElement("button",{title:"Close",onClick:m,className:"text-gray-500 dark:text-gray-400",style:{border:"none",background:"none",cursor:"pointer",fontSize:18,lineHeight:1}},"\xD7")),e.createElement("p",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:11,marginBottom:16}},t.id," \xB7 ",t.type),Object.entries(o).map(([c,x])=>e.createElement(A,{key:c},e.createElement("span",{style:{display:"block",marginBottom:3}},r[c]||c),x==="list"?e.createElement(dt,{holds:s[c]||{},labels:a[c]||{},rows:d[c],onChange:h=>p({...d,[c]:h}),onSettle:h=>u({...d,[c]:h})}):e.createElement(I,{type:x,value:d[c],choices:l[c],onChange:h=>p({...d,[c]:h}),onSettle:h=>u({...d,[c]:h})}))),e.createElement(y,{variant:"danger",size:"sm",className:"w-full",onClick:f},"Delete step"))},ct=Rt;var te={width:240,boxSizing:"border-box",padding:"10px 14px",borderRadius:8,textAlign:"center",fontSize:12,cursor:"pointer"},ee="border-2 border-dashed border-amber-500 bg-amber-50 text-amber-700 dark:bg-amber-950 dark:text-amber-300",oe="border-2 border-dashed border-accent-600 bg-accent-50 text-accent-800 dark:bg-accent-950 dark:text-accent-200",re=({node:t,dragging:o,onFill:s,onDrop:r})=>e.createElement("div",{ref:t.ref,"data-placeholder":t.id,title:`Choose the step \u201C${t.label}\u201D should lead to`,onClick:s,onDragOver:a=>{o&&(a.preventDefault(),a.dataTransfer.dropEffect="move")},onDrop:a=>{a.preventDefault(),r()},className:o?oe:ee,style:te},e.createElement("div",{style:{fontWeight:600}},t.label),e.createElement("div",{style:{fontSize:11}},o?"drop a step here":"leads nowhere yet \u2014 click to choose")),mt=re;var ne=({entries:t,at:o,onPick:s,onConnect:r,onDismiss:a})=>e.createElement($,{className:"shadow-lg",style:{position:"absolute",zIndex:9,top:o.y,left:o.x,width:210,padding:8,borderRadius:8}},e.createElement("p",{className:"text-gray-500 dark:text-gray-400",style:{margin:"0 0 6px",fontSize:11}},"Add a step"),t.map(l=>e.createElement(y,{key:l.type,variant:"secondary",size:"sm",className:"w-full mb-1.5 flex-col",onClick:()=>s(l)},l.label,e.createElement("span",{className:"opacity-75",style:{display:"block",fontSize:11}},l.type))),r&&e.createElement(y,{variant:"secondary",size:"sm",className:"w-full mb-1.5",onClick:r},"Connect to a step already here"),e.createElement(y,{variant:"secondary",size:"sm",className:"w-full",onClick:a},"Cancel")),pt=ne;var se={width:24,height:24,padding:0,fontSize:15,lineHeight:"15px"},ut=({label:t,title:o,idle:s,enabled:r,onUse:a})=>e.createElement(y,{variant:"secondary",size:"sm",title:r?o:s,disabled:!r,onClick:a,style:{opacity:r?1:.4,cursor:r?"pointer":"default"}},t),ae=({undoable:t,redoable:o,onAdd:s,onUndo:r,onRedo:a})=>e.createElement("div",{style:{position:"absolute",top:16,left:16,zIndex:5,display:"flex",gap:8}},e.createElement(y,{variant:"secondary",className:"rounded-full",style:se,title:"Add a step",onClick:s},"+"),e.createElement(ut,{label:"\u21B6 Undo",title:"Undo the last change",idle:"Nothing to undo",enabled:t,onUse:r}),e.createElement(ut,{label:"\u21B7 Redo",title:"Redo the change you undid",idle:"Nothing to redo",enabled:o,onUse:a})),ft=ae;var le=t=>e.createElement(w,{...t,as:"textarea"}),gt=le;var yt=t=>{let o=t.problem.replace(/_/g," ");return t.node?`\u201C${t.node}\u201D ${o}`:o};var ht=({version:t,published:o})=>t?o?o===t?`Version ${t} \xB7 live`:`Version ${t} \xB7 visitors still on ${o}`:`Version ${t} \xB7 never published`:"No version yet";var ie={width:280,padding:20,overflowY:"auto"},W={fontWeight:600,marginBottom:6,marginTop:14},_={fontSize:12,marginBottom:4,lineHeight:1.4},Y={display:"block",marginBottom:3},U=(t,o,s)=>r=>{r.target.value!==(t[o]??"")&&s({[o]:r.target.value})},de=({flow:t,changes:o,problems:s,refusal:r,notice:a,onCreate:l,onPublish:i,onSaveDetails:f,onClose:m})=>e.createElement($,{as:"aside",style:ie,"data-builder-panel":!0},e.createElement("div",{style:{display:"flex",alignItems:"start",justifyContent:"space-between",gap:8}},e.createElement("h2",{style:{fontWeight:600},"data-flow-name":!0},t.title||t.slug),e.createElement("button",{title:"Close",onClick:m,className:"text-gray-500 dark:text-gray-400",style:{border:"none",background:"none",cursor:"pointer",fontSize:18,lineHeight:1}},"\xD7")),e.createElement("a",{className:"text-accent-600 dark:text-accent-400",style:{fontSize:12,display:"block"},href:t.history_url,"data-history":!0},ht(t)),e.createElement("h2",{style:W},"Problems"),r&&e.createElement("p",{className:"text-red-800 dark:text-red-400",style:{..._,fontWeight:600},"data-refusal":!0},r),a&&!r&&e.createElement("p",{className:"text-emerald-800 dark:text-emerald-400",style:{..._,fontWeight:600},"data-notice":!0},a),s.length===0&&!r?e.createElement("p",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:12}},"Nothing wrong with this flow."):s.map(d=>e.createElement("p",{key:`${d.node}-${d.problem}`,className:"text-amber-700 dark:text-amber-400",style:_,"data-problem":!0},"\u26A0 ",yt(d))),e.createElement("h2",{style:W},"Changes since the last version"),o.length===0?e.createElement("p",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:12}},"Nothing has changed."):o.map((d,p)=>e.createElement("p",{key:p,style:_,"data-change":!0},d)),e.createElement("h2",{style:W},"Details"),e.createElement(A,null,e.createElement("span",{style:Y},"Title"),e.createElement(w,{className:"mb-3",defaultValue:t.title??"",onBlur:U(t,"title",f),"data-flow-title":!0})),e.createElement(A,null,e.createElement("span",{style:Y},"Summary"),e.createElement(gt,{className:"mb-3",rows:4,defaultValue:t.summary??"",onBlur:U(t,"summary",f),"data-flow-summary":!0})),e.createElement(A,null,e.createElement("span",{style:Y},"Start label"),e.createElement(w,{className:"mb-3",defaultValue:t.start_label??"",onBlur:U(t,"start_label",f),"data-flow-start-label":!0})),e.createElement("div",{style:{marginTop:16}},e.createElement(y,{variant:"secondary",size:"sm",className:"w-full mb-1.5",onClick:l,"data-create-version":!0},"Create version"),e.createElement(y,{size:"sm",className:"w-full mb-1.5",onClick:i,"data-publish":!0},"Publish"),e.createElement(y,{variant:"secondary",size:"sm",className:"w-full mb-1.5",href:t.definition_url,"data-definition":!0},"Definition"),e.createElement(y,{variant:"secondary",size:"sm",className:"w-full mb-1.5",href:t.details_url,"data-details":!0},"Edit details"))),bt=de;var xt={width:24,height:24,padding:0,fontSize:15,lineHeight:"15px"},ce=({link:t,onInsert:o,onRemove:s,onDrop:r,dragging:a})=>{let[l,i]=b(!1),f=l||a;return e.createElement("div",{"data-connector":`${t.source}-${t.target}`,style:{position:"absolute",left:t.midX-34,top:t.midY-20,width:68,height:40,zIndex:4},onMouseEnter:()=>i(!0),onMouseLeave:()=>i(!1),onDragEnter:()=>i(!0),onDragLeave:()=>i(!1),onDragOver:m=>{m.preventDefault(),m.dataTransfer.dropEffect="move"},onDrop:m=>{m.preventDefault(),i(!1),r()}},e.createElement("div",{style:{display:"flex",gap:4,justifyContent:"center",alignItems:"center",height:"100%",opacity:f?1:0,transition:"opacity .12s"}},e.createElement(y,{variant:"secondary",title:a?"Move the step here":"Insert a step here",onClick:o,className:"rounded-full data-[over=true]:ring-2 data-[over=true]:ring-accent-600","data-over":!!(a&&l),style:xt},"+"),!a&&e.createElement(y,{variant:"danger",title:"Remove this connection",onClick:s,className:"rounded-full",style:xt},"\xD7")))},vt=ce;var me=({links:t,extent:o,dragging:s,onInsert:r,onRemove:a,onDrop:l})=>e.createElement(e.Fragment,null,e.createElement("svg",{width:o.width,height:o.height,style:{position:"absolute",top:0,left:0,pointerEvents:"none",zIndex:1}},e.createElement("defs",null,e.createElement("marker",{id:"alembic-arrow",viewBox:"0 0 10 10",refX:"8",refY:"5",markerWidth:"5",markerHeight:"5",orient:"auto"},e.createElement("path",{d:"M 0 0 L 10 5 L 0 10 z",className:"fill-gray-400 dark:fill-zinc-500"}))),t.map(i=>e.createElement("path",{key:i.id,"data-link":i.id,className:"stroke-gray-400 dark:stroke-zinc-500",fill:"none",strokeWidth:"1.5",markerEnd:"url(#alembic-arrow)",d:i.path}))),t.filter(i=>i.label).map(i=>e.createElement("div",{key:`${i.id}-label`,"data-link-label":i.id,className:"bg-surface-50 text-gray-500 dark:bg-surface-950 dark:text-gray-400",style:{position:"absolute",left:i.midX-10,top:i.midY-18,zIndex:3,fontSize:11,padding:"0 3px"}},i.label)),t.filter(i=>!i.placeholder).map(i=>e.createElement(vt,{key:i.id,link:i,dragging:!!s,onInsert:()=>r(i),onRemove:()=>a(i),onDrop:()=>l(i)}))),kt=me;var pe="Your change was not saved because the server could not be reached.",wt=({base:t,token:o,fetch:s,onFlow:r,onError:a,onNotice:l})=>async(i,f,m)=>{let d=await s(t+i,{method:f,headers:{"Content-Type":"application/json","X-CSRF-Token":o},body:m&&JSON.stringify(m)}).catch(()=>null);if(!d)return l(null),a(pe);let p=await d.json().catch(()=>({}));if(!d.ok)return l(null),a(p.error||"That change was refused");a(null),l(p.notice||null),r(await(await s(t+".json",{headers:{Accept:"application/json"}})).json())};var ue=(t,o,s)=>{let[r,a]=b(s),[l,i]=b(null),[f,m]=b(null),d=P(()=>wt({base:t,token:o,fetch:(...p)=>window.fetch(...p),onFlow:a,onError:i,onNotice:m}),[t,o]);return{flow:r,error:l,notice:f,send:d}},Ct=ue;var O=(t,o,s,r)=>{let a=t.left-s.left+r.scrollLeft,l=t.top-s.top+r.scrollTop;return o==="left"?{x:a,y:l+t.height/2}:o==="right"?{x:a+t.width,y:l+t.height/2}:o==="top"?{x:a+t.width/2,y:l}:{x:a+t.width/2,y:l+t.height}},fe=(t,o)=>o==="top"?{x:t.x,y:t.y-3}:o==="left"?{x:t.x-3,y:t.y}:o==="right"?{x:t.x+3,y:t.y}:{x:t.x,y:t.y+3},ge=(t,o,s,r,a)=>{let l={straight:`M ${o.x} ${o.y} L ${s.x} ${s.y}`,turn:`M ${o.x} ${o.y} H ${s.x} V ${s.y}`,lane:`M ${o.x} ${o.y} V ${r} H ${s.x} V ${s.y}`,detour:`M ${o.x} ${o.y} H ${a} V ${s.y} H ${s.x}`}[t.route];return{...t,path:l,midX:t.route==="detour"?a:(o.x+s.x)/2,midY:t.route==="lane"?r:(o.y+s.y)/2}},ye=(t,o,s,r)=>{let[a,l]=b([]),[i,f]=b({width:"100%",height:"100%"});return Q(()=>{let m=()=>{let p=o.current?.getBoundingClientRect();p&&(f({width:o.current.scrollWidth,height:o.current.scrollHeight}),l(t.edges.flatMap(u=>{let c=s.current[u.source]?.getBoundingClientRect(),x=s.current[u.target]?.getBoundingClientRect();if(!c||!x)return[];let h=O(c,u.leaves,p,o.current),C=fe(O(x,u.enters,p,o.current),u.enters),N=(O(c,"bottom",p,o.current).y+O(x,"top",p,o.current).y)/2,z=u.leaves==="left"?Math.min(h.x,C.x)-28:Math.max(h.x,C.x)+28;return[ge(u,h,C,N,z)]})))};m(),window.addEventListener("resize",m);let d=new ResizeObserver(m);return o.current&&d.observe(o.current),()=>{window.removeEventListener("resize",m),d.disconnect()}},r),{links:a,extent:i}},St=ye;var Nt=(t,o)=>{let s=new Set(o),r=t,a=2;for(;s.has(r);)r=`${t}_${a++}`;return r};var xe={display:"flex",height:"100%",minHeight:0,fontSize:13},ve={flex:1,overflow:"auto",position:"relative"},ke={position:"absolute",top:56,left:16,zIndex:5,width:264,padding:12,borderRadius:8},we={display:"grid",rowGap:64,columnGap:0,padding:40,justifyContent:"center",position:"relative"},Ce={position:"sticky",zIndex:8,top:8,margin:"8px auto 0",width:"fit-content",padding:"6px 12px",borderRadius:6,fontSize:12},Se=({port:t,onCancel:o})=>e.createElement("div",{className:"bg-accent-100 text-accent-800 dark:bg-accent-900 dark:text-accent-100",style:Ce},"Choose the step \u201C",t||"next","\u201D should lead to \u2014 ",e.createElement("button",{onClick:o,className:"text-accent-800 underline dark:text-accent-100",style:{border:"none",background:"none",cursor:"pointer",fontSize:12,padding:0}},"cancel")),Ne=({base:t,token:o,initial:s})=>{let{flow:r,error:a,notice:l,send:i}=Ct(t,o,s),[f,m]=b(null),[d,p]=b(null),[u,c]=b(null),[x,h]=b(null),[C,N]=b(!1),z=j({}),B=j(null);E(()=>{let n=()=>{m(null),N(!0)};return document.addEventListener("alembic:open-flow",n),()=>document.removeEventListener("alembic:open-flow",n)},[]),E(()=>{if(!C)return;let n=g=>{g.target.closest("[data-builder-panel], [data-open-panel]")||N(!1)};return document.addEventListener("click",n),()=>document.removeEventListener("click",n)},[C]),E(()=>{document.dispatchEvent(new CustomEvent("alembic:flow-named",{detail:r.flow?.title||r.flow?.slug}))},[r.flow?.title,r.flow?.slug]);let Bt=P(()=>Object.fromEntries(r.nodes.map(n=>[n.id,n])),[r.nodes]),{links:Et,extent:Tt}=St(r,B,z,[r,f,Bt]),X=P(()=>{let n={};return r.violations.forEach(g=>{var v;return(n[v=g.node]||(n[v]=[])).push(g)}),n},[r.violations]),H=r.nodes.filter(n=>!n.loose),G=r.nodes.filter(n=>n.loose),$t=Math.max(0,...H.map(n=>n.row))+1,At=Math.max(0,...H.map(n=>n.column))+1,q=n=>{if(!u)return;let[g,v]=u;c(null),g!==n&&i("/edges","POST",{from:g,to:n,on:v||null})},S=r.nodes.find(n=>n.id===f),D=r.palette.find(n=>n.type===S?.type);return e.createElement("div",{className:"text-gray-900 dark:text-gray-100",style:xe,onMouseUp:()=>h(null),onKeyDown:n=>{n.key==="Escape"&&(m(null),c(null),p(null))},tabIndex:-1},e.createElement("div",{ref:B,className:"bg-surface-50 dark:bg-surface-950",style:ve,onClick:n=>{n.target===B.current&&(m(null),c(null),N(!1))}},u&&e.createElement(Se,{port:u[1],onCancel:()=>c(null)}),e.createElement(ft,{undoable:r.undoable,redoable:r.redoable,onAdd:()=>p({at:{x:16,y:52}}),onUndo:()=>{m(null),i("/undo","POST")},onRedo:()=>{m(null),i("/redo","POST")}}),e.createElement(kt,{links:Et,extent:Tt,dragging:x,onInsert:n=>p({from:n.source,to:n.target,at:{x:n.midX+30,y:n.midY}}),onRemove:n=>{m(null),i("/edges","DELETE",{from:n.source,to:n.target})},onDrop:n=>{let g=x;h(null),i("/steps/"+g+"/move","PATCH",{from:n.source,to:n.target})}}),G.length>0&&e.createElement("div",{"data-loose":!0,className:"border border-dashed border-gray-300 bg-gray-50 dark:border-zinc-700 dark:bg-zinc-900",style:ke},e.createElement("div",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:11,marginBottom:6}},"Not in the flow yet \u2014 drag one onto a connection"),G.map(n=>e.createElement("div",{key:n.id,style:{marginBottom:8}},e.createElement(F,{node:{...n,ref:g=>{z.current[n.id]=g},violations:X[n.id]||[],connected:[]},selected:f===n.id,armed:u&&u[0]===n.id?u[1]:null,connecting:!!u,onSelect:()=>u?q(n.id):m(n.id),onArm:(g,v)=>{v.stopPropagation(),c([n.id,g])},onDragStart:()=>h(n.id),onDragEnd:()=>h(null)})))),e.createElement("div",{style:{...we,gridTemplateColumns:`repeat(${At+1}, ${280/2}px)`,gridTemplateRows:`repeat(${$t}, auto)`}},H.map(n=>e.createElement("div",{key:n.id,style:{gridRow:n.row+1,gridColumn:`${n.column+1} / span 2`,zIndex:2}},n.placeholder&&e.createElement(mt,{node:{...n,ref:g=>{z.current[n.id]=g}},dragging:!!x,onFill:()=>p({from:n.from,on:n.on,at:{x:16,y:52}}),onDrop:()=>{let g=x;h(null),g&&i("/edges","POST",{from:n.from,to:g,on:n.on})}}),!n.placeholder&&e.createElement(F,{node:{...n,ref:g=>{z.current[n.id]=g},violations:X[n.id]||[],connected:r.edges.filter(g=>g.source===n.id).map(g=>g.label||null)},selected:n.id===f,armed:u&&u[0]===n.id?u[1]:null,connecting:!!u&&u[0]!==n.id,onSelect:()=>u?q(n.id):m(n.id),onArm:(g,v)=>{let J=B.current.getBoundingClientRect();p({from:n.id,on:g,at:{x:v.clientX-J.left+B.current.scrollLeft+8,y:v.clientY-J.top+B.current.scrollTop+8}})},onDragEnd:()=>h(null),onDragStart:()=>h(n.id)})))),d&&e.createElement(pt,{entries:r.palette,at:d.at,onDismiss:()=>p(null),onConnect:d.on!==void 0?()=>{c([d.from,d.on]),p(null)}:null,onPick:n=>{let g=d;p(null),i("/steps","POST",{id:Nt(n.type,r.nodes.map(v=>v.id)),type:n.type,from:g.from,to:g.to,on:g.on})}})),C&&!S&&e.createElement(bt,{flow:r.flow||{},changes:r.changes||[],problems:r.violations,refusal:a,notice:l,onClose:()=>N(!1),onCreate:()=>i("/versions","POST"),onPublish:()=>i("/publish","POST"),onSaveDetails:n=>i("/details","PATCH",{flow:n})}),S&&e.createElement(ct,{node:S,fields:D?.fields||{},holds:D?.records||{},labels:D?.labels||{},recordLabels:D?.record_labels||{},choices:at(S,D),onClose:()=>m(null),onSave:n=>i(`/steps/${S.id}`,"PATCH",{config:n}),onDelete:()=>{m(null),i(`/steps/${S.id}`,"DELETE")}}))},zt=Ne;tt("alembic/flow-editor",zt);document.addEventListener("alembic:flow-named",t=>{let o=document.querySelector("[data-flow-heading]");o&&(o.textContent=t.detail)});rt(document,K);})();
@@ -1,183 +0,0 @@
1
- module Alembic
2
- module Manage
3
- class CanvasController < BaseController
4
- include DrawsCanvas
5
- def show
6
- render json: canvas_payload(diagnostic)
7
- end
8
-
9
- def create
10
- objections = Flow::Validator.new(document).violations
11
- return render json: { error: refusal(objections) }, status: :unprocessable_entity if objections.any?
12
-
13
- stood_at = diagnostic.current_definition_version&.number
14
- diagnostic.create_version
15
-
16
- render json: { notice: created(stood_at) }
17
- end
18
-
19
- def publish
20
- objections = Flow::Validator.new(document).violations
21
- return render json: { error: refusal(objections) }, status: :unprocessable_entity if objections.any?
22
-
23
- ran = diagnostic.live_version&.number
24
- diagnostic.publish
25
-
26
- render json: { notice: published(ran) }
27
- end
28
-
29
- def details
30
- diagnostic.update!(details_params)
31
- render json: { notice: "Saved the flow's details." }
32
- end
33
-
34
- def undo
35
- diagnostic.edit_history.undo_change
36
- head :no_content
37
- end
38
-
39
- def redo
40
- diagnostic.edit_history.redo_change
41
- head :no_content
42
- end
43
-
44
- def add_step
45
- apply(:added, params[:id]) do |flow|
46
- next flow.insert(new_step, on: edge_endpoints, leaving: first_port) if placed_on_edge?
47
- next flow.add(new_step).connect(from: params[:from], to: params[:id], on: params[:on].presence) if branched_from?
48
-
49
- flow.add(new_step)
50
- end
51
- end
52
-
53
- def configure_step
54
- apply(:updated, params[:step]) { |flow| flow.configure(params[:step], coerced(flow, params[:step])) }
55
- end
56
-
57
- def move_step
58
- apply(:moved, params[:step]) { |flow| flow.move(params[:step], on: edge_endpoints, leaving: port_for(params[:step])) }
59
- end
60
-
61
- def remove_step
62
- return render json: { error: refusal_to_remove }, status: :unprocessable_entity if begins_the_flow?(params[:step])
63
-
64
- apply(:removed, params[:step]) { |flow| flow.remove(params[:step]) }
65
- end
66
-
67
- def connect
68
- apply(:connected, params[:from], params[:to]) { |flow| flow.connect(from: params[:from], to: params[:to], on: params[:on].presence) }
69
- end
70
-
71
- def disconnect
72
- apply(:disconnected, params[:from], params[:to]) { |flow| flow.disconnect(from: params[:from], to: params[:to]) }
73
- end
74
-
75
- private
76
-
77
- def apply(action = nil, *steps)
78
- before = document.to_h
79
- diagnostic.edit_history.record(yield(document), action, steps, before)
80
- head :no_content
81
- rescue Flow::InvalidEdit => invalid
82
- render json: { error: invalid.message }, status: :unprocessable_entity
83
- end
84
-
85
- def diagnostic
86
- @diagnostic ||= Flow::Definition.find(params[:flow_id])
87
- end
88
-
89
- def document
90
- Flow::Document.new(diagnostic.document || diagnostic.definition || {})
91
- end
92
-
93
- def details_params
94
- params.require(:flow).permit(:title, :summary, :start_label, :persists)
95
- end
96
-
97
- def new_step
98
- { "id" => params.require(:id), "type" => params.require(:type) }
99
- end
100
-
101
- def first_port
102
- first_value_of(Flow::Node.new(id: nil, type: params[:type], config: {}))
103
- end
104
-
105
- def port_for(id)
106
- first_value_of(document.node(id))
107
- end
108
-
109
- def first_value_of(node)
110
- return unless node && Flow.registry.registered?(node.type)
111
-
112
- step_type = Flow.registry.fetch(node.type)
113
- return unless step_type.routes?
114
-
115
- step_type.outputs.flat_map { |output| output.values_for(node) }.first&.fetch("value", nil)&.to_s
116
- end
117
-
118
- def begins_the_flow?(id)
119
- node = document.node(id)
120
-
121
- node.present? && document.begins_here?(node)
122
- end
123
-
124
- def placed_on_edge?
125
- params[:from].present? && params[:to].present?
126
- end
127
-
128
- def branched_from?
129
- params[:from].present?
130
- end
131
-
132
- def edge_endpoints
133
- [ params[:from], params[:to] ]
134
- end
135
-
136
- def configuration
137
- params.fetch(:config, {}).permit!.to_h
138
- end
139
-
140
- def created(stood_at)
141
- now_at = diagnostic.reload.current_definition_version&.number
142
- return "Nothing has changed since version #{stood_at}." if now_at == stood_at
143
-
144
- "Created version #{now_at}."
145
- end
146
-
147
- def published(ran)
148
- now_at = diagnostic.reload.live_version&.number
149
- return "Visitors already run version #{now_at}." if now_at == ran
150
-
151
- "Published version #{now_at}. Visitors run it now."
152
- end
153
-
154
- def refusal_to_remove
155
- "Cannot remove where a flow begins."
156
- end
157
-
158
- def refusal(objections)
159
- "Cannot publish: #{objections.map { |problem| worded(problem) }.join(', ')}."
160
- end
161
-
162
- def worded(problem)
163
- trouble = problem.problem.to_s.humanize(capitalize: false)
164
-
165
- problem.node ? "“#{problem.node}” is #{trouble}" : trouble
166
- end
167
-
168
- def coerced(flow, id)
169
- step_type = Flow::Digest.new(flow).step(id)&.type
170
- return configuration unless step_type && Flow.registry.registered?(step_type)
171
-
172
- settled(Flow.registry.fetch(step_type))
173
- end
174
-
175
- def settled(step_type)
176
- step_type.settings.coerce(configuration).tap do |values|
177
- objections = step_type.settings.objections(values)
178
- raise Flow::InvalidEdit, objections.join(", ") if objections.any?
179
- end
180
- end
181
- end
182
- end
183
- end
@@ -1,15 +0,0 @@
1
- module Alembic
2
- module Manage
3
- class DefinitionsController < BaseController
4
- def edit
5
- @diagnostic = Flow::Definition.find(params[:flow_id])
6
- end
7
-
8
- def update
9
- @diagnostic = Flow::Definition.find(params[:flow_id])
10
- @diagnostic.edit_history.edit_document(JSON.parse(params.require(:definition)))
11
- redirect_to manage_flow_path(@diagnostic), notice: "Definition saved."
12
- end
13
- end
14
- end
15
- end
@@ -1,22 +0,0 @@
1
- module Alembic
2
- module Manage
3
- class VersionsController < BaseController
4
- def index
5
- @diagnostic = diagnostic
6
- @versions = @diagnostic.definition_versions.order(number: :desc)
7
- end
8
-
9
- def return
10
- diagnostic.return_to(diagnostic.definition_versions.find(params[:id]))
11
-
12
- redirect_to manage_flow_path(diagnostic), notice: "The flow is back to that version."
13
- end
14
-
15
- private
16
-
17
- def diagnostic
18
- @diagnostic ||= Flow::Definition.find(params[:flow_id])
19
- end
20
- end
21
- end
22
- end
@@ -1,35 +0,0 @@
1
- module Alembic
2
- module Manage
3
- module DrawsCanvas
4
- extend ActiveSupport::Concern
5
-
6
- private
7
-
8
- def canvas_payload(diagnostic)
9
- Flow::Canvas.new(canvas_document(diagnostic)).to_h
10
- .merge("undoable" => diagnostic.edit_history.undoable?, "redoable" => diagnostic.edit_history.redoable?,
11
- "changes" => listed_changes(diagnostic), "flow" => flow_details(diagnostic))
12
- end
13
-
14
- def canvas_document(diagnostic)
15
- Flow::Document.new(diagnostic.document || diagnostic.definition || {})
16
- end
17
-
18
- def listed_changes(diagnostic)
19
- diagnostic.changes_since_version.to_a.map { |change| Flow::Change.phrase(change) }
20
- end
21
-
22
- def flow_details(diagnostic)
23
- { "title" => diagnostic.title,
24
- "slug" => diagnostic.slug,
25
- "summary" => diagnostic.summary,
26
- "start_label" => diagnostic.start_label,
27
- "version" => diagnostic.current_definition_version&.number,
28
- "published" => diagnostic.live_version&.number,
29
- "definition_url" => edit_manage_flow_definition_path(diagnostic),
30
- "details_url" => edit_manage_flow_path(diagnostic),
31
- "history_url" => manage_flow_versions_path(diagnostic) }
32
- end
33
- end
34
- end
35
- end