easy_flow 0.15.0 → 0.17.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 +4 -4
- data/app/models/easy_flow/count.rb +30 -0
- data/app/views/easy_flow/steps/_uploading.html.erb +1 -5
- data/lib/easy_flow/engine.rb +1 -0
- data/lib/easy_flow/version.rb +1 -1
- data/the_local/agents/easy_flow-develop.md +5 -5
- data/the_local/agents/easy_flow-info.md +6 -4
- data/the_local/agents/easy_flow-install.md +6 -4
- data/the_local/interface.yml +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '093d6e31f420e50db193c425d8d523e75f242fc86f82b069962cc09e3639f79b'
|
|
4
|
+
data.tar.gz: 4d87fc9a7f19b7be067a01502653aa8e271dff52df51de6971317b830ba6a370
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d4b69c37a43cfb0b9b4de6696b97063da84086ba23154a78bcc013577a6a6beff5a4ed6bf65647580ad88336b18486244662e4eb5792e39c4225616ca8a578bd
|
|
7
|
+
data.tar.gz: 9ede6727e7d129813dd1ec212b6c18e0edf9846b17a20feba45756ff5986ad4f70af897df70d5e462ec2eb775f9725c7545a510c306dc09c4c02ec1ae828256e
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module EasyFlow
|
|
2
|
+
class Count
|
|
3
|
+
include Step
|
|
4
|
+
|
|
5
|
+
step_name "Count"
|
|
6
|
+
|
|
7
|
+
setting :step, type: :previous_step
|
|
8
|
+
setting :output, outputs_of: :step
|
|
9
|
+
setting :answer, from: :output
|
|
10
|
+
|
|
11
|
+
output :count, type: :integer
|
|
12
|
+
|
|
13
|
+
names_by { |node| [ "Count", *node.config.values_at("step", "answer") ].compact_blank.join(" ") }
|
|
14
|
+
|
|
15
|
+
def process(node, state)
|
|
16
|
+
visits(node, state).count { |answer| counted?(node, answer) }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def visits(node, state)
|
|
22
|
+
state.select { |key, _| key.to_s.split("@").first == node.config["step"] }.values
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def counted?(node, answer)
|
|
26
|
+
answer = answer[node.config["output"]] if answer.is_a?(Hash)
|
|
27
|
+
node.config["answer"].blank? || answer.to_s == node.config["answer"].to_s
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -1,5 +1 @@
|
|
|
1
|
-
|
|
2
|
-
<legend class="ks-section-title mb-5 text-xl font-semibold leading-snug"><%= step.text %></legend>
|
|
3
|
-
|
|
4
|
-
<%= file_field_tag "answers[#{step.id}]", accept: step.accepts.presence %>
|
|
5
|
-
</fieldset>
|
|
1
|
+
<%= ui_file_upload(name: "answers[#{step.id}]", label: step.text, accept: step.accepts.presence, hint: ("Accepts #{step.accepts}" if step.accepts.present?)) %>
|
data/lib/easy_flow/engine.rb
CHANGED
data/lib/easy_flow/version.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: easy_flow-develop
|
|
3
|
-
description: Use PROACTIVELY for adding a step type to easy_flow flows (a step that asks the visitor something, takes several answers at once, computes a value from earlier answers, picks the next branch, or holds the visitor until something outside the flow has happened), showing a step differently depending on the visitor's stored run, branching on what a visitor ticked on a checklist, moving a paused run on once what it waits for has happened, refusing a blank or invalid answer to a step with a message, offering an admin a step setting whose options are read from the app's own records, letting an admin pick another flow of the same host in a step's settings, adding a step type that starts another flow and works out which flow and version to run from its own settings, adding a step type that starts another flow chosen from the visitor's run, such as its owner or its answers, offering a visitor only the answers to a step that their earlier answers allow, filling in a step that has only one possible answer without asking it, skipping a step that does not apply to a visitor, letting an admin edit a value stored on one of the app's own records from a step's settings on the canvas, serving a host's flows from the app's own controller and routes, starting a visitor's run on a published version of a flow other than the live one, acting when a visitor finishes a flow, acting on the output a visitor's flow ended with, keeping a flow from being published while a step that starts another flow names a flow or version that cannot run or leads back to the flow it sits in, finding the run of another flow that a Flow step started, the run a waiting run is waiting on, and the run that started it, sending a visitor back to the run that started a flow once that flow ends, handling a run whose starting run was removed with its flow, handling a Flow step that cannot start its flow or whose flow ended with no output, taking one file or several from a visitor at a step, showing a step's recorded answer by a label the step type works out, and reading a run's recorded answers and question labels, including every answer ticked on a checklist and every visit's answer when a flow loops back to a question already asked — MUST BE USED instead of hand-rolling questionnaire steps, checkbox lists, file upload steps, branching logic, answer lists filtered by earlier answers, skipped questions, number comparisons, hard-coded setting options, copying a record's value into a flow and back, answer validation, polling or "come back later" pages, flow controllers or answer lookups.
|
|
3
|
+
description: Use PROACTIVELY for adding a step type to easy_flow flows (a step that asks the visitor something, takes several answers at once, computes a value from earlier answers, counts how many times an earlier step was answered so a loop can give up after a number of tries, picks the next branch, or holds the visitor until something outside the flow has happened), showing a step differently depending on the visitor's stored run, branching on what a visitor ticked on a checklist, moving a paused run on once what it waits for has happened, refusing a blank or invalid answer to a step with a message, offering an admin a step setting whose options are read from the app's own records, letting an admin pick another flow of the same host in a step's settings, adding a step type that starts another flow and works out which flow and version to run from its own settings, adding a step type that starts another flow chosen from the visitor's run, such as its owner or its answers, offering a visitor only the answers to a step that their earlier answers allow, filling in a step that has only one possible answer without asking it, skipping a step that does not apply to a visitor, letting an admin edit a value stored on one of the app's own records from a step's settings on the canvas, serving a host's flows from the app's own controller and routes, starting a visitor's run on a published version of a flow other than the live one, acting when a visitor finishes a flow, acting on the output a visitor's flow ended with, keeping a flow from being published while a step that starts another flow names a flow or version that cannot run or leads back to the flow it sits in, finding the run of another flow that a Flow step started, the run a waiting run is waiting on, and the run that started it, sending a visitor back to the run that started a flow once that flow ends, handling a run whose starting run was removed with its flow, handling a Flow step that cannot start its flow or whose flow ended with no output, taking one file or several from a visitor at a step, showing a step's recorded answer by a label the step type works out, and reading a run's recorded answers and question labels, including every answer ticked on a checklist and every visit's answer when a flow loops back to a question already asked — MUST BE USED instead of hand-rolling questionnaire steps, checkbox lists, file upload steps, branching logic, answer lists filtered by earlier answers, skipped questions, number comparisons, hard-coded setting options, copying a record's value into a flow and back, answer validation, retry counters, polling or "come back later" pages, flow controllers or answer lookups.
|
|
4
4
|
tools: Read, Write, Edit, Grep
|
|
5
5
|
scope: guided flows — versioned documents of steps and the connections between them, drawn on a canvas by an admin and run by a visitor one step at a time, with step types the host registers
|
|
6
6
|
---
|
|
@@ -9,7 +9,7 @@ This local follows the steps below exactly and invents none. Where a step names
|
|
|
9
9
|
|
|
10
10
|
## What easy_flow is
|
|
11
11
|
|
|
12
|
-
A Rails engine for flows an admin draws on a canvas and a visitor runs one step at a time. Each step is an instance of a step type. The engine ships
|
|
12
|
+
A Rails engine for flows an admin draws on a canvas and a visitor runs one step at a time. Each step is an instance of a step type. The engine ships ten: start (`:start`), end (`:terminal`, whose one setting is the output an admin writes for a flow that ends there), question (`:question`, a question with a list of answers of which the visitor picks one, which the admin can mark required so a blank answer is refused), checklist (`:checklist`, a question with a list of answers of which the visitor ticks any number, which the admin can mark required so a visitor who ticks nothing is refused), File upload (`:file_upload`, a question the visitor answers by choosing one file from a file upload control labelled with the question text, with an admin setting listing the accepted file types as comma-separated extensions such as `.pdf, .png`, which limits the visitor's file picker to those types and is shown under the control as `Accepts` followed by the list as the admin wrote it, such as `Accepts .pdf, .png`, which the admin can mark required so a visitor who chooses no file is refused, and whose recorded answer is the reference the host's file store returned for the file), three that pick a branch from an earlier answer with no code — condition (`:condition`, is or is not a chosen value), switch (`:switch`, follows the connection labelled with the answer) and compare (`:compare`, reads the answer as a number and checks it by more than, less than, at least or at most against an amount) — Count (`:count`, which acts without the visitor and records a whole number, how many visits to an earlier step the admin picks the run has recorded, counting only visits that gave the answer the admin picks or every visit when the admin picks none, reading that answer from the output the admin picks when the earlier step recorded several, named on the canvas `Count` followed by the earlier step's id and the answer, such as `Count tests failed`, and recording a new count under its own visit key each time a loop reaches it, so a compare step after it can end a loop once the count reaches an amount), and Flow (`:flow_step`, names another flow of the same host and the number of one of its versions, with one connection for each different output that version's End steps write, and named on the canvas by that flow's title and the version number, such as `Intake, version 2`). When a stored run stops at a Flow step, a run of the named flow is started on the named version, and the first run waits on the Flow step. When the second run ends with an output, that output is recorded in the first run at the Flow step, and the first run moves on along the connection labelled with that output. When the second run ends with no output, nothing is recorded and the first run stays waiting at the Flow step. On a question and on a checklist the admin can give each answer info, a longer explanation the visitor opens with an info button beside that answer. An admin may connect a step back to an earlier one, so a flow can ask the same question more than once, and each visit's answer is kept. A File upload step takes a file only in a flow the admin set to save each step. In a flow set to save on finish or to save nothing, a visitor who chooses a file is shown `A file can only be uploaded in a flow that saves its runs.` and cannot go on with it. Before writing a step type to ask for one answer or several, to take a file, to branch on an answer or a number, or to count the visits to an earlier step, ask the developer whether an admin placing one of the built-in types on the canvas is enough. None of condition, switch or compare reads a checklist's answer, so branching on what a visitor ticked takes a step type of the app's own that defines `route`. Use this local when the app needs a step type of its own, needs a host's flows on its own pages with its own behaviour when a visitor finishes, needs a visitor's earlier answers to decide which answers a later step offers, or needs to read what a visitor answered. It assumes easy_flow is already installed and a host is declared; if not, hand off to `easy_flow-install` first.
|
|
13
13
|
|
|
14
14
|
## Interface
|
|
15
15
|
|
|
@@ -33,7 +33,7 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
33
33
|
- It only picks which connection to follow — define `route`.
|
|
34
34
|
- It holds the visitor until something outside the flow has happened, such as a payment arriving or a reviewer approving — declare `waits_until`.
|
|
35
35
|
A type may both `process` and `route`. A type that does none of the four is passed through without stopping when a visitor reaches it.
|
|
36
|
-
2. Create the class in the app, for example `app/models/flow_steps/rating.rb`. The class name, underscored, is the type's id (`Rating` becomes `:rating`), and that id is stored in every flow that uses it, so it must not change after admins start using the type. It must not be one of the built-in ids `start`, `terminal`, `question`, `checklist`, `file_upload`, `condition`, `switch`, `compare` or `flow_step`:
|
|
36
|
+
2. Create the class in the app, for example `app/models/flow_steps/rating.rb`. The class name, underscored, is the type's id (`Rating` becomes `:rating`), and that id is stored in every flow that uses it, so it must not change after admins start using the type. It must not be one of the built-in ids `start`, `terminal`, `question`, `checklist`, `file_upload`, `condition`, `switch`, `compare`, `count` or `flow_step`:
|
|
37
37
|
|
|
38
38
|
```ruby
|
|
39
39
|
module FlowSteps
|
|
@@ -183,7 +183,7 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
183
183
|
Array(state[node.config["step"]]).include?(node.config["answer"])
|
|
184
184
|
end
|
|
185
185
|
```
|
|
186
|
-
- In a flow that loops, the first visit to a step is recorded under its id and each later visit under `<id>@<n>`, where `n` counts from 2. `route` is given the latest visit's answer under the plain step id. `process` and `waits_until` are given the answers as recorded, so the plain id holds the first visit's answer and later visits are under `<id>@2`, `<id>@3` and on. A `process` step reached again records its result under its own `<id>@<n>`. When a computing or waiting type reads an earlier step that can be asked again, ask the developer whether it should read the first visit or the latest.
|
|
186
|
+
- In a flow that loops, the first visit to a step is recorded under its id and each later visit under `<id>@<n>`, where `n` counts from 2. `route` is given the latest visit's answer under the plain step id. `process` and `waits_until` are given the answers as recorded, so the plain id holds the first visit's answer and later visits are under `<id>@2`, `<id>@3` and on. A `process` step reached again records its result under its own `<id>@<n>`. When a computing or waiting type reads an earlier step that can be asked again, ask the developer whether it should read the first visit or the latest. To end a loop after a number of visits, ask the developer whether a built-in Count step followed by a compare step is enough before writing a type that counts.
|
|
187
187
|
7. For a type that awaits input, write the partial named in `drawn_by`, for example `app/views/flow_steps/_rating.html.erb`. It receives the display object as `step`. It renders only the input, since the page supplies the form, the Next button and the Back button. The input must be named `answers[<step id>]`, or the answer is not recorded:
|
|
188
188
|
|
|
189
189
|
```erb
|
|
@@ -447,7 +447,7 @@ Use this when what a visitor answered earlier decides which answers a later step
|
|
|
447
447
|
## Conventions
|
|
448
448
|
|
|
449
449
|
- A step type's id comes from its class name or the id passed to `EasyFlow.step`, and it is stored in flow documents, so renaming the class or id breaks every flow that uses it.
|
|
450
|
-
- Never give a step type one of the built-in ids: `start`, `terminal`, `question`, `checklist`, `file_upload`, `condition`, `switch`, `compare`, `flow_step`.
|
|
450
|
+
- Never give a step type one of the built-in ids: `start`, `terminal`, `question`, `checklist`, `file_upload`, `condition`, `switch`, `compare`, `count`, `flow_step`.
|
|
451
451
|
- Register class-based step types inside `to_prepare`. A type registered anywhere else is lost on code reload in development.
|
|
452
452
|
- Registering a type does not put it in the palette of a host that names a list of offered step types without the type's id. Which step types a host offers is set through `easy_flow-install`, not here.
|
|
453
453
|
- A type that declares `ends_here` is in every host's palette, and a type that declares `begins_here` is in no host's palette.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: easy_flow-info
|
|
3
|
-
description: Use to learn what easy_flow offers — guided flows an admin draws on a canvas and a visitor runs one step at a time, versioned documents of steps and connections, flows that loop back to ask a step again, hosts and the step types each offers its admins, runs and the published version each starts on, and the output a flow gives when it ends, the built-in step types including questions and checklists that can require an answer and explain each answer behind an info button, file upload steps that hand a visitor's file to the app's file store and read it back by its name, and branching on an answer or comparing a number, Flow steps that name another flow, open its canvas when their card is clicked with a button back to the flow it was opened from, start a run of it for the same owner when a stored run reaches them, are flagged when the flow or version they name cannot run or leads back to the flow they sit in, let the waiting run name that inner run, move that run on along the output it ends with, and fail with an error naming the step when its version was taken out of service or its inner run ended with no output, removing a flow and why it is refused while a waiting run depends on it, step types the host app registers, including ones that start another flow and work out which flow and version to run from their own settings and are named after that flow, or choose it from the run they are in, the answers a host allows a step in a run and the steps it fills in or passes over, the checks they make on an answer, what a step shows a visitor and how that can depend on the visitor's run, and steps that hold a run until something outside the flow has happened, and the settings an admin fills in, including picks whose options come from the app's data and settings kept on one of the app's own records.
|
|
3
|
+
description: Use to learn what easy_flow offers — guided flows an admin draws on a canvas and a visitor runs one step at a time, versioned documents of steps and connections, flows that loop back to ask a step again, hosts and the step types each offers its admins, runs and the published version each starts on, and the output a flow gives when it ends, the built-in step types including questions and checklists that can require an answer and explain each answer behind an info button, file upload steps that hand a visitor's file to the app's file store and read it back by its name, and branching on an answer or comparing a number, Count steps that count how often an earlier step was answered so a loop can give up after a number of tries, Flow steps that name another flow, open its canvas when their card is clicked with a button back to the flow it was opened from, start a run of it for the same owner when a stored run reaches them, are flagged when the flow or version they name cannot run or leads back to the flow they sit in, let the waiting run name that inner run, move that run on along the output it ends with, and fail with an error naming the step when its version was taken out of service or its inner run ended with no output, removing a flow and why it is refused while a waiting run depends on it, step types the host app registers, including ones that start another flow and work out which flow and version to run from their own settings and are named after that flow, or choose it from the run they are in, the answers a host allows a step in a run and the steps it fills in or passes over, the checks they make on an answer, what a step shows a visitor and how that can depend on the visitor's run, and steps that hold a run until something outside the flow has happened, and the settings an admin fills in, including picks whose options come from the app's data and settings kept on one of the app's own records.
|
|
4
4
|
tools: Read
|
|
5
5
|
scope: guided flows — versioned documents of steps and the connections between them, drawn on a canvas by an admin and run by a visitor one step at a time, with step types the host registers
|
|
6
6
|
---
|
|
@@ -11,7 +11,7 @@ This local explains easy_flow and the words it uses. It makes no changes and giv
|
|
|
11
11
|
|
|
12
12
|
easy_flow is a Rails engine for guided, branching flows. An admin builds a flow on a canvas by placing steps and connecting them, previews it, and publishes it. A visitor then walks the published flow one step at a time, and each answer decides which step comes next.
|
|
13
13
|
|
|
14
|
-
Reach for it when an app needs a questionnaire, an intake form, or any decision path that an admin should be able to change without a deploy. The engine ships a start step, an end step, a question step, a checklist step, a file upload step, three steps that pick a branch from earlier answers, and a Flow step that names another flow. Anything else a flow needs to ask, do, or wait for is a step type the app declares itself.
|
|
14
|
+
Reach for it when an app needs a questionnaire, an intake form, or any decision path that an admin should be able to change without a deploy. The engine ships a start step, an end step, a question step, a checklist step, a file upload step, three steps that pick a branch from earlier answers, a Count step that counts earlier answers, and a Flow step that names another flow. Anything else a flow needs to ask, do, or wait for is a step type the app declares itself.
|
|
15
15
|
|
|
16
16
|
## Interface
|
|
17
17
|
|
|
@@ -32,6 +32,7 @@ easy_flow declares no commands of its own for this local. Its surface is split b
|
|
|
32
32
|
- To explain an answer to the visitor, no code is needed: an admin fills in that answer's info on a question or checklist step.
|
|
33
33
|
- To start another flow from inside a flow, no code is needed: an admin places a Flow step on the canvas and picks that flow and its version. The connections leaving the step are labelled with the ways that flow can end, and a stored run moves on along the one named after the output its inner run ended with. Clicking the step's card opens the canvas of the flow it runs, and that canvas has a button back to the flow it was opened from. A Flow step cannot start the flow it sits in, directly or through other flows.
|
|
34
34
|
- To ask a step again, such as repeating a question until the visitor says they are done, no code is needed: an admin connects a later step back to an earlier one on the canvas.
|
|
35
|
+
- To end a loop after a number of tries, no code is needed: an admin places a Count step after the step being repeated and a Compare step after the Count step, and connects the Compare step's false connection back to the repeated step.
|
|
35
36
|
- If the question is only what a word below means, this page is the answer.
|
|
36
37
|
|
|
37
38
|
## Conventions
|
|
@@ -54,7 +55,7 @@ easy_flow declares no commands of its own for this local. Its surface is split b
|
|
|
54
55
|
- **Flow output** — the text an admin writes into the output setting of an End step, given as the result of a stored run that has reached that step. A flow may hold several End steps with a different output on each, so the output says which way the flow ended. A run that has not reached an End step, or that ended on one whose output was left blank, gives no output.
|
|
55
56
|
- **Question** — the built-in step type that asks the visitor: a question text, an optional category, a yes-or-no required setting, and a list of answers, each with a value, a label, a weight, a hint and an info. The visitor picks one answer, and that answer's value is recorded.
|
|
56
57
|
- **Checklist** — the built-in step type that asks the visitor to tick any number of answers: a question text, a yes-or-no required setting, and a list of answers, each with a value, a label and an info. The list of ticked values is recorded, and a checklist left with nothing ticked records an empty list.
|
|
57
|
-
- **File upload** — the built-in step type that asks the visitor for one file: a question text, the accepted file types, and a yes-or-no required setting. The accepted file types are a comma-separated list of extensions, such as `.pdf, .png`, and an empty list accepts any file. A file whose extension is not on the list is refused with a message naming the accepted types, such as "Choose a .pdf or .png file.", and is not handed to the file store. A required file upload left empty is refused with "Choose a file to go on." A file can only be uploaded in a flow that keeps a stored run, so a flow that carries its answers in the page refuses one with "A file can only be uploaded in a flow that saves its runs."
|
|
58
|
+
- **File upload** — the built-in step type that asks the visitor for one file: a question text, the accepted file types, and a yes-or-no required setting. The accepted file types are a comma-separated list of extensions, such as `.pdf, .png`, and an empty list accepts any file. The visitor sees a styled file upload control labelled with the question text. When accepted file types are set, the visitor's file picker offers only those types, and a line under the control reads "Accepts" followed by the list exactly as the admin wrote it, such as "Accepts .pdf, .png". A file whose extension is not on the list is refused with a message naming the accepted types, such as "Choose a .pdf or .png file.", and is not handed to the file store. A required file upload left empty is refused with "Choose a file to go on." A file can only be uploaded in a flow that keeps a stored run, so a flow that carries its answers in the page refuses one with "A file can only be uploaded in a flow that saves its runs."
|
|
58
59
|
- **File store** — the object the app sets to keep uploaded files. It takes an accepted file, keeps it, and returns a reference, and that reference is what the run records as the step's answer. When a step's answer is sent as a list holding several files, such as from a step type of the app's own, each file is handed to the store and the run records the list of references. It also gives the name of the file a reference points to, which is what the read-back shows. When a file is accepted and the app has set no file store, the step fails with an error saying a file store must be set.
|
|
59
60
|
- **Hint** — a short line of text shown under an answer's label on a question step.
|
|
60
61
|
- **Info** — a longer explanation of one answer on a question or checklist step. The visitor opens it with an info button beside that answer, and an answer with no info has no button.
|
|
@@ -64,6 +65,7 @@ easy_flow declares no commands of its own for this local. Its surface is split b
|
|
|
64
65
|
- **Condition** — a built-in branching step that checks whether an earlier step's answer is, or is not, a chosen value, and follows the true or the false connection.
|
|
65
66
|
- **Switch** — a built-in branching step that follows the connection labelled with an earlier step's answer.
|
|
66
67
|
- **Compare** — a built-in branching step that reads an earlier step's answer as a number and checks it against an amount by more than, less than, at least or at most, then follows the true or the false connection. When the earlier step recorded several outputs, the admin picks which one. An answer that is missing or is not a number decides false.
|
|
68
|
+
- **Count** — a built-in step that acts on its own and records a whole number: how many visits to an earlier step the run has recorded. When the admin picks an answer, only visits that gave that answer are counted, and when the admin picks none, every visit is counted. When the earlier step recorded several outputs, the admin picks which one the answer is read from. On the canvas the step is named "Count" followed by the earlier step and the answer it counts, such as "Count tests failed". Each visit to a Count step in a loop records a new count under its own visit key, so a Compare step after it can end the loop once the count reaches an amount.
|
|
67
69
|
- **Flow step** — a built-in step that names another flow and the number of one of its versions. The admin picks the flow from the same host's flows, listed by title as the admin's list of flows shows them. The step has one connection for each different output the End steps of that version write, and none when no flow or version is picked or no End step there has an output. On the canvas its card is named after the flow's title and the version, such as "Onboarding, version 2", and is marked "Runs a flow". Once a flow is picked, clicking the card opens that flow's canvas, and the card's Settings button opens the step's own settings instead. A canvas opened from a Flow step's card shows a "Back to" button named after the title of the flow it was opened from, or its slug when it has no title, which returns to that flow's canvas. The button only appears when that flow belongs to the same host, and to the same owner when the host has one. While the admin is connecting steps, clicking the card picks it as the connection's target. A run that reaches a Flow step stops there. When the run is a stored run, it starts one inner run of the named flow on the picked version. A run that carries its answers in the page, and an admin's preview, stop at the Flow step, start no run, and never move past it.
|
|
68
70
|
- **Unrunnable Flow step** — a Flow step whose picked flow or version cannot be run. Its card shows "missing flow" when no flow is picked or the picked flow no longer exists, and "unrunnable version" when the picked flow has no version with that number or that version is a draft, retired or withdrawn. These are always on, unlike the optional checks below, and the flow holding such a step cannot be saved as a new version or published until it is fixed.
|
|
69
71
|
- **Circular Flow step** — a Flow step that leads back to the flow it sits in. That is either a Flow step naming its own flow, or one naming a flow whose picked version holds a Flow step that leads back the same way, through any number of flows. Each flow along the way is read at the version its Flow step picked. Its card shows "circular", and like an unrunnable Flow step this is always on and keeps the flow from being saved as a new version or published until it is fixed.
|
|
@@ -80,7 +82,7 @@ easy_flow declares no commands of its own for this local. Its surface is split b
|
|
|
80
82
|
- **Run** — one visitor's pass through a flow. A run may belong to one of the app's own records, its owner, which the app sets. A run is pinned to the version it started on, so publishing a new version does not change a run already under way. A run starts on the live version unless the app chooses another of the flow's published versions. A run is refused when the chosen version is a draft, is retired or withdrawn, or belongs to another flow. It records each answer by visit, and going back discards the last answer on the path.
|
|
81
83
|
- **Stored run** and **carried answers** — the two ways a visitor's progress is held. A stored run is saved by the app and found again by its id. A flow that keeps nothing carries the answers given so far in the page itself and sends them along with each step.
|
|
82
84
|
- **Answers** — the recorded state of a run, keyed by visit. The next step is always worked out from these answers and the connections in the pinned version.
|
|
83
|
-
- **Loop** — a connection that leads back to a step the run has already passed, so that step is visited again. Branching steps read the most recent answer to a step, so a loop ends when an answer sends the run down a different connection.
|
|
85
|
+
- **Loop** — a connection that leads back to a step the run has already passed, so that step is visited again. Branching steps read the most recent answer to a step, so a loop ends when an answer sends the run down a different connection. Reading a finished run again follows the same connections it took at the time, since each branching step reads the answers as they stood at that visit.
|
|
84
86
|
- **Visit** — one time a run reaches a step. The first visit is keyed by the step id alone, and each later visit is keyed by the step id, an `@`, and the visit number, such as `size@2`. Every visit's answer is kept, and a finished run lists each one.
|
|
85
87
|
- **Stopped loop** — a run that comes back to a step with no new answer given since its last visit there ends at that point rather than cycling forever. Only answers the visitor gives count, so a loop made only of steps that act on their own stops the first time it comes round.
|
|
86
88
|
- **Reserved `@`** — a step id may not contain `@`, since that mark numbers later visits. A flow holding such a step id is reported as invalid.
|
|
@@ -25,7 +25,7 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
25
25
|
## How to use it
|
|
26
26
|
|
|
27
27
|
1. Confirm the app has Keystone UI installed (`keystone_ui` in the Gemfile). easy_flow's controllers use its helpers and it is not pulled in by easy_flow. If it is missing, stop and hand off to the `keystone_ui-install` local before continuing.
|
|
28
|
-
2. Read the `keystone_ui` version in the app's `Gemfile.lock`. easy_flow's visitor pages pass each answer's info text to Keystone UI's radio cards and checkbox rows, and easy_flow is built against `keystone_ui` 0.27.0. If the app's version is older, ask the developer whether to run `bundle update keystone_ui` before continuing.
|
|
28
|
+
2. Read the `keystone_ui` version in the app's `Gemfile.lock`. easy_flow's visitor pages pass each answer's info text to Keystone UI's radio cards and checkbox rows and draw a File upload step with Keystone UI's file upload control, and easy_flow is built against `keystone_ui` 0.27.0. If the app's version is older, ask the developer whether to run `bundle update keystone_ui` before continuing.
|
|
29
29
|
3. Add `gem "easy_flow"` to the host's `Gemfile` and run `bundle install`.
|
|
30
30
|
4. Run `bin/rails easy_flow:install:migrations`, then `bin/rails db:migrate`. This writes six migrations into `db/migrate` and updates `db/schema.rb`.
|
|
31
31
|
5. Ask the developer which hosts the app needs. A host is one part of the app that owns its own set of flows, and one host never sees another's flows. Ask for each host's name and the path it is served under.
|
|
@@ -45,7 +45,7 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
45
45
|
host.visitor_authorization_method = :easy_flow_visitor_permitted?
|
|
46
46
|
host.refusal_method = :refuse_flow
|
|
47
47
|
host.owner_method = :current_account
|
|
48
|
-
host.offers = %i[question checklist file_upload condition switch compare flow_step]
|
|
48
|
+
host.offers = %i[question checklist file_upload condition switch compare count flow_step]
|
|
49
49
|
end
|
|
50
50
|
```
|
|
51
51
|
|
|
@@ -55,7 +55,7 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
55
55
|
- `visitor_authorization_method` — a method on the base controller, called with the flow, returning true when the visitor may run it. With none set, every visitor is refused.
|
|
56
56
|
- `refusal_method` — a method on the base controller, called with the refusal error when a visitor is refused or a flow is unpublished or withdrawn. With none set, the response is `404 Not Found`.
|
|
57
57
|
- `owner_method` — a method on the base controller, called with no arguments, returning the record whose flows the current request works with, such as the signed-in account. When set, the admin pages list, create and edit only that record's flows, a visitor runs only that record's flows, and two records may each hold a flow with the same slug. With none set, every flow in the host is shared by everyone who reaches it. Ask the developer whether each host's flows belong to one record or are shared.
|
|
58
|
-
- `offers` — the step types this host's admins can add from the canvas palette, as a list of step type names. With none set, every registered step type is offered. The engine's own names are `question`, `checklist`, `file_upload`, `condition`, `switch`, `compare` and `flow_step`, `file_upload` being the File upload step, which needs the file store from step 10, and `flow_step` being the Flow step, which names one of the same host's flows. A step type the app declares is named by the id it was declared with, or after its class when it is a step class, so `Steps::Notify` is `notify`. The End step is offered whether it is listed or not, and the Start step is never offered. Ask the developer which step types each host should offer.
|
|
58
|
+
- `offers` — the step types this host's admins can add from the canvas palette, as a list of step type names. With none set, every registered step type is offered. The engine's own names are `question`, `checklist`, `file_upload`, `condition`, `switch`, `compare`, `count` and `flow_step`, `file_upload` being the File upload step, which needs the file store from step 10, `count` being the Count step, which counts how often an earlier step was answered, and `flow_step` being the Flow step, which names one of the same host's flows. A step type the app declares is named by the id it was declared with, or after its class when it is a step class, so `Steps::Notify` is `notify`. The End step is offered whether it is listed or not, and the Start step is never offered. Ask the developer which step types each host should offer.
|
|
59
59
|
|
|
60
60
|
Each method named here must exist on the base controller. Ask the developer to point at it or write it. Do not invent its logic.
|
|
61
61
|
8. Mount the engine in `config/routes.rb`, once per host. The host name in `defaults` must match a name declared in step 7. When there is more than one mount, give each an `as:` name:
|
|
@@ -77,7 +77,7 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
77
77
|
- The visitor's answer must be submitted as `answers[<%= step.id %>]`. Always build the field name from `step.id` and never from a fixed id. When a flow loops back and asks a question again, `step.id` names that visit, so each visit's answer is stored apart.
|
|
78
78
|
- It replaces the engine's drawing of every step whose type names no partial, so it draws each answer's hint and info itself or they are not shown.
|
|
79
79
|
- It is not used for a checklist step. A checklist is always drawn by the engine as one checkbox per answer, each with an info button when the answer has info text, and the visitor may tick several.
|
|
80
|
-
- It is not used for a File upload step. A File upload step is always drawn by the engine as
|
|
80
|
+
- It is not used for a File upload step. A File upload step is always drawn by the engine as Keystone UI's file upload control, labelled with the step's question text. When the step has accepted file types, the visitor's file picker offers only those types, and a line under the control reads "Accepts" followed by the types as the admin wrote them.
|
|
81
81
|
10. Ask the developer whether any host will offer the File upload step, and if so, where the app keeps uploaded files. The engine keeps no file itself and has no default store. Ask the developer to point at the app's store or write one. Do not pick a storage service for them. Set it in the initializer:
|
|
82
82
|
|
|
83
83
|
```ruby
|
|
@@ -101,6 +101,7 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
101
101
|
- After publishing a flow with a checklist, check that a visitor can tick several answers and go on, and that a checklist marked required refuses to go on with nothing ticked.
|
|
102
102
|
- After upgrading easy_flow, run `bin/rails easy_flow:install:migrations` again and then `bin/rails db:migrate`. Only migrations the app does not already have are copied.
|
|
103
103
|
- After setting a host's `owner_method`, check that two different owners each see only their own flows on `<mount path>/manage/flows`.
|
|
104
|
+
- After install, check that a Count step placed on the canvas, once its earlier step and answer are picked, is named "Count" followed by that step and that answer. It needs no setting in the initializer beyond being listed in a host's `offers` when that host sets `offers`.
|
|
104
105
|
- After install, check that a Flow step placed on the canvas offers the host's flows by title as its flow setting. With a host's `owner_method` set, it offers only that owner's flows. It needs no setting in the initializer.
|
|
105
106
|
- After choosing a flow on a Flow step, check that its canvas card reads "Runs a flow", that clicking the card opens the chosen flow's canvas under the same mount path, and that its Settings button opens the step's settings instead.
|
|
106
107
|
- After opening a chosen flow's canvas from a Flow step's card, check that its header shows a "Back to" button naming the flow it was opened from, by title or by slug when it has no title, and that the button opens that flow's canvas. A canvas opened from the flow list shows no such button.
|
|
@@ -118,6 +119,7 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
|
|
|
118
119
|
- After setting `EasyFlow.file_store`, publish a flow with a File upload step whose "What this keeps of a run" detail is "Every answer as it is given", upload a file as a visitor, and check that the completion page shows the name the store gives it.
|
|
119
120
|
- A File upload step takes a file only in a flow that keeps every answer as it is given. In a flow that keeps nothing or keeps the run only once it finishes, the visitor is told "A file can only be uploaded in a flow that saves its runs." and cannot go on with a file chosen.
|
|
120
121
|
- A File upload step's "Accepted file types" setting is a comma-separated list of extensions, such as `.pdf, .png`. A file of another kind is refused with a message naming the accepted kinds and is never passed to the file store.
|
|
122
|
+
- After publishing a flow with a File upload step whose accepted file types are set, check that the visitor's page shows the styled file upload control labelled with the question text, and the line "Accepts .pdf, .png" or the step's own list under it. If the page raises an undefined method error for `ui_file_upload`, compare the app's `keystone_ui` version with the one in step 2.
|
|
121
123
|
- After setting a host's `offers`, check that the canvas palette on that host's `<mount path>/manage/flows` lists only those step types and End.
|
|
122
124
|
- Taking a step type off a host's `offers` removes it from the palette only. Steps of that type already in the host's flows stay in them and keep running.
|
|
123
125
|
- The initializer runs once at boot, so a change to it needs a server restart.
|
data/the_local/interface.yml
CHANGED
|
@@ -39,6 +39,7 @@ sources:
|
|
|
39
39
|
- app/models/easy_flow/steps/question.rb
|
|
40
40
|
- app/models/easy_flow/steps/checklist.rb
|
|
41
41
|
- app/models/easy_flow/steps/file_upload.rb
|
|
42
|
+
- app/models/easy_flow/count.rb
|
|
42
43
|
- app/models/easy_flow/step_type.rb
|
|
43
44
|
- app/models/easy_flow/choice.rb
|
|
44
45
|
- app/jobs/easy_flow/advance_parent_job.rb
|
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.
|
|
4
|
+
version: 0.17.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- tylercschneider
|
|
@@ -94,6 +94,7 @@ files:
|
|
|
94
94
|
- app/models/easy_flow/chosen_flow.rb
|
|
95
95
|
- app/models/easy_flow/compare.rb
|
|
96
96
|
- app/models/easy_flow/condition.rb
|
|
97
|
+
- app/models/easy_flow/count.rb
|
|
97
98
|
- app/models/easy_flow/definition.rb
|
|
98
99
|
- app/models/easy_flow/digest.rb
|
|
99
100
|
- app/models/easy_flow/document.rb
|