|
1 | | -# forms-runner |
2 | | - |
3 | | -Citizen-facing forms using a config driven Node application. |
4 | | - |
5 | | -This repository is forked from [the old Defra digital form builder](https://github.com/DEFRA/digital-form-builder). |
6 | | -These projects has been adapted to run several configurations on a single instance. |
7 | | - |
8 | | -> DEFRA's digital form builder is a metadata-driven framework that builds on our robust, |
9 | | -> enterprise backend tech stack and the new gov.uk frontend Design System and allows form based gov.uk sites to be easily |
10 | | -> built using a graphical design tool. |
11 | | -
|
12 | | -The designer is no longer a plugin and is responsible for running itself on default port 3000. |
13 | | - |
14 | | -- [Requirements](#requirements) |
15 | | - - [Node.js](#nodejs) |
16 | | -- [Local development](#local-development) |
17 | | - - [Setup](#setup) |
18 | | - - [Development](#development) |
19 | | - - [Local JSON API](#local-json-api) |
20 | | - - [Production](#production) |
21 | | - - [npm scripts](#npm-scripts) |
22 | | - - [File Uploads with Local Development](#file-uploads-with-local-development) |
23 | | -- [Docker](#docker) |
24 | | - - [Development Image](#development-image) |
25 | | - - [Production Image](#production-image) |
26 | | -- [Licence](#licence) |
27 | | - - [About the licence](#about-the-licence) |
28 | | - |
29 | | -## Requirements |
30 | | - |
31 | | -### Node.js |
32 | | - |
33 | | -Please install [Node.js](http://nodejs.org/) `>= v20`. You will find it |
34 | | -easier to use the Node Version Manager [nvm](https://github.com/creationix/nvm) |
35 | | - |
36 | | -To use the correct version of Node.js for this application, via nvm: |
37 | | - |
38 | | -```bash |
39 | | -$ cd forms-runner |
40 | | -$ nvm use |
41 | | -``` |
42 | | - |
43 | | -## Local development |
44 | | - |
45 | | -for local developers |
46 | | - |
47 | | -### Setup |
48 | | - |
49 | | -Install application dependencies: |
50 | | - |
51 | | -```bash |
52 | | -$ npm ci |
53 | | -``` |
54 | | - |
55 | | -### Development |
56 | | - |
57 | | -To run the application in `development` mode run: |
58 | | - |
59 | | -```bash |
60 | | -$ npm run dev |
61 | | -``` |
62 | | - |
63 | | -### Production |
64 | | - |
65 | | -To mimic the application running in `production` mode locally run: |
66 | | - |
67 | | -```bash |
68 | | -$ npm run start |
69 | | -``` |
70 | | - |
71 | | -### npm scripts |
72 | | - |
73 | | -All available npm scripts can be seen in [package.json](./package.json) |
74 | | -To view them in your command line run: |
75 | | - |
76 | | -```bash |
77 | | -$ npm run |
78 | | -``` |
79 | | - |
80 | | -### File Uploads with Local Development |
81 | | - |
82 | | -When developing locally with file upload functionality, there are specific configuration requirements to handle CORS (Cross-Origin Resource Sharing) and CSP (Content Security Policy) restrictions. |
83 | | - |
84 | | -### Setting up the CDP Uploader Service |
85 | | - |
86 | | -The forms-runner application needs to use the CDP uploader service which is available in the docker-compose setup from the forms-api-submissions repository: |
87 | | - |
88 | | -1. Clone the forms-api-submissions repository |
89 | | -2. Start the required services with docker-compose: |
90 | | - |
91 | | -```bash |
92 | | -$ cd forms-api-submissions |
93 | | -$ docker-compose up -d |
94 | | -``` |
95 | | - |
96 | | -This will start: |
97 | | - |
98 | | -- The CDP uploader service on port 7337 |
99 | | -- A Nginx reverse proxy on port 7300 |
100 | | -- Supporting services (localstack, Redis) needed by the uploader |
101 | | - |
102 | | -### Configuring the Uploader URL |
103 | | - |
104 | | -For file uploads to work properly in local development, you need to use the sslip.io domain that maps to the proxy: |
105 | | - |
106 | | -1. Set the UPLOADER_URL in your .env file: |
107 | | - |
108 | | -``` |
109 | | -UPLOADER_URL=http://uploader.127.0.0.1.sslip.io:7300 |
| 1 | +# forms-engine |
| 2 | + |
| 3 | +Form hapi-plugin |
| 4 | + |
| 5 | +... |
| 6 | + |
| 7 | +## Templates |
| 8 | + |
| 9 | +The following elements support [LiquidJS templates](https://liquidjs.com/): |
| 10 | + |
| 11 | +- Page **title** |
| 12 | +- Form component **titles** |
| 13 | + - Support for fieldset legend text or label text |
| 14 | + - This includes when the title is used in **error messages** |
| 15 | +- Html (guidance) component **content** |
| 16 | +- Summary component **row** key title (check answers and repeater summary) |
| 17 | + |
| 18 | +### Template data |
| 19 | + |
| 20 | +The data the templates are evaluated against is the raw answers the user has provided up to the page they're currently on. |
| 21 | +For example, given a YesNoField component called `TKsWbP`, the template `{{ TKsWbP }}` would render "true" or "false" depending on how the user answered the question. |
| 22 | + |
| 23 | +The current FormContext is also available as `context` in the templates. This allows access to the full data including the path the user has taken in their journey and any miscellaneous data returned from `Page event`s in `context.data`. |
| 24 | + |
| 25 | +### Liquid Filters |
| 26 | + |
| 27 | +There are a number of `LiquidJS` filters available to you from within the templates: |
| 28 | + |
| 29 | +- `page` - returns the page definition for the given path |
| 30 | +- `field` - returns the component definition for the given name |
| 31 | +- `href` - returns the page href for the given page path |
| 32 | +- `answer` - returns the user's answer for a given component |
| 33 | +- `evaluate` - evaluates and returns a Liquid template using the current context |
| 34 | + |
| 35 | +### Examples |
| 36 | + |
| 37 | +```json |
| 38 | +"pages": [ |
| 39 | + { |
| 40 | + "title": "What's your name?", |
| 41 | + "path": "/full-name", |
| 42 | + "components": [ |
| 43 | + { |
| 44 | + "name": "WmHfSb", |
| 45 | + "title": "What's your full name?", |
| 46 | + "type": "TextField" |
| 47 | + } |
| 48 | + ] |
| 49 | + }, |
| 50 | + // This example shows how a component can use an answer to a previous question (What's your full name) in it's title |
| 51 | + { |
| 52 | + "title": "Are you in England?", |
| 53 | + "path": "/are-you-in-england", |
| 54 | + "components": [ |
| 55 | + { |
| 56 | + "name": "TKsWbP", |
| 57 | + "title": "Are you in England, {{ WmHfSb }}?", |
| 58 | + "type": "YesNoField" |
| 59 | + } |
| 60 | + ] |
| 61 | + }, |
| 62 | + // This example shows how a Html (guidance) component can use the available filters to get the form definition and user answers and display them |
| 63 | + { |
| 64 | + "title": "Template example for {{ WmHfSb }}?", |
| 65 | + "path": "/example", |
| 66 | + "components": [ |
| 67 | + { |
| 68 | + "title": "Html", |
| 69 | + "type": "Html", |
| 70 | + "content": "<p class=\"govuk-body\"> |
| 71 | + // Use Liquid's `assign` to create a variable that holds reference to the \"/are-you-in-england\" page |
| 72 | + {%- assign inEngland = \"/are-you-in-england\" | page -%} |
| 73 | + |
| 74 | + // Use the reference to `evaluate` the title |
| 75 | + {{ inEngland.title | evaluate }}<br> |
| 76 | + |
| 77 | + // Use the href filter to display the full page path |
| 78 | + {{ \"/are-you-in-england\" | href }}<br> |
| 79 | + |
| 80 | + // Use the `answer` filter to render the user provided answer to a question |
| 81 | + {{ 'TKsWbP' | answer }} |
| 82 | + </p>\n" |
| 83 | + } |
| 84 | + ] |
| 85 | + } |
| 86 | +] |
110 | 87 | ``` |
111 | | - |
112 | | -2. Make sure "host.docker.internal" is enabled in your Docker Desktop settings |
113 | | - |
114 | | -### How it Works |
115 | | - |
116 | | -- The docker-compose setup includes an Nginx reverse proxy that routes requests from uploader.127.0.0.1.sslip.io:7300 to the CDP uploader service |
117 | | -- When developing locally, JavaScript CORS restrictions would normally block direct requests to localhost:7337 |
118 | | -- The sslip.io domain (a special DNS service that maps IPs to domains) allows your browser to make cross-origin requests |
119 | | -- The application automatically detects local development URLs with localhost:7337 and rewrites them to use the proxy |
120 | | - |
121 | | -### Troubleshooting |
122 | | - |
123 | | -- If file uploads fail, ensure all the required docker services are running |
124 | | -- Verify the proxy is working by testing: http://uploader.127.0.0.1.sslip.io:7300 |
125 | | -- Check Docker logs for the cdp-uploader and proxy containers if issues persist |
126 | | - |
127 | | -## Docker |
128 | | - |
129 | | -### Development image |
130 | | - |
131 | | -Build: |
132 | | - |
133 | | -```bash |
134 | | -$ docker build --target development --no-cache --tag forms-runner:development . |
135 | | -``` |
136 | | - |
137 | | -Run: |
138 | | - |
139 | | -```bash |
140 | | -$ docker run -p 3000:3000 forms-runner:development |
141 | | -``` |
142 | | - |
143 | | -### Production image |
144 | | - |
145 | | -Build: |
146 | | - |
147 | | -```bash |
148 | | -docker build --no-cache --tag forms-runner . |
149 | | -``` |
150 | | - |
151 | | -Run: |
152 | | - |
153 | | -```bash |
154 | | -$ docker run -p 3000:3000 forms-runner |
155 | | -``` |
156 | | - |
157 | | -# Environment variables |
158 | | - |
159 | | -If there is a .env file present, these will be loaded in. |
160 | | - |
161 | | -### ⚠️ See [config](./src/config/index.ts) for default values for each environment |
162 | | - |
163 | | -Please use a config file instead. This will give you more control over each environment. |
164 | | -The defaults can be found in [config](./src/config/index.ts). Place your config files in `runner/config` |
165 | | -See [https://github.com/node-config/node-config#readme](https://github.com/node-config/node-config#readme) for more info. |
166 | | - |
167 | | -| name | description | required | default | valid | notes | |
168 | | -| ------------------ | ------------------------------------------------------------------------- | :------: | ------- | :-------------------------: | :-------------------------------------------------------------------------------------------------------------------------: | |
169 | | -| NODE_ENV | Node environment | no | | development,test,production | | |
170 | | -| PORT | Port number | no | 3009 | | | |
171 | | -| NOTIFY_TEMPLATE_ID | Notify api key | yes | | | Template ID required to send form payloads via [GOV.UK Notify](https://www.notifications.service.gov.uk) email service. | |
172 | | -| NOTIFY_API_KEY | Notify api key | yes | | | API KEY required to send form payloads via [GOV.UK Notify](https://www.notifications.service.gov.uk) email service. | |
173 | | -| LOG_LEVEL | Log level | no | debug | trace,debug,info,error | | |
174 | | -| PHASE_TAG | Tag to use for phase banner | no | beta | alpha, beta, empty string | | |
175 | | -| FEEDBACK_LINK | Link to display in the phase banner when asking for feedback. | no | | | Used for an anchor tag's href. To display an email link, use a 'mailto:dest@domain.com' value. Else use a standard website. | |
176 | | -| HTTP_PROXY | HTTP proxy to use, e.g. the one from CDP. Currently used for Hapi Wreck. | no | | | |
177 | | -| HTTPS_PROXY | HTTPS proxy to use, e.g. the one from CDP. Currently used for Hapi Wreck. | no | | | |
178 | | -| NO_PROXY | HTTP proxy to use, e.g. the one from CDP. Currently used for Hapi Wreck. | no | | | |
179 | | - |
180 | | -For proxy options, see https://www.npmjs.com/package/proxy-from-env which is used by https://github.com/TooTallNate/proxy-agents/tree/main/packages/proxy-agent. |
181 | | - |
182 | | -# Testing |
183 | | - |
184 | | -Tests are found inside `test/cases`. For test scripts, name them `${NAME}.test.js`. |
185 | | - |
186 | | -# Outputs |
187 | | - |
188 | | -At the end of a form, there are multiple output types. The schemas for the right json format can be found in the engine repo. |
189 | | -Additional steps are required for the different output types. |
190 | | - |
191 | | -- Notify |
192 | | - - A GOV.UK [notify](https://www.notifications.service.gov.uk) is required |
193 | | - - For each notification you wish to send, a template must be set up. If there are 'personalisations' they must match the configuration |
194 | | - |
195 | | -## Licence |
196 | | - |
197 | | -THIS INFORMATION IS LICENSED UNDER THE CONDITIONS OF THE OPEN GOVERNMENT LICENCE found at: |
198 | | - |
199 | | -<http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3> |
200 | | - |
201 | | -The following attribution statement MUST be cited in your products and applications when using this information. |
202 | | - |
203 | | -> Contains public sector information licensed under the Open Government license v3 |
204 | | -
|
205 | | -### About the licence |
206 | | - |
207 | | -The Open Government Licence (OGL) was developed by the Controller of Her Majesty's Stationery Office (HMSO) to enable |
208 | | -information providers in the public sector to license the use and re-use of their information under a common open |
209 | | -licence. |
210 | | - |
211 | | -It is designed to encourage use and re-use of information freely and flexibly, with only a few conditions. |
0 commit comments