easy_flow 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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/builds/easy_flow/canvas.js +1 -0
  3. data/app/controllers/concerns/easy_flow/manage/authenticates_admin.rb +19 -0
  4. data/app/controllers/concerns/easy_flow/manage/draws_canvas.rb +34 -0
  5. data/app/controllers/easy_flow/application_controller.rb +32 -0
  6. data/app/controllers/easy_flow/flows_controller.rb +103 -0
  7. data/app/controllers/easy_flow/manage/base_controller.rb +14 -0
  8. data/app/controllers/easy_flow/manage/canvas_controller.rb +183 -0
  9. data/app/controllers/easy_flow/manage/definitions_controller.rb +15 -0
  10. data/app/controllers/easy_flow/manage/flows_controller.rb +55 -0
  11. data/app/controllers/easy_flow/manage/previews_controller.rb +38 -0
  12. data/app/controllers/easy_flow/manage/versions_controller.rb +22 -0
  13. data/app/javascript/easy_flow/canvas/Canvas.jsx +197 -0
  14. data/app/javascript/easy_flow/canvas/Connector.jsx +30 -0
  15. data/app/javascript/easy_flow/canvas/ConnectorLayer.jsx +31 -0
  16. data/app/javascript/easy_flow/canvas/Control.jsx +42 -0
  17. data/app/javascript/easy_flow/canvas/Inspector.jsx +44 -0
  18. data/app/javascript/easy_flow/canvas/Panel.jsx +61 -0
  19. data/app/javascript/easy_flow/canvas/Placeholder.jsx +24 -0
  20. data/app/javascript/easy_flow/canvas/Port.jsx +16 -0
  21. data/app/javascript/easy_flow/canvas/Records.jsx +34 -0
  22. data/app/javascript/easy_flow/canvas/StepCard.jsx +57 -0
  23. data/app/javascript/easy_flow/canvas/Toolbar.jsx +19 -0
  24. data/app/javascript/easy_flow/canvas/TypePicker.jsx +21 -0
  25. data/app/javascript/easy_flow/canvas/changes.js +5 -0
  26. data/app/javascript/easy_flow/canvas/choices.js +4 -0
  27. data/app/javascript/easy_flow/canvas/flow.js +7 -0
  28. data/app/javascript/easy_flow/canvas/flowSender.js +22 -0
  29. data/app/javascript/easy_flow/canvas/ids.js +7 -0
  30. data/app/javascript/easy_flow/canvas/rows.js +2 -0
  31. data/app/javascript/easy_flow/canvas/styles.js +3 -0
  32. data/app/javascript/easy_flow/canvas/useConnectors.js +75 -0
  33. data/app/javascript/easy_flow/canvas/useFlow.js +17 -0
  34. data/app/javascript/easy_flow/canvas.jsx +13 -0
  35. data/app/views/easy_flow/flows/complete.html.erb +22 -0
  36. data/app/views/easy_flow/flows/show.html.erb +17 -0
  37. data/app/views/easy_flow/flows/step.html.erb +27 -0
  38. data/app/views/easy_flow/manage/definitions/edit.html.erb +13 -0
  39. data/app/views/easy_flow/manage/flows/edit.html.erb +26 -0
  40. data/app/views/easy_flow/manage/flows/index.html.erb +32 -0
  41. data/app/views/easy_flow/manage/flows/show.html.erb +26 -0
  42. data/app/views/easy_flow/manage/versions/index.html.erb +41 -0
  43. data/app/views/easy_flow/steps/_choosing.html.erb +9 -0
  44. data/app/views/layouts/easy_flow/application.html.erb +15 -0
  45. data/config/routes.rb +32 -0
  46. data/lib/easy_flow/engine.rb +11 -0
  47. data/lib/easy_flow/version.rb +1 -1
  48. data/lib/easy_flow.rb +15 -0
  49. metadata +58 -1
