2019-01-18 22:26:05 +00:00
2017-09-22 17:17:14 +01:00
2018-03-24 23:20:49 +00:00
2017-04-29 11:42:07 +01:00
2018-03-24 21:32:09 +00:00
2017-04-29 11:42:07 +01:00
2017-04-29 11:42:07 +01:00
2017-12-23 22:33:15 +00:00
2017-04-29 11:42:07 +01:00
2017-04-29 11:42:07 +01:00
2017-04-29 11:42:07 +01:00
2017-08-18 16:23:56 +01:00
2017-04-29 11:42:07 +01:00
2017-04-29 11:42:07 +01:00
2017-04-29 11:42:07 +01:00
2018-03-03 23:13:25 +00:00
2017-04-29 11:42:07 +01:00
2017-04-29 11:42:07 +01:00
2019-01-18 22:26:05 +00:00
2017-10-16 22:14:57 +01:00
2017-06-17 22:15:58 +01:00
2017-04-29 11:42:07 +01:00

IntroImage

Contents

  1. About
  2. User Documentation
  3. Technical Documentation
  4. Project Planning
  5. Research
  6. Legal

Watch Demo Video

Happy App Demo on YouTube

Introduction

Happy App finds out how team members are feeling about their project, and visually displays results.

Scheduled emails are sent out to every member at a given time, containing an embedded poll, making submitting responses effortless. All responses are anonymised, encouraging team member to be honest. The dashboard displays a summary of results in a series of data visualisations, showing:

  • Overall team sentiment for today
  • Sentiment change over time
  • Sentiment by team

Demo

Live demo at: happy-app-demo.as93.net

The demo uses automatically generated sample data (where teams have been given random city names), and scores are totally random.

Screen Shots

Home Page: Homepage

Mobile Screen Shots: Mobile

Team Page Screenshots (click to show)

TeamPage

Current Status

Dependencies

dependencies Status devDependencies Status

Code Quality

Maintainability Codacy Badge

Support

Maintenance stable

Tests

//todo

User Documentation

Initial Configuration

// todo

Adding Results

// todo

Displaying Results

// todo

Mobile

//todo

Technical Documentation

Development Setup

Setting up the project for development is done in the standard way.

The steps are as follows:

  1. Clone the repo, and cd into it
  2. yarn install the npm node dependencies, and frontend dependencies
  3. Connect to mongo, mongod. See the Getting Started page on MongoDB documentation.
  4. Populate the database with some sample data (optional). gulp populate-sample-data (See Data section for more info)
  5. Start the development server, npm run dev. This watches, compiles and refreshes appropriate server and client components.

Production Setup

  1. Clone or upload the files to your server directory
  2. Run yarn, to install the npm and frontend modules
  3. Create a .env file in the project root, and populate it like the example below
  4. Setup and start a mongo instance, and configure the port appropriately in the .env
  5. Build the produciton version, with npm run buil:prod
  6. Run npm run test to verify that everything is working as expected
  7. Start the app (using a forever or pm2 to keep it alive), forever start node server
  8. Set up a cron job or similar to start the app on server reboot

Example .env file. Will need populating with valid API keys.

NODE_ENV=production
PORT=3001
ROLLBAR_KEY=123abc
NEW_RELIC_APP_NAME=happy-app
NEW_RELIC_LICENSE_KEY=123abc

App Customisation

Test Environment

Read more about the test strategy

Data

All data is anonymised, a one-way hash is created from the users email address, which is used by the system to uniquely identify them, but this is not displayed to users/ admins.

User data is represented in the following JSON format:

teamName: (String)
data: (Array)
---date: (Timestamp)
---userResults: (Object)
------userHash: (StringHash)
------score: (String)
------comment: (String)
For example (click to expand)

Example JSON:

[
  {
    "teamName": "team-name",
    "data": [
      {
        "date": 1495273151191,
        "userResults": [
          { "userHash": "USR28JD83H3DKDS", "score": "good", "comment": "" },
          { "userHash": "USRCJD93JD93JD9", "score": "good", "comment": "fun team lunch" },
          { "userHash": "USRNC983JD93JSM", "score": "average", "comment": "" },
          { "userHash": "USRJCI3NDX923JC", "score": "bad", "comment": "too many meetings" },
          { "userHash": "USRNZZK1SD251CS", "score": "average", "comment": "" }
        ]
      },
      {
        "date": 1495273223108,
        "userResults": [
          { "userHash": "USR28JD83H3DKDS", "score": "bad", "comment": "" },
          { "userHash": "USRCJD93JD93JD9", "score": "good", "comment": "" },
          { "userHash": "USRNC983JD93JSM", "score": "good", "comment": "fast progress" }
        ]
      }
    ]
  }
]

see more...

For development, a random set of data can be generated (using a tool such as json-generator), with a definition similar to the one below:

[
  {
    'repeat(4,6)': {
    teamName: 'team-{{city()}}',
    data: [
      {     
       'repeat(45,90)': {
        date: function (tags, parent, index) {
           var d = new Date();
           return d.setDate(d.getDate()-index);
		},
            userResults: [
                {
                'repeat(6,30)': {
                userHash:function(t,p,i){ return parseInt((i+1*i)*75+10, 16); },
                score: '{{random("good", "average", "bad")}}',
                comment:''
                }
              }
           ]
        }
      }
    ]
  }
  }
]

