README.md
# GFW Forms API
[![Build Status](https://travis-ci.com/gfw-api/gfw-forms-api.svg?branch=dev)](https://travis-ci.com/gfw-api/gfw-forms-api)
[![Test Coverage](https://api.codeclimate.com/v1/badges/fead108699d985f0b266/test_coverage)](https://codeclimate.com/github/gfw-api/gfw-forms-api/test_coverage)
This repository is the microservice that implements the forms and Questionnaire functionality
## Dependencies
You will need [Control Tower](https://github.com/control-tower/control-tower) up and running - either natively or with Docker. Refer to the project's README for information on how to set it up.
The GFW Forms API microservice is built using [Node.js](https://nodejs.org/en/), and can be executed either natively or using Docker, each of which has its own set of requirements.
Native execution requires:
- [Node.js](https://nodejs.org/en/)
- [MongoDB](https://www.mongodb.com/)
Execution using Docker requires:
- [Docker](https://www.docker.com/)
- [Docker Compose](https://docs.docker.com/compose/)
Dependencies on other Microservices:
- [GFW Areas](https://github.com/gfw-api/gfw-area)
- [FW teams](https://github.com/gfw-api/fw-teams)
## Getting started
Start by cloning the repository from github to your execution environment
```
git clone https://github.com/gfw-api/gfw-forms-api.git && cd gfw-forms-api
```
After that, follow one of the instructions below:
### Using native execution
1 - Set up your environment variables. See `dev.env.sample` for a list of variables you should set, which are described in detail in [this section](#environment-variables) of the documentation. Native execution will NOT load the `dev.env` file content, so you need to use another way to define those values
2 - Install node dependencies using yarn:
```
yarn
```
3 - Start the application server:
```
yarn start
```
The endpoints provided by this microservice should now be available through Control Tower's URL.
### Using Docker
1 - Create and complete your `dev.env` file with your configuration. The meaning of the variables is available in this [section](#configuration-environment-variables). You can find an example `dev.env.sample` file in the project root.
2 - Execute the following command to run Control tower:
```
./forms.sh develop
```
The endpoints provided by this microservice should now be available through Control Tower's URL.
## Testing
There are two ways to run the included tests:
### Using native execution
Follow the instruction above for setting up the runtime environment for native execution, then run:
```
yarn test
```
### Using Docker
Follow the instruction above for setting up the runtime environment for Docker execution, then run:
```
./forms.sh test
```
### Configuration
It is necessary to define these environment variables:
* CT_URL => Control Tower URL
* NODE_ENV => Environment (prod, staging, dev)
## Quick Overview
### Report entity
```json
{
"data": [
{
"type": "reports",
"id": "591f2513d3a6c4003f4960b4",
"attributes": {
"name": {
"en": "My first report",
"es": "Mi primer informe"
},
"languages": [
"en",
"es"
],
"defaultLanguage": "en",
"areaOfInterest": "aoi-id",
"user": "1a10d7c6e0a37126611fd7a7",
"questions": [
{
"type": "text",
"name": "name",
"defaultValue": {
"en": "Insert your name",
"es": "Spanish"
},
"_id": "591f2513d3a6c4003f4960b7",
"conditions": [],
"childQuestions": [],
"order": 1,
"required": false,
"label": {
"en": "Name",
"es": "Nombre"
}
},
{
"type": "checkbox",
"name": "age",
"defaultValue": 0,
"_id": "591f2513d3a6c4003f4960b5",
"conditions": [],
"childQuestions": [
{
"type": "text",
"name": "specific-age",
"defaultValue": {
"en": "Insert your name",
"es": "Spanish"
},
"conditionalValue": 0,
"_id": "591f2513d3a6c4003f4960b6",
"order": 0,
"required": true,
"label": {
"en": "Specific age",
"es": "Specific age"
}
}
],
"order": 2,
"required": false,
"values": {
"en": [
{
"value": 0,
"label": "19-32"
},
{
"value": 1,
"label": "12-43"
}
],
"es": [
{
"value": 0,
"label": "18-12"
},
{
"value": 1,
"label": "12-45"
}
]
},
"label": {
"en": "Range age",
"es": "Spanish"
}
}
],
"createdAt": "2017-05-19T17:02:11.415Z"
}
}
]
}
```
### CRUD Reports
```json
All endpoints are logged. Check if user is ADMIN or MANAGER in gfw application
GET: /reports -> Return all reports accessible to user logged
GET: /reports/:id -> Returns report with the same id. Check if user is ADMIN or MANAGER in gfw application
Example response:
{
"data": {
"type": "reports",
"id": "592402c4cfcfaf0070e78826",
"attributes": {
"name": {
"en": "My report template",
"es": "Mi report templato"
},
"languages": [
"en",
"es"
],
"defaultLanguage": "en",
"areaOfInterest": "aoi-id",
"user": "1a10d7c6e0a37126611fd7a7",
"public": false,
"questions": [
{
"type": "text",
"name": "name",
"defaultValue": {
"es": "Spanish",
"en": "Insert your name"
},
"_id": "592402c4cfcfaf0070e78829",
"conditions": [],
"childQuestions": [],
"order": 1,
"required": false,
"label": {
"es": "Nombre",
"en": "Name"
}
},
{
"type": "checkbox",
"name": "age",
"defaultValue": 0,
"_id": "592402c4cfcfaf0070e78827",
"conditions": [],
"childQuestions": [
{
"type": "text",
"name": "specific-age",
"defaultValue": {
"es": "Spanish",
"en": "Insert your name"
},
"conditionalValue": 0,
"_id": "592402c4cfcfaf0070e78828",
"order": 0,
"required": true,
"label": {
"es": "Specific age",
"en": "Specific age"
}
}
],
"order": 2,
"required": false,
"values": {
"es": [
{
"label": "18-12",
"value": 0
},
{
"label": "12-45",
"value": 1
}
],
"en": [
{
"label": "19-32",
"value": 0
},
{
"label": "12-43",
"value": 1
}
]
},
"label": {
"es": "Spanish",
"en": "Range age"
}
}
],
"createdAt": "2017-05-23T09:37:08.315Z"
}
}
}
POST: /reports -> Create an report and associate to the user. With body:
{
"areaOfInterest": "aoi-id",
"languages": ["en", "es"],
"defaultLanguage": "en",
"name": {
"en": "My report template",
"es": "Mi report templato"
},
"public": false,
"questions": [
{
"type": "text",
"label": {
"en": "Name",
"es": "Nombre"
},
"name": "name",
"conditions": [],
"childQuestions": [],
"order": 1,
"required": false,
"values": {},
"defaultValue": {
"en": "Insert your name",
"es": "Spanish"
}
},
{
"type": "checkbox",
"label": {
"en": "Range age",
"es": "Spanish"
},
"name": "age",
"conditions": [],
"order": 2,
"required": false,
"values": {
"en": [
{ "value": 0, "label": "19-32"},
{ "value": 1, "label": "12-43"}
],
"es": [
{ "value": 0, "label": "18-12"},
{ "value": 1, "label": "12-45"}
]
},
"defaultValue": 0,
"childQuestions": [
{
"type": "text",
"label": {
"en": "Specific age",
"es": "Specific age"
},
"name": "specific-age",
"defaultValue": {
"en": "Insert your name",
"es": "Spanish"
},
"conditionalValue": 0,
"order": 0,
"required": true,
"values": {}
}
]
}
]
}
Notes: public fields can only be passed as true by ADMINs. These templates appear to all users. Required fields:
- name
- languages
- defaultLanguage
- public
- questions
PATCH: /reports/:id -> Update the report with the same id.
DELETE: /reports/:id -> Delete the report with the same id.
```
### CRUD report answers
```json
GET: /report/:id/answers -> Return all answers of the report by id of the user logged
GET: /report/:id/answers/:id -> Return answer with the same id. Check if the answer is owned of the logged user
Example response:
{
"data": {
"type": "answers",
"id": "59240430cfcfaf0070e78866",
"attributes": {
"report": "592402c4cfcfaf0070e78826",
"username": "fwuser",
"organization": "gfw",
"areaOfInterest": "my-area-id",
"language": "es",
"createdAt": "12-04-2017T13:40:34:223Z",
"userPosition": [
"1",
"1"
],
"clickedPosition": [
"1",
"1"
],
"startDate": "2013-01-23 12:00:33",
"endDate": "2013-02-23 15:00:33",
"layer": "GLAD",
"user": "1a10d7c6e0a37126611fd7a7",
"responses": [
{
"name": "name",
"parent": "none",
"value": "Ed",
"_id": "59240430cfcfaf0070e7886f"
},
{
"name": "age",
"parent": "none",
"value": "1",
"_id": "59240430cfcfaf0070e7886f"
},
{
"name": "specific-age",
"parent": "age",
"value": "21",
"_id": "59240430cfcfaf0070e7886f"
}
]
}
}
}
POST: /reports/:id/answers -> Create an answer to the report with the id of the report and associate to the user. With body:
Without Content-type (it is possible send files as attachments). For example
<questionName>: <responseValue>
name: Pepe
age: 0-18
specific-age: 32
photo: upload_file
Notes: These templates appear to all users. Required fields:
- language
- userPosition (comma separated lat lng [1,1])
- clickedPosition (comma separated lat lng [1,1])
- createdAt
- Any questions for the template that have the value required as true
PATCH: /reports/:id/answer/:id -> Update the answer with the same id. Check if the answer is owned by the logged user
DELETE: /reports/:id/answer/:id -> Delete the answer with the same id. Check if the answer is owned by the logged user
```
### Download report answers
```
GET: /reports/:id/download-answers -> downloads all answers to the report by :id.
```
WIP:
* All PATCH under development
* Accept query params to all GET requests
* Download individual answers for reports
* Add query params to fetch answers by language