@@ -0,0 +1,3 @@
1
+ export const CARD = 240
2
+ export const GAP_X = 40
3
+ export const GAP_Y = 64
@@ -0,0 +1,75 @@
1
+ import { useLayoutEffect, useState } from "react"
2
+
3
+ export const anchor = (box, side, frame, surface) => {
4
+ const left = box.left - frame.left + surface.scrollLeft
5
+ const top = box.top - frame.top + surface.scrollTop
6
+
7
+ if (side === "left") return { x: left, y: top + box.height / 2 }
8
+ if (side === "right") return { x: left + box.width, y: top + box.height / 2 }
9
+ if (side === "top") return { x: left + box.width / 2, y: top }
10
+ return { x: left + box.width / 2, y: top + box.height }
11
+ }
12
+
13
+ export const shy = (point, side) => {
14
+ if (side === "top") return { x: point.x, y: point.y - 3 }
15
+ if (side === "left") return { x: point.x - 3, y: point.y }
16
+ if (side === "right") return { x: point.x + 3, y: point.y }
17
+ return { x: point.x, y: point.y + 3 }
18
+ }
19
+
20
+ export const drawn = (edge, a, b, lane, detour) => {
21
+ const path = {
22
+ straight: `M ${a.x} ${a.y} L ${b.x} ${b.y}`,
23
+ turn: `M ${a.x} ${a.y} H ${b.x} V ${b.y}`,
24
+ lane: `M ${a.x} ${a.y} V ${lane} H ${b.x} V ${b.y}`,
25
+ detour: `M ${a.x} ${a.y} H ${detour} V ${b.y} H ${b.x}`
26
+ }[edge.route]
27
+
28
+ return {
29
+ ...edge, path,
30
+ midX: edge.route === "detour" ? detour : (a.x + b.x) / 2,
31
+ midY: edge.route === "lane" ? lane : (a.y + b.y) / 2
32
+ }
33
+ }
34
+
35
+ const useConnectors = (flow, surface, cards, watching) => {
36
+ const [ links, setLinks ] = useState([])
37
+ const [ extent, setExtent ] = useState({ width: "100%", height: "100%" })
38
+
39
+ useLayoutEffect(() => {
40
+ const measure = () => {
41
+ const frame = surface.current?.getBoundingClientRect()
42
+ if (!frame) return
43
+
44
+ setExtent({ width: surface.current.scrollWidth, height: surface.current.scrollHeight })
45
+
46
+ setLinks(flow.edges.flatMap((edge) => {
47
+ const fromBox = cards.current[edge.source]?.getBoundingClientRect()
48
+ const toBox = cards.current[edge.target]?.getBoundingClientRect()
49
+ if (!fromBox || !toBox) return []
50
+
51
+ const a = anchor(fromBox, edge.leaves, frame, surface.current)
52
+ const b = shy(anchor(toBox, edge.enters, frame, surface.current), edge.enters)
53
+ const lane = (anchor(fromBox, "bottom", frame, surface.current).y + anchor(toBox, "top", frame, surface.current).y) / 2
54
+ const detour = edge.leaves === "left" ? Math.min(a.x, b.x) - 28 : Math.max(a.x, b.x) + 28
55
+
56
+ return [ drawn(edge, a, b, lane, detour) ]
57
+ }))
58
+ }
59
+
60
+ measure()
61
+ window.addEventListener("resize", measure)
62
+
63
+ const watcher = new ResizeObserver(measure)
64
+ if (surface.current) watcher.observe(surface.current)
65
+
66
+ return () => {
67
+ window.removeEventListener("resize", measure)
68
+ watcher.disconnect()
69
+ }
70
+ }, watching)
71
+
72
+ return { links, extent }
73
+ }
74
+
75
+ export default useConnectors
@@ -0,0 +1,17 @@
1
+ import { useMemo, useState } from "react"
2
+ import { createFlowSender } from "./flowSender"
3
+
4
+ const useFlow = (base, token, initial) => {
5
+ const [ flow, setFlow ] = useState(initial)
6
+ const [ error, setError ] = useState(null)
7
+ const [ notice, setNotice ] = useState(null)
8
+
9
+ const send = useMemo(
10
+ () => createFlowSender({ base, token, fetch: (...request) => window.fetch(...request), onFlow: setFlow, onError: setError, onNotice: setNotice }),
11
+ [ base, token ]
12
+ )
13
+
14
+ return { flow, error, notice, send }
15
+ }
16
+
17
+ export default useFlow
@@ -0,0 +1,13 @@
1
+ import { createRoot } from "react-dom/client"
2
+ import { register } from "keystone_ui-react/src/registry.js"
3
+ import { startMounting } from "keystone_ui-react/src/mounting.js"
4
+ import Canvas from "./canvas/Canvas"
5
+
6
+ register("easy_flow/flow-editor", Canvas)
7
+
8
+ document.addEventListener("easy_flow:flow-named", (event) => {
9
+ const heading = document.querySelector("[data-flow-heading]")
10
+ if (heading) heading.textContent = event.detail
11
+ })
12
+
13
+ startMounting(document, createRoot)
@@ -0,0 +1,22 @@
1
+ <% content_for(:title, "Complete") %>
2
+
3
+ <% starting_over = flow_start_path(@guide.slug) %>
4
+
5
+ <%= ui_page(max_width: :md) do %>
6
+ <%= ui_page_header(title: "That's everything", subtitle: "Thanks — here's what you told us") do |header| %>
7
+ <% header.action do %>
8
+ <%= ui_button(label: "Start over", href: starting_over, variant: :secondary) %>
9
+ <% end %>
10
+ <% end %>
11
+
12
+ <%= ui_section do %>
13
+ <ul class="divide-y divide-gray-100 border-y border-gray-100">
14
+ <% @answered.each do |step, value| %>
15
+ <li data-answer="<%= step %>" class="flex items-baseline justify-between gap-6 py-3">
16
+ <span class="text-gray-600"><%= @guide.question_text(step) %></span>
17
+ <span class="shrink-0 font-medium text-gray-900"><%= @guide.choice_label(step, value) %></span>
18
+ </li>
19
+ <% end %>
20
+ </ul>
21
+ <% end %>
22
+ <% end %>
@@ -0,0 +1,17 @@
1
+ <% content_for(:title, @flow.title.presence || @flow.slug) %>
2
+
3
+ <%= ui_page(max_width: :md) do %>
4
+ <%= ui_page_header(title: @flow.title.presence || @flow.slug) %>
5
+
6
+ <%= ui_section do %>
7
+ <div class="flex flex-wrap items-center gap-3">
8
+ <% if @flow.each_step? && @flow.definition.present? && !previewing? %>
9
+ <%= ui_form(action: easy_flow.flow_runs_path(@flow.slug), method: :post) do %>
10
+ <%= ui_button(label: @flow.start_label.presence || "Start", type: :submit) %>
11
+ <% end %>
12
+ <% else %>
13
+ <%= ui_button(label: @flow.start_label.presence || "Start", href: flow_step_path(@flow.slug)) %>
14
+ <% end %>
15
+ </div>
16
+ <% end %>
17
+ <% end %>
@@ -0,0 +1,27 @@
1
+ <% content_for(:title, @guide.headline) %>
2
+
3
+ <%= ui_page(max_width: :md) do %>
4
+ <%= link_to "← Start over", flow_start_path(@guide.slug), class: "text-sm text-accent-600 hover:text-accent-700" %>
5
+
6
+ <div class="mt-6 mb-6">
7
+ <%= ui_progress(value: @answers.size, max: [ @guide.steps_on_path(@answers).size, 1 ].max, label: "Question #{@answers.size + 1}") %>
8
+ </div>
9
+
10
+ <%= form_with url: step_form[:url], method: step_form[:method], data: { turbo: false } do %>
11
+ <% if carries_answers? %>
12
+ <% @answers.each do |key, value| %>
13
+ <%= hidden_field_tag "answers[#{key}]", value %>
14
+ <% end %>
15
+ <% end %>
16
+
17
+ <%= render @drawing, step: @question %>
18
+
19
+ <div class="mt-8 flex items-center gap-4">
20
+ <%= ui_button(label: "Next", type: :submit) %>
21
+
22
+ <% if @answers.any? %>
23
+ <button type="submit" name="back" value="1" formnovalidate class="cursor-pointer text-sm text-gray-500 underline underline-offset-2 hover:text-gray-900">← Back</button>
24
+ <% end %>
25
+ </div>
26
+ <% end %>
27
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <%= ui_page(max_width: :lg) do %>
2
+ <p class="mb-4">
3
+ <%= link_to "← Back to the flow", easy_flow.manage_flow_path(@flow), class: "text-sm text-accent-600 hover:text-accent-700" %>
4
+ </p>
5
+
6
+ <%= ui_form_page(title: "Definition", back_url: easy_flow.manage_flow_path(@flow), subtitle: @flow.slug) %>
7
+
8
+ <%= ui_form(action: easy_flow.manage_flow_definition_path(@flow), method: :patch) do %>
9
+ <%= ui_textarea(name: "definition", value: JSON.pretty_generate(@flow.document), rows: 30) %>
10
+
11
+ <%= ui_button(label: "Save", type: :submit) %>
12
+ <% end %>
13
+ <% end %>
@@ -0,0 +1,26 @@
1
+ <%= ui_page(max_width: :lg) do %>
2
+ <p class="mb-4">
3
+ <%= link_to "← Back to the flow", easy_flow.manage_flow_path(@flow), class: "text-sm text-accent-600 hover:text-accent-700" %>
4
+ </p>
5
+
6
+ <%= ui_form_page(title: "Edit details", back_url: easy_flow.manage_flow_path(@flow)) %>
7
+
8
+ <%= ui_form(action: easy_flow.manage_flow_path(@flow), method: :patch) do %>
9
+ <%= ui_section(title: "How this is introduced") do %>
10
+ <label class="block text-sm font-medium mb-1">Title</label>
11
+ <%= ui_input(name: "flow[title]", value: @flow.title) %>
12
+
13
+ <label class="block text-sm font-medium mb-1 mt-4">Start label</label>
14
+ <%= ui_input(name: "flow[start_label]", value: @flow.start_label) %>
15
+ <% end %>
16
+
17
+ <%= ui_section(title: "What this keeps of a run") do %>
18
+ <%= ui_select(name: "flow[persists]", selected: @flow.persists,
19
+ options: [ [ "Nothing", "unsaved" ],
20
+ [ "Every answer as it is given", "each_step" ],
21
+ [ "The whole run once it finishes", "on_finish" ] ]) %>
22
+ <% end %>
23
+
24
+ <%= ui_button(label: "Save", type: :submit) %>
25
+ <% end %>
26
+ <% end %>
@@ -0,0 +1,32 @@
1
+ <%= ui_page(max_width: :xl) do %>
2
+ <%= ui_page_header(title: "Flows", subtitle: "Build and edit your flows") %>
3
+
4
+ <%= ui_data_table(
5
+ items: @flows,
6
+ columns: [ { title: "Title" }, { slug: "Slug" }, { kind: "Kind" }, { status: "Status" } ],
7
+ empty_message: "No flows yet."
8
+ ) do |table| %>
9
+ <% table.link(:title) { |flow| easy_flow.manage_flow_path(flow) } %>
10
+ <% table.actions do |flow| %>
11
+ <%= ui_form(action: easy_flow.manage_flow_path(flow), method: :delete) do %>
12
+ <%= ui_button(label: "Remove", type: :submit, variant: :secondary) %>
13
+ <% end %>
14
+ <% end %>
15
+ <% end %>
16
+
17
+ <%= ui_section(title: "Create a flow") do %>
18
+ <% if @flow&.errors&.any? %>
19
+ <%= ui_alert(message: @flow.errors.full_messages.to_sentence, type: :error) %>
20
+ <% end %>
21
+
22
+ <%= ui_form(action: easy_flow.manage_flows_path, method: :post) do %>
23
+ <label class="block text-sm font-medium mb-1">Slug</label>
24
+ <%= ui_input(name: "flow[slug]", placeholder: "e.g. business-scorecard") %>
25
+
26
+ <label class="block text-sm font-medium mb-1 mt-4">Kind</label>
27
+ <%= ui_select(name: "flow[kind]", options: [ [ "Scored", "scored" ], [ "Guide", "guide" ] ]) %>
28
+
29
+ <%= ui_button(label: "Create", type: :submit, variant: :secondary) %>
30
+ <% end %>
31
+ <% end %>
32
+ <% end %>
@@ -0,0 +1,26 @@
1
+ <% content_for :head do %>
2
+ <%= javascript_include_tag "keystone_ui/react", defer: true %>
3
+ <%= javascript_include_tag "easy_flow/canvas", defer: true %>
4
+ <% end %>
5
+
6
+ <div class="flex h-screen flex-col overflow-hidden">
7
+ <header class="flex shrink-0 items-center justify-between gap-4 border-b border-gray-200 px-6 py-3">
8
+ <div>
9
+ <h1 class="text-lg font-semibold text-gray-900" data-flow-heading><%= @flow.title.presence || @flow.slug %></h1>
10
+ <p class="text-sm text-gray-500"><%= @flow.slug %></p>
11
+ </div>
12
+ <div class="flex items-center gap-2">
13
+ <button type="button" data-open-panel
14
+ onclick="document.dispatchEvent(new CustomEvent('easy_flow:open-flow'))"
15
+ class="inline-flex items-center justify-center font-semibold rounded-lg border-0 cursor-pointer bg-accent-600 text-white hover:bg-accent-700 text-base px-4 py-2">This flow</button>
16
+
17
+ <%= ui_button(label: "Try it", href: easy_flow.manage_flow_preview_path(@flow), variant: :secondary) %>
18
+
19
+ <%= ui_button(label: "All flows", href: easy_flow.manage_flows_path, variant: :secondary) %>
20
+ </div>
21
+ </header>
22
+
23
+ <%= react_ui("easy_flow/flow-editor", { base: easy_flow.manage_flow_canvas_path(@flow), token: form_authenticity_token, initial: @canvas },
24
+ class: "min-h-0 flex-1",
25
+ data: { flow_canvas: true }) %>
26
+ </div>
@@ -0,0 +1,41 @@
1
+ <%= ui_page(max_width: :lg) do %>
2
+ <p class="mb-4">
3
+ <%= link_to "← Back to the flow", easy_flow.manage_flow_path(@flow), class: "text-sm text-accent-600 hover:text-accent-700" %>
4
+ </p>
5
+
6
+ <%= ui_page_header(title: "History", subtitle: @flow.title.presence || @flow.slug) %>
7
+
8
+ <%= ui_section do %>
9
+ <ul class="divide-y divide-gray-100 border-y border-gray-100">
10
+ <% @versions.each do |version| %>
11
+ <li data-version="<%= version.number %>" class="py-4">
12
+ <div class="flex items-baseline justify-between gap-4">
13
+ <span class="font-medium text-gray-900">Version <%= version.number %></span>
14
+ <span class="text-sm text-gray-500"><%= version.created_at.to_fs(:long) %></span>
15
+ </div>
16
+
17
+ <% if version == @flow.live_version %>
18
+ <p data-live class="mt-1 text-sm font-medium text-green-700">Visitors run this version</p>
19
+ <% end %>
20
+
21
+ <% if version.changes.any? %>
22
+ <ul class="mt-2 space-y-0.5">
23
+ <% version.changes.each do |change| %>
24
+ <li data-captured class="text-sm text-gray-600"><%= EasyFlow::Change.phrase(change) %></li>
25
+ <% end %>
26
+ </ul>
27
+ <% else %>
28
+ <p class="mt-2 text-sm text-gray-500">Nothing was recorded against this version.</p>
29
+ <% end %>
30
+
31
+ <% unless version == @versions.first %>
32
+ <%= button_to "Return the flow to this version",
33
+ easy_flow.return_manage_flow_version_path(@flow, version),
34
+ form: { data: { turbo: false } }, data: { return: true },
35
+ class: "mt-3 inline-flex items-center rounded-lg border border-gray-300 bg-white px-3 py-1.5 text-sm text-gray-900 hover:bg-gray-50 cursor-pointer" %>
36
+ <% end %>
37
+ </li>
38
+ <% end %>
39
+ </ul>
40
+ <% end %>
41
+ <% end %>
@@ -0,0 +1,9 @@
1
+ <fieldset>
2
+ <legend class="mb-5 text-xl font-semibold leading-snug text-gray-900"><%= step.text %></legend>
3
+
4
+ <div class="space-y-3">
5
+ <% step.choices.each do |choice| %>
6
+ <%= ui_radio_card(name: "answers[#{step.id}]", value: choice.value, label: choice.label.presence || choice.value, hint: choice.hint) %>
7
+ <% end %>
8
+ </div>
9
+ </fieldset>
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>EasyFlow</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= yield :head %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
data/config/routes.rb CHANGED
@@ -1,2 +1,34 @@
1
1
  EasyFlow::Engine.routes.draw do