To populate the database with either randomly generated data, or exported JSON, run:

gulp populate-sample-data

By default this generates a set of random, but reasonably realistic sample data, the parameters of which were defined in the populate-demo-db.js file. Alternativley, the path of previously generated or exported data can be specified, and the database will be populated the that data. An example filename parameter may look something like this: /tasks/setup/sample-data.json.

API

The frontend accesses it's data through the set of functions exposed by the backend. There are GET routes for just returning data, and POST routes which update/ add new data, and require authentication.

All API calls are made from BASE_URL/api/, where BASE_URL is the URI of the app root (e.g. 'localhost', IP address or the domain pointing to main app)

/teams

Returns an array of all teams referenced to in the datasets

  • URL: /teams/
  • Method: GET
  • URL Params: none
  • Success Response:
    • Code: 200
    • Content: ['team-name1', 'team2', 'three', 'forth-team']
  • Error Response:
    • Code: 200
    • Content: []

/team-sentiment

Returns all recorded sentiment for all teams

  • URL: /team-sentiment/
  • Method: GET
  • URL Params: none
  • Success Response:
    • Code: 200
    • Content: {teamName: '', data: { [.....] }} (See the above section on data format)
  • Error Response:
    • Code: 200
    • Content: {}

/team-sentiment/:team-name

Returns all recorded sentiment data for any given team

  • URL: /team-sentiment/:team-name
  • Method: GET
  • URL Params: teamName (the name of the team, as a String)
  • Success Response:
    • Code: 200
    • Content: {teamName: '', data: { [.....] }} (See the above section on data format)
  • Error Response:
    • Code: 200
    • Content: {}

/team-members

Returns all member hashes for each team. Requires authentication.

  • URL: /team-members
  • Method: GET
  • URL Params: none
  • Success Response:
    • Code: 200
    • Content: ``
  • Error Response:
    • Code: ``
    • Content: {}

/save-response

Checks and saves the response for a given user hash.

  • URL: /save-response
  • Method: POST
  • URL Params: { emailHash: '', score: 'good', comment: ''}
  • Success Response:
    • Code: 200
    • Content: ``
  • Error Response:
    • Code: ``
    • Content: {}

File Structure

happy-app
│   README.md
│   package.json    
│
└───client
│   └───dev
│       │───components
│       │───pages
│       │───services
│       │───styles
│       │───graphics
|       |   app.module.js
|       |   app.ts
|       |   config.js
|       |   index.html
|       |   main-jit.ts
|       |   main-aot.ts
|    ___|   manifest.json
|   |   
│   └───dist
│       │─── ...     
│   
└───server
|   │───api
|   │───auth
|   │───commons
|   │───config
|   │───constants
|   │───routes
|   │   error-tracking.js
|   │   index.js
|   |   server.js
|
└───tasks
|
└───tests

Error Handling

Errors are tracked, monitored and handled using Rollbar. An API key is required, and needs to be added into the .env file, as ROLLBAR_KEY. If no key is specified, all Rollbar events will just be skipped.

The error tracking code is in /server/commons/error-tracking.js. So to swap Rollbar out with something else, such as TrackJS or ErrLytics, this Should be the only file which needs modifying.

To use, first include the above file: const rollbar = require("../../commons/error-tracking"); Then either log a message, like: rollbar.logMessage("Team List returned", teamNames); Or in an error catch block, log the error, like: rollbar.logWarning("Unable to fetch team list", err);

Rollbar also catches and manages client side errors, and is initialised in client/app.module.ts.

Analytics and Tracking

angulartics2 is ued to implement Google Analytics and Google Tag Manager. The tracking is managed in analytics-tracking.service.ts. A function similar to the one below can be used to track events:

trackAnalyticEvents(action, properties = {}){
  this.angulartics2.eventTrack.next({ action: action, properties: properties});
}

As well as ths, the standard GA / GTAG code snipped it in the client/index.html.

Mobile App

There is no mobile app companion for happy-app.

Though it was built following Google's Progressive Web App guidelines. It aims to be reliable, fast and engaging. And this is achieved through making use of service workers for basic offline Functionality, and the Google manifest.json, to allow for custom splash screens, icons and colours once it to be added to the users home screen. It is, of course fully responsive, and every effort has been made to support all modern browsers and devices, as best as possible.

Offline Functionality

Server-side Rendering

AOT

D3 Charts Info

Each D3.js is in it's own component, so should be able to be implemented anywhere in the application, and managed centrally. See overview-chart.component.ts for an example. Team data is managed centrally in
team.service.ts and each chart listens for changes in this service and updates accordingly. All the D3 chart components follow the same structure. There are (currently) six charts:

  • calendar-chart - Detailed calendar breakdown for a given team
  • day-breakdown-chart - Breakdown of sentiment results between teams for a given day
  • grid-chart - High-level overvier of average sentiment for all teams
  • message-chart - Visual display of annomised team-member comments for each team
  • overview-chart - Donut chart showing proportions of sentiment for a given team
  • time-chart - Shows sentiment over time, for a given team

