alembic 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +105 -0
- data/Rakefile +6 -0
- data/app/assets/builds/alembic/canvas.js +1 -0
- data/app/assets/builds/alembic/page_builder.css +1 -0
- data/app/assets/builds/alembic/page_builder.js +5 -0
- data/app/assets/stylesheets/alembic/application.css +15 -0
- data/app/controllers/alembic/application_controller.rb +32 -0
- data/app/controllers/alembic/flows_controller.rb +104 -0
- data/app/controllers/alembic/manage/base_controller.rb +16 -0
- data/app/controllers/alembic/manage/canvas_controller.rb +183 -0
- data/app/controllers/alembic/manage/definitions_controller.rb +15 -0
- data/app/controllers/alembic/manage/flows_controller.rb +55 -0
- data/app/controllers/alembic/manage/page_blocks_controller.rb +19 -0
- data/app/controllers/alembic/manage/pages_controller.rb +38 -0
- data/app/controllers/alembic/manage/previews_controller.rb +38 -0
- data/app/controllers/alembic/manage/versions_controller.rb +22 -0
- data/app/controllers/concerns/alembic/manage/authenticates_admin.rb +19 -0
- data/app/controllers/concerns/alembic/manage/draws_canvas.rb +35 -0
- data/app/helpers/alembic/application_helper.rb +11 -0
- data/app/javascript/alembic/canvas/Canvas.jsx +197 -0
- data/app/javascript/alembic/canvas/Connector.jsx +30 -0
- data/app/javascript/alembic/canvas/ConnectorLayer.jsx +31 -0
- data/app/javascript/alembic/canvas/Control.jsx +42 -0
- data/app/javascript/alembic/canvas/Inspector.jsx +44 -0
- data/app/javascript/alembic/canvas/Panel.jsx +67 -0
- data/app/javascript/alembic/canvas/Placeholder.jsx +24 -0
- data/app/javascript/alembic/canvas/Port.jsx +16 -0
- data/app/javascript/alembic/canvas/Records.jsx +34 -0
- data/app/javascript/alembic/canvas/StepCard.jsx +57 -0
- data/app/javascript/alembic/canvas/Toolbar.jsx +19 -0
- data/app/javascript/alembic/canvas/TypePicker.jsx +21 -0
- data/app/javascript/alembic/canvas/changes.js +5 -0
- data/app/javascript/alembic/canvas/choices.js +4 -0
- data/app/javascript/alembic/canvas/flow.js +7 -0
- data/app/javascript/alembic/canvas/flowSender.js +22 -0
- data/app/javascript/alembic/canvas/ids.js +7 -0
- data/app/javascript/alembic/canvas/rows.js +2 -0
- data/app/javascript/alembic/canvas/styles.js +3 -0
- data/app/javascript/alembic/canvas/useConnectors.js +75 -0
- data/app/javascript/alembic/canvas/useFlow.js +17 -0
- data/app/javascript/alembic/canvas.jsx +13 -0
- data/app/javascript/alembic/page_builder/PageBuilder.jsx +18 -0
- data/app/javascript/alembic/page_builder.jsx +10 -0
- data/app/jobs/alembic/application_job.rb +4 -0
- data/app/mailers/alembic/application_mailer.rb +6 -0
- data/app/models/alembic/application_record.rb +5 -0
- data/app/models/alembic/asked.rb +3 -0
- data/app/models/alembic/choice.rb +7 -0
- data/app/models/alembic/flow/admission.rb +19 -0
- data/app/models/alembic/flow/canvas.rb +167 -0
- data/app/models/alembic/flow/change.rb +18 -0
- data/app/models/alembic/flow/condition.rb +24 -0
- data/app/models/alembic/flow/definition.rb +132 -0
- data/app/models/alembic/flow/digest.rb +116 -0
- data/app/models/alembic/flow/document.rb +131 -0
- data/app/models/alembic/flow/drawing.rb +15 -0
- data/app/models/alembic/flow/edge.rb +9 -0
- data/app/models/alembic/flow/edit_history.rb +75 -0
- data/app/models/alembic/flow/layout.rb +88 -0
- data/app/models/alembic/flow/name.rb +15 -0
- data/app/models/alembic/flow/node.rb +5 -0
- data/app/models/alembic/flow/output.rb +23 -0
- data/app/models/alembic/flow/progress/kept.rb +38 -0
- data/app/models/alembic/flow/progress/loose.rb +43 -0
- data/app/models/alembic/flow/progress.rb +11 -0
- data/app/models/alembic/flow/registry.rb +25 -0
- data/app/models/alembic/flow/run.rb +54 -0
- data/app/models/alembic/flow/runner.rb +65 -0
- data/app/models/alembic/flow/settings.rb +80 -0
- data/app/models/alembic/flow/start.rb +13 -0
- data/app/models/alembic/flow/step.rb +42 -0
- data/app/models/alembic/flow/step_type/declaration.rb +118 -0
- data/app/models/alembic/flow/step_type.rb +69 -0
- data/app/models/alembic/flow/summaries.rb +44 -0
- data/app/models/alembic/flow/summary_version.rb +13 -0
- data/app/models/alembic/flow/switch.rb +17 -0
- data/app/models/alembic/flow/terminal.rb +13 -0
- data/app/models/alembic/flow/validator.rb +171 -0
- data/app/models/alembic/flow/version.rb +26 -0
- data/app/models/alembic/flow/violation.rb +9 -0
- data/app/models/alembic/flow.rb +44 -0
- data/app/models/alembic/outputs/band.rb +22 -0
- data/app/models/alembic/outputs/grouped.rb +26 -0
- data/app/models/alembic/outputs/lowest.rb +20 -0
- data/app/models/alembic/outputs/percentage.rb +31 -0
- data/app/models/alembic/outputs/tally.rb +23 -0
- data/app/models/alembic/outputs/weighted_sum.rb +26 -0
- data/app/models/alembic/page.rb +11 -0
- data/app/models/alembic/runner.rb +13 -0
- data/app/models/alembic/steps/question.rb +52 -0
- data/app/models/alembic/summary/output_type.rb +40 -0
- data/app/models/alembic/summary/registry.rb +25 -0
- data/app/models/alembic/summary/report.rb +31 -0
- data/app/models/alembic/summary/result.rb +5 -0
- data/app/models/alembic/summary/run.rb +13 -0
- data/app/models/alembic/summary.rb +15 -0
- data/app/views/alembic/flow/steps/_choosing.html.erb +9 -0
- data/app/views/alembic/flows/complete.html.erb +34 -0
- data/app/views/alembic/flows/show.html.erb +17 -0
- data/app/views/alembic/flows/step.html.erb +27 -0
- data/app/views/alembic/manage/definitions/edit.html.erb +13 -0
- data/app/views/alembic/manage/flows/edit.html.erb +29 -0
- data/app/views/alembic/manage/flows/index.html.erb +32 -0
- data/app/views/alembic/manage/flows/show.html.erb +26 -0
- data/app/views/alembic/manage/pages/_block_content.html.erb +1 -0
- data/app/views/alembic/manage/pages/index.html.erb +20 -0
- data/app/views/alembic/manage/pages/show.html.erb +11 -0
- data/app/views/alembic/manage/versions/index.html.erb +41 -0
- data/app/views/layouts/alembic/application.html.erb +17 -0
- data/config/routes.rb +42 -0
- data/db/migrate/20260604215031_create_alembic_diagnostics.rb +14 -0
- data/db/migrate/20260605015051_create_alembic_questions.rb +12 -0
- data/db/migrate/20260605021526_create_alembic_options.rb +14 -0
- data/db/migrate/20260605023308_create_alembic_conditions.rb +11 -0
- data/db/migrate/20260605025623_create_alembic_bands.rb +12 -0
- data/db/migrate/20260605032859_create_alembic_condition_options.rb +10 -0
- data/db/migrate/20260605032900_reshape_conditions_for_placement.rb +11 -0
- data/db/migrate/20260605125119_create_alembic_results.rb +14 -0
- data/db/migrate/20260605130338_create_alembic_rules.rb +10 -0
- data/db/migrate/20260605130339_create_alembic_rule_results.rb +10 -0
- data/db/migrate/20260605210714_add_definition_to_alembic_diagnostics.rb +5 -0
- data/db/migrate/20260606000855_add_guide_copy_to_alembic_diagnostics.rb +9 -0
- data/db/migrate/20260606005430_create_alembic_nodes.rb +22 -0
- data/db/migrate/20260606010312_create_alembic_build_steps.rb +12 -0
- data/db/migrate/20260606011110_create_alembic_warnings.rb +11 -0
- data/db/migrate/20260804180000_create_alembic_domains.rb +14 -0
- data/db/migrate/20260804180100_add_domain_to_alembic_questions.rb +5 -0
- data/db/migrate/20260822120000_create_alembic_definition_versions.rb +14 -0
- data/db/migrate/20260822120100_backfill_alembic_definition_versions.rb +17 -0
- data/db/migrate/20260822130000_remove_definition_from_alembic_diagnostics.rb +28 -0
- data/db/migrate/20260822140000_create_alembic_responses.rb +14 -0
- data/db/migrate/20260824120000_create_alembic_transitions.rb +10 -0
- data/db/migrate/20260824130000_drop_alembic_builder_tables.rb +17 -0
- data/db/migrate/20260824140000_add_definition_cursor_to_alembic_diagnostics.rb +5 -0
- data/db/migrate/20260824160000_add_summary_definition_to_alembic_diagnostics.rb +5 -0
- data/db/migrate/20260824170000_drop_alembic_guide_copy_columns.rb +8 -0
- data/db/migrate/20260825120000_create_alembic_summary_versions.rb +14 -0
- data/db/migrate/20260825130000_add_summary_cursor_to_alembic_diagnostics.rb +5 -0
- data/db/migrate/20260825140000_move_summary_definitions_into_versions.rb +26 -0
- data/db/migrate/20260825150000_drop_summary_definition_from_alembic_diagnostics.rb +5 -0
- data/db/migrate/20260825160000_add_summary_version_to_alembic_responses.rb +6 -0
- data/db/migrate/20260825170000_rename_question_settings_in_current_definitions.rb +51 -0
- data/db/migrate/20260825180000_add_document_to_alembic_diagnostics.rb +6 -0
- data/db/migrate/20260825190000_seed_documents_from_current_definitions.rb +29 -0
- data/db/migrate/20260825200000_add_published_version_to_alembic_diagnostics.rb +6 -0
- data/db/migrate/20260825210000_publish_current_definitions.rb +29 -0
- data/db/migrate/20260825220000_add_undone_changes_to_alembic_diagnostics.rb +5 -0
- data/db/migrate/20260825223322_add_status_to_alembic_definition_versions.rb +8 -0
- data/db/migrate/20260825224538_remove_published_version_from_alembic_diagnostics.rb +5 -0
- data/db/migrate/20260825225015_change_alembic_diagnostic_status_to_availability.rb +16 -0
- data/db/migrate/20260825230000_add_undo_history_to_alembic_diagnostics.rb +5 -0
- data/db/migrate/20260825230500_add_changes_to_alembic_definition_versions.rb +5 -0
- data/db/migrate/20260826230000_rename_alembic_responses_to_flow_runs.rb +5 -0
- data/db/migrate/20260826234500_rename_answers_to_recorded_on_flow_runs.rb +5 -0
- data/db/migrate/20260826235000_rename_definition_versions_to_flow_versions.rb +5 -0
- data/db/migrate/20260826235500_rename_summary_versions_to_flow_summaries.rb +5 -0
- data/db/migrate/20260827000000_rename_diagnostics_to_flows.rb +8 -0
- data/db/migrate/20260831000000_add_persists_to_alembic_flows.rb +5 -0
- data/db/migrate/20260914120000_create_alembic_pages.rb +9 -0
- data/db/migrate/20260915120000_add_blocks_to_alembic_pages.rb +5 -0
- data/lib/alembic/engine.rb +43 -0
- data/lib/alembic/leftover_stylesheet.rb +14 -0
- data/lib/alembic/version.rb +3 -0
- data/lib/alembic.rb +34 -0
- data/lib/tasks/alembic_tasks.rake +4 -0
- metadata +252 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Alembic
|
|
2
|
+
module Summary
|
|
3
|
+
class UnknownOutputType < KeyError; end
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
def output(id, &declaration)
|
|
7
|
+
registry.register(OutputType.define(id, &declaration))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def registry
|
|
11
|
+
@registry ||= Registry.new
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
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,34 @@
|
|
|
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
|
+
<% if @outputs.any? %>
|
|
13
|
+
<%= ui_section do %>
|
|
14
|
+
<%= ui_grid(cols: { default: 1, sm: 2 }, gap: :lg) do %>
|
|
15
|
+
<% @outputs.each do |output| %>
|
|
16
|
+
<div data-output="<%= output.id %>">
|
|
17
|
+
<%= ui_stat_card(label: output.label, value: alembic_output_lines(output.value).join(" · ")) %>
|
|
18
|
+
</div>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% end %>
|
|
21
|
+
<% end %>
|
|
22
|
+
<% end %>
|
|
23
|
+
|
|
24
|
+
<%= ui_section(title: @outputs.any? ? "What you told us" : nil) do %>
|
|
25
|
+
<ul class="divide-y divide-gray-100 border-y border-gray-100">
|
|
26
|
+
<% @answered.each do |step, value| %>
|
|
27
|
+
<li data-answer="<%= step %>" class="flex items-baseline justify-between gap-6 py-3">
|
|
28
|
+
<span class="text-gray-600"><%= @guide.question_text(step) %></span>
|
|
29
|
+
<span class="shrink-0 font-medium text-gray-900"><%= @guide.choice_label(step, value) %></span>
|
|
30
|
+
</li>
|
|
31
|
+
<% end %>
|
|
32
|
+
</ul>
|
|
33
|
+
<% end %>
|
|
34
|
+
<% end %>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<% content_for(:title, @diagnostic.title.presence || @diagnostic.slug) %>
|
|
2
|
+
|
|
3
|
+
<%= ui_page(max_width: :md) do %>
|
|
4
|
+
<%= ui_page_header(title: @diagnostic.title.presence || @diagnostic.slug, subtitle: @diagnostic.summary) %>
|
|
5
|
+
|
|
6
|
+
<%= ui_section do %>
|
|
7
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
8
|
+
<% if @diagnostic.each_step? && @diagnostic.definition.present? && !previewing? %>
|
|
9
|
+
<%= ui_form(action: alembic.flow_runs_path(@diagnostic.slug), method: :post) do %>
|
|
10
|
+
<%= ui_button(label: @diagnostic.start_label.presence || "Start", type: :submit) %>
|
|
11
|
+
<% end %>
|
|
12
|
+
<% else %>
|
|
13
|
+
<%= ui_button(label: @diagnostic.start_label.presence || "Start", href: flow_step_path(@diagnostic.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", alembic.manage_flow_path(@diagnostic), class: "text-sm text-accent-600 hover:text-accent-700" %>
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
<%= ui_form_page(title: "Definition", back_url: alembic.manage_flow_path(@diagnostic), subtitle: @diagnostic.slug) %>
|
|
7
|
+
|
|
8
|
+
<%= ui_form(action: alembic.manage_flow_definition_path(@diagnostic), method: :patch) do %>
|
|
9
|
+
<%= ui_textarea(name: "definition", value: JSON.pretty_generate(@diagnostic.document), rows: 30) %>
|
|
10
|
+
|
|
11
|
+
<%= ui_button(label: "Save", type: :submit) %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<% end %>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<%= ui_page(max_width: :lg) do %>
|
|
2
|
+
<p class="mb-4">
|
|
3
|
+
<%= link_to "← Back to the flow", alembic.manage_flow_path(@diagnostic), class: "text-sm text-accent-600 hover:text-accent-700" %>
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
<%= ui_form_page(title: "Edit details", back_url: alembic.manage_flow_path(@diagnostic)) %>
|
|
7
|
+
|
|
8
|
+
<%= ui_form(action: alembic.manage_flow_path(@diagnostic), 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: @diagnostic.title) %>
|
|
12
|
+
|
|
13
|
+
<label class="block text-sm font-medium mb-1 mt-4">Summary</label>
|
|
14
|
+
<%= ui_textarea(name: "flow[summary]", value: @diagnostic.summary, rows: 4) %>
|
|
15
|
+
|
|
16
|
+
<label class="block text-sm font-medium mb-1 mt-4">Start label</label>
|
|
17
|
+
<%= ui_input(name: "flow[start_label]", value: @diagnostic.start_label) %>
|
|
18
|
+
<% end %>
|
|
19
|
+
|
|
20
|
+
<%= ui_section(title: "What this keeps of a run") do %>
|
|
21
|
+
<%= ui_select(name: "flow[persists]", selected: @diagnostic.persists,
|
|
22
|
+
options: [ [ "Nothing", "unsaved" ],
|
|
23
|
+
[ "Every answer as it is given", "each_step" ],
|
|
24
|
+
[ "The whole run once it finishes", "on_finish" ] ]) %>
|
|
25
|
+
<% end %>
|
|
26
|
+
|
|
27
|
+
<%= ui_button(label: "Save", type: :submit) %>
|
|
28
|
+
<% end %>
|
|
29
|
+
<% 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: @diagnostics,
|
|
6
|
+
columns: [ { title: "Title" }, { slug: "Slug" }, { kind: "Kind" }, { status: "Status" } ],
|
|
7
|
+
empty_message: "No diagnostics yet."
|
|
8
|
+
) do |table| %>
|
|
9
|
+
<% table.link(:title) { |diagnostic| alembic.manage_flow_path(diagnostic) } %>
|
|
10
|
+
<% table.actions do |diagnostic| %>
|
|
11
|
+
<%= ui_form(action: alembic.manage_flow_path(diagnostic), 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 diagnostic") do %>
|
|
18
|
+
<% if @diagnostic&.errors&.any? %>
|
|
19
|
+
<%= ui_alert(message: @diagnostic.errors.full_messages.to_sentence, type: :error) %>
|
|
20
|
+
<% end %>
|
|
21
|
+
|
|
22
|
+
<%= ui_form(action: alembic.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 "alembic/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><%= @diagnostic.title.presence || @diagnostic.slug %></h1>
|
|
10
|
+
<p class="text-sm text-gray-500"><%= @diagnostic.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('alembic: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: alembic.manage_flow_preview_path(@diagnostic), variant: :secondary) %>
|
|
18
|
+
|
|
19
|
+
<%= ui_button(label: "All diagnostics", href: alembic.manage_flows_path, variant: :secondary) %>
|
|
20
|
+
</div>
|
|
21
|
+
</header>
|
|
22
|
+
|
|
23
|
+
<%= react_ui("alembic/flow-editor", { base: alembic.manage_flow_canvas_path(@diagnostic), token: form_authenticity_token, initial: @canvas },
|
|
24
|
+
class: "min-h-0 flex-1",
|
|
25
|
+
data: { flow_canvas: true }) %>
|
|
26
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= KsBlocks.registry.block_types(kind: :pages).find { |type| type.key.to_s == block["type"] }&.name %>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<%= ui_page(max_width: :xl) do %>
|
|
2
|
+
<%= ui_page_header(title: "Pages", subtitle: "Build and edit your pages") %>
|
|
3
|
+
|
|
4
|
+
<%= ui_data_table(
|
|
5
|
+
items: @pages,
|
|
6
|
+
columns: [ { name: "Name" } ],
|
|
7
|
+
empty_message: "No pages yet."
|
|
8
|
+
) do |table| %>
|
|
9
|
+
<% table.link(:name) { |page| alembic.manage_page_path(page) } %>
|
|
10
|
+
<% end %>
|
|
11
|
+
|
|
12
|
+
<%= ui_section(title: "Create a page") do %>
|
|
13
|
+
<%= ui_form(action: alembic.manage_pages_path, method: :post) do %>
|
|
14
|
+
<label class="block text-sm font-medium mb-1">Name</label>
|
|
15
|
+
<%= ui_input(name: "page[name]", placeholder: "e.g. Welcome") %>
|
|
16
|
+
|
|
17
|
+
<%= ui_button(label: "Create", type: :submit, variant: :secondary) %>
|
|
18
|
+
<% end %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% end %>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<% content_for :head do %>
|
|
2
|
+
<%= stylesheet_link_tag "alembic/page_builder" %>
|
|
3
|
+
<%= javascript_include_tag "keystone_ui/react", defer: true %>
|
|
4
|
+
<%= javascript_include_tag "alembic/page_builder", defer: true %>
|
|
5
|
+
<% end %>
|
|
6
|
+
|
|
7
|
+
<%= react_ui("alembic/page-builder", @payload.merge(token: form_authenticity_token)) %>
|
|
8
|
+
|
|
9
|
+
<%= block_contents(@page.blocks) do |block| %>
|
|
10
|
+
<%= render "alembic/manage/pages/block_content", block: block %>
|
|
11
|
+
<% end %>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<%= ui_page(max_width: :lg) do %>
|
|
2
|
+
<p class="mb-4">
|
|
3
|
+
<%= link_to "← Back to the flow", alembic.manage_flow_path(@diagnostic), class: "text-sm text-accent-600 hover:text-accent-700" %>
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
<%= ui_page_header(title: "History", subtitle: @diagnostic.title.presence || @diagnostic.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 == @diagnostic.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"><%= Alembic::Flow::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
|
+
alembic.return_manage_flow_version_path(@diagnostic, 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,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Alembic</title>
|
|
5
|
+
<%= csrf_meta_tags %>
|
|
6
|
+
<%= csp_meta_tag %>
|
|
7
|
+
|
|
8
|
+
<%= yield :head %>
|
|
9
|
+
|
|
10
|
+
<%= stylesheet_link_tag "alembic/application", media: "all" %>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
|
|
14
|
+
<%= yield %>
|
|
15
|
+
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
Alembic::Engine.routes.draw do
|
|
2
|
+
namespace :manage do
|
|
3
|
+
resources :pages, only: [ :index, :create, :show ] do
|
|
4
|
+
get "layout", to: "page_blocks#layout", as: :layout
|
|
5
|
+
post "blocks", to: "page_blocks#add_block", as: :blocks
|
|
6
|
+
patch "blocks", to: "page_blocks#place_blocks"
|
|
7
|
+
patch "blocks/:block_id", to: "page_blocks#fill_block"
|
|
8
|
+
delete "blocks/:block_id", to: "page_blocks#remove_block", as: :block
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
resources :flows, only: [ :index, :create, :show, :edit, :update, :destroy ] do
|
|
12
|
+
resource :definition, only: [ :edit, :update ]
|
|
13
|
+
resource :preview, only: :show, controller: "previews" do
|
|
14
|
+
get :step
|
|
15
|
+
end
|
|
16
|
+
resources :versions, only: :index do
|
|
17
|
+
post :return, on: :member
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
resource :canvas, only: :show, controller: "canvas" do
|
|
21
|
+
post "steps", action: :add_step
|
|
22
|
+
patch "steps/:step", action: :configure_step
|
|
23
|
+
delete "steps/:step", action: :remove_step
|
|
24
|
+
patch "steps/:step/move", action: :move_step
|
|
25
|
+
post "versions", action: :create
|
|
26
|
+
post "publish", action: :publish
|
|
27
|
+
patch "details", action: :details
|
|
28
|
+
post "undo", action: :undo
|
|
29
|
+
post "redo", action: :redo
|
|
30
|
+
post "edges", action: :connect
|
|
31
|
+
delete "edges", action: :disconnect
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
post ":slug/runs", to: "flows#start", as: :flow_runs
|
|
37
|
+
get "runs/:id", to: "flows#step", as: :run
|
|
38
|
+
patch "runs/:id", to: "flows#update"
|
|
39
|
+
|
|
40
|
+
get ":slug", to: "flows#show", as: :flow
|
|
41
|
+
get ":slug/step", to: "flows#step", as: :flow_step
|
|
42
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class CreateAlembicDiagnostics < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_diagnostics do |t|
|
|
4
|
+
t.string :slug
|
|
5
|
+
t.string :title
|
|
6
|
+
t.text :summary
|
|
7
|
+
t.string :kind
|
|
8
|
+
t.string :status
|
|
9
|
+
|
|
10
|
+
t.timestamps
|
|
11
|
+
end
|
|
12
|
+
add_index :alembic_diagnostics, :slug, unique: true
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class CreateAlembicQuestions < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_questions do |t|
|
|
4
|
+
t.references :diagnostic, null: false, foreign_key: { to_table: :alembic_diagnostics }
|
|
5
|
+
t.integer :position
|
|
6
|
+
t.string :key
|
|
7
|
+
t.text :text
|
|
8
|
+
|
|
9
|
+
t.timestamps
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class CreateAlembicOptions < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_options do |t|
|
|
4
|
+
t.references :question, null: false, foreign_key: { to_table: :alembic_questions }
|
|
5
|
+
t.integer :position
|
|
6
|
+
t.string :value
|
|
7
|
+
t.string :label
|
|
8
|
+
t.text :hint
|
|
9
|
+
t.integer :weight
|
|
10
|
+
|
|
11
|
+
t.timestamps
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class CreateAlembicConditions < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_conditions do |t|
|
|
4
|
+
t.references :question, null: false, foreign_key: { to_table: :alembic_questions }
|
|
5
|
+
t.string :depends_on
|
|
6
|
+
t.json :values
|
|
7
|
+
|
|
8
|
+
t.timestamps
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class CreateAlembicBands < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_bands do |t|
|
|
4
|
+
t.references :diagnostic, null: false, foreign_key: { to_table: :alembic_diagnostics }
|
|
5
|
+
t.integer :ceiling
|
|
6
|
+
t.string :name
|
|
7
|
+
t.text :description
|
|
8
|
+
|
|
9
|
+
t.timestamps
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class CreateAlembicConditionOptions < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_condition_options do |t|
|
|
4
|
+
t.references :condition, null: false, foreign_key: { to_table: :alembic_conditions }
|
|
5
|
+
t.references :option, null: false, foreign_key: { to_table: :alembic_options }
|
|
6
|
+
|
|
7
|
+
t.timestamps
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class ReshapeConditionsForPlacement < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
add_reference :alembic_conditions, :subject, polymorphic: true, null: false
|
|
4
|
+
add_reference :alembic_conditions, :tested_question, null: false,
|
|
5
|
+
foreign_key: { to_table: :alembic_questions }
|
|
6
|
+
|
|
7
|
+
remove_reference :alembic_conditions, :question, foreign_key: { to_table: :alembic_questions }
|
|
8
|
+
remove_column :alembic_conditions, :depends_on, :string
|
|
9
|
+
remove_column :alembic_conditions, :values, :json
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class CreateAlembicResults < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_results do |t|
|
|
4
|
+
t.references :diagnostic, null: false, foreign_key: { to_table: :alembic_diagnostics }
|
|
5
|
+
t.string :slot
|
|
6
|
+
t.string :key
|
|
7
|
+
t.string :title
|
|
8
|
+
t.text :body
|
|
9
|
+
t.integer :position
|
|
10
|
+
|
|
11
|
+
t.timestamps
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class CreateAlembicRuleResults < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_rule_results do |t|
|
|
4
|
+
t.references :rule, null: false, foreign_key: { to_table: :alembic_rules }
|
|
5
|
+
t.references :result, null: false, foreign_key: { to_table: :alembic_results }
|
|
6
|
+
|
|
7
|
+
t.timestamps
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
class AddGuideCopyToAlembicDiagnostics < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
add_column :alembic_diagnostics, :kicker, :string
|
|
4
|
+
add_column :alembic_diagnostics, :headline, :string
|
|
5
|
+
add_column :alembic_diagnostics, :blurb, :text
|
|
6
|
+
add_column :alembic_diagnostics, :start_label, :string
|
|
7
|
+
add_column :alembic_diagnostics, :resolver_key, :string
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class CreateAlembicNodes < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_nodes do |t|
|
|
4
|
+
t.references :diagnostic, null: false, foreign_key: { to_table: :alembic_diagnostics }
|
|
5
|
+
t.string :kind
|
|
6
|
+
t.string :key
|
|
7
|
+
t.integer :position
|
|
8
|
+
t.string :name
|
|
9
|
+
t.text :tagline
|
|
10
|
+
t.text :complexity
|
|
11
|
+
t.text :setup
|
|
12
|
+
t.text :maintenance
|
|
13
|
+
t.text :captures
|
|
14
|
+
t.text :why
|
|
15
|
+
t.text :pains
|
|
16
|
+
t.text :avoid
|
|
17
|
+
t.text :avoid_pain
|
|
18
|
+
|
|
19
|
+
t.timestamps
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class CreateAlembicBuildSteps < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_build_steps do |t|
|
|
4
|
+
t.references :node, null: false, foreign_key: { to_table: :alembic_nodes }
|
|
5
|
+
t.integer :position
|
|
6
|
+
t.string :title
|
|
7
|
+
t.text :code
|
|
8
|
+
|
|
9
|
+
t.timestamps
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class CreateAlembicWarnings < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_warnings do |t|
|
|
4
|
+
t.references :diagnostic, null: false, foreign_key: { to_table: :alembic_diagnostics }
|
|
5
|
+
t.string :key
|
|
6
|
+
t.text :text
|
|
7
|
+
|
|
8
|
+
t.timestamps
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class CreateAlembicDomains < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_domains do |t|
|
|
4
|
+
t.references :diagnostic, null: false, foreign_key: { to_table: :alembic_diagnostics }
|
|
5
|
+
t.string :key
|
|
6
|
+
t.string :name
|
|
7
|
+
t.text :gap_meaning
|
|
8
|
+
t.text :gap_cost
|
|
9
|
+
t.integer :position
|
|
10
|
+
|
|
11
|
+
t.timestamps
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class CreateAlembicDefinitionVersions < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :alembic_definition_versions do |t|
|
|
4
|
+
t.references :diagnostic, null: false, foreign_key: { to_table: :alembic_diagnostics }
|
|
5
|
+
t.integer :number, null: false
|
|
6
|
+
t.json :definition
|
|
7
|
+
|
|
8
|
+
t.datetime :created_at, null: false
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
add_index :alembic_definition_versions, [ :diagnostic_id, :number ], unique: true,
|
|
12
|
+
name: "index_alembic_definition_versions_on_diagnostic_and_number"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class BackfillAlembicDefinitionVersions < ActiveRecord::Migration[8.1]
|
|
2
|
+
class Diagnostic < ActiveRecord::Base
|
|
3
|
+
self.table_name = "alembic_diagnostics"
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
class DefinitionVersion < ActiveRecord::Base
|
|
7
|
+
self.table_name = "alembic_definition_versions"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def up
|
|
11
|
+
Diagnostic.where.not(definition: nil).find_each do |diagnostic|
|
|
12
|
+
next if DefinitionVersion.exists?(diagnostic_id: diagnostic.id)
|
|
13
|
+
|
|
14
|
+
DefinitionVersion.create!(diagnostic_id: diagnostic.id, number: 1, definition: diagnostic.definition)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|