2
+ namespace :manage do
3
+ resources :flows, only: [ :index, :create, :show, :edit, :update, :destroy ] do
4
+ resource :definition, only: [ :edit, :update ]
5
+ resource :preview, only: :show, controller: "previews" do
6
+ get :step
7
+ end
8
+ resources :versions, only: :index do
9
+ post :return, on: :member
10
+ end
11
+
12
+ resource :canvas, only: :show, controller: "canvas" do
13
+ post "steps", action: :add_step
14
+ patch "steps/:step", action: :configure_step
15
+ delete "steps/:step", action: :remove_step
16
+ patch "steps/:step/move", action: :move_step
17
+ post "versions", action: :create
18
+ post "publish", action: :publish
19
+ patch "details", action: :details
20
+ post "undo", action: :undo
21
+ post "redo", action: :redo
22
+ post "edges", action: :connect
23
+ delete "edges", action: :disconnect
24
+ end
25
+ end
26
+ end
27
+
28
+ post ":slug/runs", to: "flows#start", as: :flow_runs
29
+ get "runs/:id", to: "flows#step", as: :run
30
+ patch "runs/:id", to: "flows#update"
31
+
32
+ get ":slug", to: "flows#show", as: :flow
33
+ get ":slug/step", to: "flows#step", as: :flow_step
2
34
  end