Tech Stack

TechStack

The app uses a fairly standard MEAN (Mongo, Express, Angular 4, Node) stack, with D3.js for the charts, and isomorphic rendering with Angular Universal.

Show Full Tech Stack:

The majority of it was written in/ with SASS/SCSS (for the styles), TypeScript (for client-side JS), Babel (for server-side JS) and handlebars (for non-Angular HTML).

Several utilities proved to be a vital help, when carrying out common tasks, mostly Bluebird and Q (for promises), dotenv (for managing environmental variables), RxJS (mainly for event binding in Angular), and of course Mongoose for making Mongo super easy to work with.

Testing the app, was made possible using combination of frameworks and libraries. Cucumber (for specifying BHD tests), Protractor (for E2E Angular testing), Karma (for running the unit tests), Mocha (for running server-side tests), Chai (for writing the server side tests), Istanbul (for checking test coverage), Code Climate (for checking code quality is on point), Sinnon.js (for stubs and spies), Davis DM (for checking dependencies are u2d) and Phantom (was initially used for headless browser testing).

Detailed analytics are collected with [Google Tag Manager (GTM)], and application errors and warnings are tracked with Rollbar.

Project Planning

High-Level Flow Chart

Flowchart

Wireframes

Wireframes

High-Level Functional Requirements

Mail Scheduler

The system the sends out periodic emails to team members, collects, verifies, formats and inserts results

  • Maintains a list of email addresses for each member of each team
  • Generates unique data-collection links ( associated with email address, timestamp and mood)
  • Sends emails at a specified time on given days (e.g. 4pm Mon- Fri)
  • Verifies that users response is valid (from team-member email, and not already submitted within timeframe)
  • Inserts team members response into the database

View Responses (Individual Team)

A series of data visualisations to display team mood

  • Overview chart. A very simple proportion (donut) chart, showing overall percentages. Should allow the user to switch between displaying results from today, this week, and this month.
  • Time chart. A line chart showing team sentiment over-time. Should allow the user to switch between aggregate (one line representing overall sentiment), and breakdown (line for each sentiment).
  • Calendar view. A detailed month-view calendar, showing the number of responses for each sentiment per day, with hover tooltip to view comments (if applicable) for each response.
  • Comment view. Show's in plain text the comments, sorted by most recent first.
  • Sentiment word cloud. Generated from comments, size of word represents number of occurrences, colour represents sentiment.
  • Grid view. Grid to show responses over time, the primary use of this is to gauge what percentage of team members consistently respond to the survey.
  • Stats view. Numeric value, displaying the worst and best day, highest and lowest participation day.

View Responses (All Teams)

The homepage will provide entry point to the application, as well as a quick overview of each team

  • List all teams, as links to their team response page
  • Show small overview for each team
  • Time Grid. The primary data visualisation for the homepage, is a grid, with row for each team, and column for each day, coloured by response.

Admin Dashboard

Allows team admin to modify certain application settings and maintain the team member list

  • Should be secured, only accessible using admin credentials
  • Should allow the admin to modify when emails are sent out (times and days)
  • Should allow admin to add and remove team email addresses on the distribution list

Research

Licensing Summary

Happy App is licensed under the Fair Source 5 License. It is neither open nor closed source, the code can be viewed by anyone, but it can not be used, without written permission for any organisation over 5 users. See http://fair.io/ for more information.

License

Fair Source License, version 0.9 Copyright © 2017 Alicia Sykes

Licensor: Alicia Sykes

Software: Happy App

Use Limitation: 5 users

License Grant. Licensor hereby grants to each recipient of the Software (“you”) a non-exclusive, non-transferable, royalty-free and fully-paid-up license, under all of the Licensors copyright and patent rights, to use, copy, distribute, prepare derivative works of, publicly perform and display the Software, subject to the Use Limitation and the conditions set forth below.

Use Limitation. The license granted above allows use by up to the number of users per entity set forth above (the “Use Limitation”). For determining the number of users, “you” includes all affiliates, meaning legal entities controlling, controlled by, or under common control with you. If you exceed the Use Limitation, your use is subject to payment of Licensors then-current list price for licenses.

Conditions. Redistribution in source code or other forms must include a copy of this license document to be provided in a reasonable manner. Any redistribution of the Software is only allowed subject to this license.

Trademarks. This license does not grant you any right in the trademarks, service marks, brand names or logos of Licensor.

DISCLAIMER. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OR CONDITION, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. LICENSORS HEREBY DISCLAIM ALL LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE.

Termination. If you violate the terms of this license, your rights will terminate automatically and will not be reinstated without the prior written consent of Licensor. Any such termination will not affect the right of others who may have received copies of the Software from you.

Accessibility

// TODO

Contributing

// TODO

Description
No description provided
Readme 9 MiB
Languages
JavaScript 36.2%
TypeScript 32.9%
SCSS 21.2%
HTML 9.7%