ctagroup / home-app

http://www.ctagroup.org/home-app/
Other
7 stars 5 forks source link

Home Meteor App

Build Status

Prerequisites

How to Run on local machine

Maker a local copy settings.local.json of the file settings.json

git clone git@github.com:ctagroup/home-app.git
cd home-app
git checkout master
meteor npm install
meteor run --settings settings.local.json

Testing

To run tests:

npm run test

Deploy instructions

Meteor Up is used to deploy this app. Ref: https://github.com/kadirahq/meteor-up

Deploy configs

First time steps

Deploy steps

SSL Certificate

Login to Server with SSH using home.pem key to perform following actions.

Enable

sudo ee site update home.ctagroup.org --letsencrypt

Disable

sudo ee site update home.ctagroup.org --letsencrypt=off

Renew

sudo ee site update home.ctagroup.org --letsencrypt=renew

Mongo DB Backup & Restore from Docker Server

Dump

docker run \
 --rm \
 --link mongodb:mongo \
 -v /home/ubuntu/backup-dir:/backup \
 mongo \
 bash -c 'mongodump --out /backup --host $MONGO_PORT_27017_TCP_ADDR'

Restore

docker run \
 --rm \
 --link mongodb:mongo \
 -v /home/ubuntu/home-app/meteor-mongodb\ backup/dump-2016-08-15:/backup \
 mongo \
 bash -c 'mongorestore --drop -d home-monterey /backup/home-cta --host $MONGO_PORT_27017_TCP_ADDR'

Ref: https://gist.github.com/desaiuditd/53fbfa61d564e2a9d84376e1237fdd36

Access MongoDB on the Server

Ref: https://github.com/kadirahq/meteor-up/#accessing-the-database

Coding guidelines

Each publication and method should log its details:

logger.info(`PUB[${this.userId}]: name`, params);
logger.info(`METHOD[${this.userId}]: name`, params);

Each method call should use Alert to report succes/error as below. err can be a string or an exception.

import Alert from '/imports/ui/alert';

Alert.error(err);
Alert.success('Question updated');

Reading data from API

Conform to the following schema when returning data from HSLYNK.

clientDetails = {
  clientId: '1234',
  schema: 'v2017',
  firstName: 'John',
  error: {
    message: 'Client not found',
    statusCode: 404
  }
}

If you make a call to edit/remove HMIS item you need to update local (client side) collection to reflect the changes. Ie.

Clients._collection.update(client._id, { $set: result }); // eslint-disable-line

Use authorize key in a router to check user permissions:

  authorize: {
    allow() {
      return Roles.userIsInRole(Meteor.userId(), ResponsesAccessRoles);
    },
  },

Survey definition

Survey definition describes the elements of the survey and its interal logic. Survey definition is written using JSON format and consists of the following fields:

{
  "title": "Test Survey",
  "variables": { ... },
  "items": [ ... ]
}

Survey logic

Form values are current question responses. If there is question with id = question1 and a change occurs for this question (i.e. text is entered), values.question1 will hold a response given to this question.

Form variables are recalculated on each value change. When a change occurs (i.e. user types a response), variables are first initialized with initial values provided in form.variables, then rules are fired which may change the variables. Rules are fired from top to bottom.

Form props are similar to values because the are persistent - when a change occurs, props are not reset to default values like variables do. In contrast to values, props are not submitted when the form is submitted. So far props are used to implement skipping sections.

Special variables

Some variables have special meaning. Set variables.ID.hidden equal to 1 to hide element with a given ID.

Rules

Survey item can have any number of associated rules that handle survey logic. Each rule consists of conditions and actions. If conditions are satisfied then actions are fired. All rules are evaluated from top to bottom of the survey definition, before any update in UI takes place.

Conditions

Checking for a question response value

[OPERATOR, values.ID|variables.ID|props.ID|CONST, values.ID|variables.ID|props.ID|CONST]
['==', 'values.pregnantMember', 'Yes']
['>=', 'variables.numChildren', 3],
['==', 'props.parent2.skip', 1],

Actions

Setting a variable:

['set', 'score2', 1]

Now there will be a variable variables.score2 with value of 1.

Setting element property:

['pset', 'question1.skip', 1]

This sets question1 as skipped (value is erased, question cannot be edited)

Operand reducers

[variable.ID|client.ID|value.ID]:REDUCER1:REDUCER2

Reduces will apply transformations to the value of an operand. Reducers can be chained using : notation.

As an example client.dob:age will return age based on the date of birth of a client

Reducers can be applied to arrays (set of values for a certain column in a grid):

['set', 'youngestChildAge', 'values.children.age:min'],

will set a variables.youngestChildAge equal to smallest value in age column of a children grid

Avaliable reducers:

Scoring responses

Each variable that starts with score. is treated as a scoring variable and it's value will be submitted to HMIS when surevy responses are uploaded. Keep in mind that HMIS calculates the sum of all scores automatically, so there is no need to send a variable that hold the total survey score.

Survey items

Examples

The following survey is made of 2 questions (number inputs)

{
  "title": "Test Survey",
  "id": "dummy",
  "variables": {
    "score.A": 0,
    "score.B": 0,
    "grandtotal": 0
  },
  "items": [
    {
      "id": "question1",
      "title": "Enter first number",
      "type": "question",
      "category": "number"
    },
    {
      "id": "question2",
      "title": "Enter second number",
      "type": "question",
      "category": "number"
    },
    {
      "id": "summary",
      "type": "text",
      "title": "Scoring Summary",
      "text": "First score: {{variables.score.A}}<br />Second score: {{variables.score.B}}<br /><strong>GRAND TOTAL: {{variables.grandtotal}}</strong>",
      "rules": [
        {
          "always": [
            [
              "set",
              "score.A",
              "values.question1"
            ],
            [
              "set",
              "score.B",
              "values.question2"
            ],
            [
              "sum",
              "grandtotal",
              "variables.score.A",
              "variables.score.B"
            ]
          ]
        }
      ]
    }
  ]
}

Surveys

Submission Uploader

To enable submission uploader an "uploader": true must be added to settings.json file E.G:

{
  "public": {
    "features": {
      "appProfile": "home",
      "uploader": true
    }
  }
}

Currently the Submission Uploader is only available by direct links: /submissionUploader/list /submissionUploader/new

Examples

See exampleUploadConfig.json for the example of config to be input for Submission Uploader

Meteor Components in use