@@ -1,7 +1,18 @@
1
+ require "keystone_ui-react"
2
+
1
3
  module EasyFlow
2
4
  class Engine < ::Rails::Engine
3
5
  isolate_namespace EasyFlow
4
6
 
7
+ initializer "easy_flow.tailwind" do
8
+ next unless Gem.loaded_specs.key?("keystone_ui")
9
+
10
+ require "keystone_ui"
11
+ KeystoneUi.configuration.tailwind_sources << root.join("app/views/**/*.erb").to_s
12
+ KeystoneUi.configuration.tailwind_sources << root.join("app/javascript/**/*.{js,jsx}").to_s
13
+ KeystoneUi.configuration.tailwind_sources << root.join("app/assets/builds/easy_flow/*.js").to_s
14
+ end
15
+
5
16
  initializer "easy_flow.step_types" do |app|
6
17
  app.config.to_prepare do
7
18
  EasyFlow::Start.register
@@ -1,3 +1,3 @@
1
1
  module EasyFlow
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/easy_flow.rb CHANGED
@@ -21,6 +21,21 @@ module EasyFlow
21
21
  DRAWING = "easy_flow/steps/choosing".freeze
22
22
 
23
23
  class << self
24
+ attr_writer :layout, :base_controller, :admin_layout
25
+ attr_accessor :visitor_authorization_method, :refusal_method, :admin_authentication_method
26
+
27
+ def layout
28
+ @layout || "easy_flow/application"
29
+ end
30
+
31
+ def base_controller
32
+ @base_controller || "ActionController::Base"
33
+ end
34
+
35
+ def admin_layout
36
+ @admin_layout || "application"
37
+ end
38
+
24
39
  def draws_with(template)
