Skip to content

Commit

Permalink
Allow multiple flows w/in one session (#390)
Browse files Browse the repository at this point in the history
* Adds ability for use to work through multiple flows at once, storing each flow's submission data in the session.
* Move UserFileRepositoryService into FormFlowController
* Add user files to model in screen controller
* Add flow as a path variable for download endpoints
* Updates SubmissionRepositoryServer.save() to return a new submission
object, instead of just the id.
* Adds journey test for file uploads that cross flows.

Co-authored-by: Chibuisi Enyia <cenyia@codeforamerica.org>
Co-Authored-By: Alex Gonzalez; agonzalez@codeforamerica.org
  • Loading branch information
bseeger and enyia21 authored Oct 13, 2023
1 parent ddcdbef commit bd0e116
Show file tree
Hide file tree
Showing 44 changed files with 1,638 additions and 423 deletions.
133 changes: 83 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ Table of Contents
* [Configuration Details](#configuration-details)
* [Environment Variables](#environment-variables)
* [Application Configuration](#application-configuration)
* [Actuator Endpoints](#actuator-endpoints)
* [flows-config.yaml file](#flows-configyaml-file)
* [Flow and Subflow Configuration](#flow-and-subflow-configuration)
* [Screens](#screens)
* [Defining Subflows](#defining-subflows)
Expand All @@ -81,9 +79,9 @@ Table of Contents
* [How to contribute](#how-to-contribute)
* [Maintainer information](#maintainer-information)

A Spring Boot Java library that provides a framework for developing **form flow** based applications.
The intention is to speed up the creation of web applications that are a series of forms that
collect input from users.
A Spring Boot Java library that provides a framework for developing **form flow** based
applications. The intention is to speed up the creation of web applications that are a series of
forms that collect input from users.

The library includes tooling for:

Expand Down Expand Up @@ -242,8 +240,8 @@ to add another.

#### Delete Confirmation Screen

This screen appears when a user selects `delete` on an iteration listed on the review screen. It asks
the user to confirm their deletion before submitting the actual deletion request to the server.
This screen appears when a user selects `delete` on an iteration listed on the review screen. It
asks the user to confirm their deletion before submitting the actual deletion request to the server.

This page is not technically part of the subflow and as such, does not need to be denoted
with `subflow: subflowName` in the `flows-config.yaml`.
Expand Down Expand Up @@ -302,7 +300,8 @@ form flow configuration file. They are generally used to determine template or p

Conditions are Java objects that implement the `Condition`
[interface](https://github.com/codeforamerica/form-flow/blob/main/src/main/java/formflow/library/config/submission/Condition.java)
. As conditions are called with the Submission object, the instance variable `inputData` is available to them.
. As conditions are called with the Submission object, the instance variable `inputData` is
available to them.

Here is a simple condition that looks at data in the submission to see if the email provided is a
Google address.
Expand Down Expand Up @@ -462,11 +461,10 @@ see [Hibernate's documentation.](https://docs.jboss.org/hibernate/stable/validat

Note that our implementation does not make a field required, unless `@NotEmpty`, `@NotBlank`, or
`@NotNull` is used. If a validation annotation such as `@Email` is used, it will not
actually validate the annotated input unless a user actually enters a value for that input. If you use
`@Email` and `@NotBlank` together, that causes both validations to run even if the user did not
enter a value,
validating both that they need to enter a value due to `@NotBlank` and because the blank value needs
to be a validly formatted email address due to `@Email`.
actually validate the annotated input unless a user actually enters a value for that input. If you
use `@Email` and `@NotBlank` together, that causes both validations to run even if the user did not
enter a value, validating both that they need to enter a value due to `@NotBlank` and because the
blank value needs to be a validly formatted email address due to `@Email`.

### Custom Annotations

Expand Down Expand Up @@ -1183,8 +1181,7 @@ The address fragment has two required parameters, `validate` and `inputName`.
- `validate` is a boolean value that determines whether the address should be validated by Smarty
- `inputName` is the name that will be associated with all of the above inputs by being used as a
prefix in their input's name. For example, if the `inputName` is `homeAddress` then the
corresponding
inputs will
corresponding inputs will
be `homeAddressStreetAddress1`, `homeAddressStreetAddress2`, `homeAddressCity`, `homeAddressState`,
and `homeAddressZipCode`.

Expand All @@ -1194,12 +1191,9 @@ parameters: `streetAddressHelpText`, `streetAddress2HelpText`, `cityHelpText`, `
These will pass helper text to each specific field.

Please note that when using the address fragment you will need to create corresponding fields in
your
flow inputs class for each of the above-mentioned inputs created by the fragment. For example, if
your
address fragments input name is `mailingAddress`, then you will need to create the following fields
in
your flow inputs class:
your flow inputs class for each of the above-mentioned inputs created by the fragment. For example,
if your address fragments input name is `mailingAddress`, then you will need to create the following
fields in your flow inputs class:

```
String mailingAddressStreetAddress1;
Expand Down Expand Up @@ -2204,8 +2198,7 @@ starting a
session. If no HttpSession has been established or a session lacks an appropriate Submission id,
a client will be returned to the index page of an application.

⚠️ __It is set to be the last interceptor run by any
application using Form Flow Library.__
⚠️ __It is set to be the last interceptor run by any application using Form Flow library.__

#### Configuration

Expand Down Expand Up @@ -2328,7 +2321,7 @@ the [Spring.io documentation](https://docs.spring.io/spring-boot/docs/current/re
It is expected that this file will be located within the application that is using this form flow
library.

There are a few properties that the Form Flow Library will look for in the `application.yaml`
There are a few properties that the Form Flow library will look for in the `application.yaml`
file.

```yaml
Expand All @@ -2354,18 +2347,20 @@ form-flow:

We are moving towards using a [custom theme](https://codeforamerica.github.io/uswds/dist/) of
the [US Web Design System (USWDS)](https://designsystem.digital.gov/). Enabling this
property will set template resolution to use USWDS styling in place of Honeycrisp. The USWDS
template location will become the default for your application, pulling USWDS styles, templates and fragments
in place of Honeycrisp ones. The USWDS file path will be `/resources/cfa-uswds-templates/`. You can
property will set template resolution to use USWDS styling in place of Honeycrisp. The USWDS
template location will become the default for your application, pulling USWDS styles, templates and
fragments
in place of Honeycrisp ones. The USWDS file path will be `/resources/cfa-uswds-templates/`. You can
override templates and fragments in this path by placing a file with the same name and path in your
application. For example, placing a file at `/resources/cfa-uswds-templates/fragments/example.html`
application. For example, placing a file at `/resources/cfa-uswds-templates/fragments/example.html`
would override the fragment with the same name in the USWDS fragments folder.

You can view all the USWDS templates and fragments in the [USWDS templates folder](https://github.com/codeforamerica/form-flow/tree/main/src/main/resources/cfa-uswds-templates).
You can view all the USWDS templates and fragments in
the [USWDS templates folder](https://github.com/codeforamerica/form-flow/tree/main/src/main/resources/cfa-uswds-templates).

| Property | Default | Description |
|--------------------------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------|
| `form-flow.design-system.name` | none | Can use `cfa-uswds` to enable the CfA USWDS design system assets and templates. Otherwise Honeycrisp assets and templates are used. |
| Property | Default | Description |
|--------------------------------|---------|-------------------------------------------------------------------------------------------------------------------------------------|
| `form-flow.design-system.name` | none | Can use `cfa-uswds` to enable the CfA USWDS design system assets and templates. Otherwise Honeycrisp assets and templates are used. |
|

#### File upload properties
Expand Down Expand Up @@ -2424,7 +2419,7 @@ Spring Boot provides a module,
called [`spring-boot-starter-actuator`](https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints),
that will expose endpoints that will allow you to monitor and interact with your application.

**While these are very powerful, they can also reveal sensitive information about your
**⚠️ While these are very powerful, they can also reveal sensitive information about your
application. They are a huge security concern.**

It's best to disable them in production and demo environments, or just leave the `health` and
Expand Down Expand Up @@ -2452,27 +2447,39 @@ actuator endpoints.
* [Production-ready Features](https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints)
* [Actuator API](https://docs.spring.io/spring-boot/docs/3.1.2/actuator-api/htmlsingle)

### flows-config.yaml file

### Flow and Subflow Configuration

Flows are defined in a file specified in the `application.yaml` file. The library will look for
the `form-flow.path` property. If that property is not set, the default file it will look for is
named `flows-config.yaml`.
#### flows-config.yaml file

The `flows-config.yaml` file contains the core flow through screens of the application.
It will contain a list of screens in your application as well as any conditions or actions
relating to them. It will also detail out subflow information as well as landmark pages.

The system will, by default, look for a file with the name `flows-config.yaml`
in `src/main/resources`. You can have the library load a file with a different name by including
the property `form-flow.path` in the `application.yaml` file. The library will then load the
specified file instead and pull the flow configuration from there.

To configure a flow, create a `flow-config.yaml` in your app at `src/main/resources`.
#### flows-config.yaml basic configuration

To configure a flow, create a `flows-config.yaml` in your app at `src/main/resources`.

You can define multiple flows by
[separating them with `---`](https://docs.spring.io/spring-boot/docs/1.2.0.M1/reference/html/boot-features-external-config.html#boot-features-external-config-multi-profile-yaml)
.

At it's base a flow as defined in yaml has a name, a flow object, and a collection of screens, their
next screens, any conditions for navigation between those screens, and optionally one or more
subflows.
In the yaml file, every flow described will have:

#### form-flow.yaml basic configuration
* a `name`
* a `flow`, which is essentially the set of screens in the application. Each screen could
have:
* next screens
* [conditions](#conditions) to apply to next screen flow
* [actions](#actions) to apply to data
* a `subflows` section, if any of the screens are part of a subflow
* a [`landmarks`](#landmarks) section

A basic flow configuration could look like this:
A basic form flow configuration file might look like this:

```yaml
name: exampleFlow
Expand All @@ -2481,6 +2488,7 @@ flow:
nextScreens:
- name: secondScreen
secondScreen:
beforeSaveAction: cleanData
nextScreens:
- name: thirdScreen
- name: otherScreen
Expand All @@ -2493,14 +2501,37 @@ flow:
- name: success
success:
nextScreens: null
landmarks:
firstScreen: firstScreen
___
name: someOtherFlow
flow:
otherFlowScreen:
```

You can have autocomplete and validation for flows-config by connecting your IntelliJ to the
flows-config-schema.json [as described here](#connect-flows-config-schema).
You can have IntelliJ do autocomplete and validation for fields in the `flows-config.yaml` file by
configuring IntelliJ to use
the `flows-config-schema.json`, [as described here](#connect-flows-config-schema).

#### Multiple Flows

The Form Flow library is able to accommodate multiple form flows in one application. For example,
one could create a signup form in one flow and use a separate flow for collecting documentation from
a user at a later time.
The [Form Flow Starter App](https://github.com/codeforamerica/form-flow-starter-app) has two
separate flows.

It's not recommended to allow users to work through more than one flow at once. The design of the
Form Flow library is that a user would complete one flow before working with a separate flow.

However, it is not always possible to keep the flows separate and in cases where users do cross from
one flow to another, we will keep the data for both flows. We do this by creating a
`Submission` for each flow the user has visited. Regardless of whether the user completed
any one flow, the `Submission` for each flow will be stored in the database.

**⚠️ If your screen flow has users crossing flows, you need to ensure that you provide a reentry
point
to go back to the other flow. Otherwise, the flows may not get completed properly.**

### Screens

Expand Down Expand Up @@ -2531,7 +2562,7 @@ What do you need to do to create a subflow?
(e.g. Ubi.java in the starter app)
- Define `screen` templates in `resources/templates/<flow-name>`

Example `flow-config.yaml` with a docs subflow
Example `flows-config.yaml` with a docs subflow

```yaml
name: docFlow
Expand Down Expand Up @@ -2604,7 +2635,8 @@ There are spots in the templates where the `T` operator is used.

### Logging

Form Flow adds the following attributes to the [Mapped Diagnostic Context](https://logback.qos.ch/manual/mdc.html):
Form Flow adds the following attributes to
the [Mapped Diagnostic Context](https://logback.qos.ch/manual/mdc.html):

| Attribute | Description |
|---------------|----------------------------------------------------------------------------------------------------------------------------|
Expand All @@ -2614,10 +2646,11 @@ Form Flow adds the following attributes to the [Mapped Diagnostic Context](https
| submissionId | The ID of the Submission object - see https://github.com/codeforamerica/form-flow#submission-object |
| xForwardedFor | The X-Forwarded-For request header - see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For |

These attributes can be displayed in the logs by configuring the log format as described in the above document. For an example that exposes the entire Mapped Diagnostic Context (MDC) in JSON-formatted logs,
These attributes can be displayed in the logs by configuring the log format as described in the
above document. For an example that exposes the entire Mapped Diagnostic Context (MDC) in
JSON-formatted logs,
see https://github.com/codeforamerica/form-flow-starter-app/blob/main/src/main/resources/logback-spring.xml.


### Library Details

### Publishing
Expand Down
Loading

0 comments on commit bd0e116

Please sign in to comment.