25
40
  @drawing = template
26
41
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_flow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tylercschneider
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: 8.1.3
26
+ - !ruby/object:Gem::Dependency
27
+ name: keystone_ui-react
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.1.2
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 0.1.2
26
40
  description: EasyFlow stores flows as versioned documents of steps and the connections
27
41
  between them, and runs a visitor through the live version one step at a time. Apps
28
42
  register their own step types.
@@ -35,6 +49,39 @@ files:
35
49
  - MIT-LICENSE
36
50
  - README.md
37
51
  - Rakefile
52
+ - app/assets/builds/easy_flow/canvas.js
53
+ - app/controllers/concerns/easy_flow/manage/authenticates_admin.rb
54
+ - app/controllers/concerns/easy_flow/manage/draws_canvas.rb
55
+ - app/controllers/easy_flow/application_controller.rb
56
+ - app/controllers/easy_flow/flows_controller.rb
57
+ - app/controllers/easy_flow/manage/base_controller.rb
58
+ - app/controllers/easy_flow/manage/canvas_controller.rb
59
+ - app/controllers/easy_flow/manage/definitions_controller.rb
60
+ - app/controllers/easy_flow/manage/flows_controller.rb
61
+ - app/controllers/easy_flow/manage/previews_controller.rb
62
+ - app/controllers/easy_flow/manage/versions_controller.rb
63
+ - app/javascript/easy_flow/canvas.jsx
64
+ - app/javascript/easy_flow/canvas/Canvas.jsx
65
+ - app/javascript/easy_flow/canvas/Connector.jsx
66
+ - app/javascript/easy_flow/canvas/ConnectorLayer.jsx
67
+ - app/javascript/easy_flow/canvas/Control.jsx
68
+ - app/javascript/easy_flow/canvas/Inspector.jsx
69
+ - app/javascript/easy_flow/canvas/Panel.jsx
70
+ - app/javascript/easy_flow/canvas/Placeholder.jsx
71
+ - app/javascript/easy_flow/canvas/Port.jsx
72
+ - app/javascript/easy_flow/canvas/Records.jsx
73
+ - app/javascript/easy_flow/canvas/StepCard.jsx
74
+ - app/javascript/easy_flow/canvas/Toolbar.jsx
75
+ - app/javascript/easy_flow/canvas/TypePicker.jsx
76
+ - app/javascript/easy_flow/canvas/changes.js
77
+ - app/javascript/easy_flow/canvas/choices.js
78
+ - app/javascript/easy_flow/canvas/flow.js
79
+ - app/javascript/easy_flow/canvas/flowSender.js
80
+ - app/javascript/easy_flow/canvas/ids.js
81
+ - app/javascript/easy_flow/canvas/rows.js
82
+ - app/javascript/easy_flow/canvas/styles.js
83
+ - app/javascript/easy_flow/canvas/useConnectors.js
84
+ - app/javascript/easy_flow/canvas/useFlow.js
38
85
  - app/models/easy_flow/admission.rb
39
86
  - app/models/easy_flow/application_record.rb
40
87
  - app/models/easy_flow/asked.rb
@@ -70,6 +117,16 @@ files:
70
117
  - app/models/easy_flow/validator.rb
71
118
  - app/models/easy_flow/version.rb
72
119
  - app/models/easy_flow/violation.rb
120
+ - app/views/easy_flow/flows/complete.html.erb
121
+ - app/views/easy_flow/flows/show.html.erb
122
+ - app/views/easy_flow/flows/step.html.erb
123
+ - app/views/easy_flow/manage/definitions/edit.html.erb
124
+ - app/views/easy_flow/manage/flows/edit.html.erb
125
+ - app/views/easy_flow/manage/flows/index.html.erb
126
+ - app/views/easy_flow/manage/flows/show.html.erb
127
+ - app/views/easy_flow/manage/versions/index.html.erb
128
+ - app/views/easy_flow/steps/_choosing.html.erb
129
+ - app/views/layouts/easy_flow/application.html.erb
73
130
  - config/routes.rb
74
131
  - db/migrate/20260924120000_create_easy_flow_definitions.rb
75
132
  - db/migrate/20260924120100_create_easy_flow_versions.rb