Contents
Watch Demo Video
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
Current Status
Dependencies
Code Quality
Support
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:
- Clone the repo, and
cdinto it yarn installthe npm node dependencies, and frontend dependencies- Connect to mongo,
mongod. See the Getting Started page on MongoDB documentation. - Populate the database with some sample data (optional).
gulp populate-sample-data(See Data section for more info) - Start the development server,
npm run dev. This watches, compiles and refreshes appropriate server and client components.
Production Setup
- Clone or upload the files to your server directory
- Run
yarn, to install the npm and frontend modules - Create a
.envfile in the project root, and populate it like the example below - Setup and start a mongo instance, and configure the port appropriately in the .env
- Build the produciton version, with
npm run buil:prod - Run
npm run testto verify that everything is working as expected - Start the app (using a
foreverorpm2to keep it alive),forever start node server - 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" }
]
}
]
}
]
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']
- Code:
- Error Response:
- Code:
200 - Content:
[]
- Code:
/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)
- Code:
- Error Response:
- Code:
200 - Content:
{}
- Code:
/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)
- Code:
- Error Response:
- Code:
200 - Content:
{}
- Code:
/team-members
Returns all member hashes for each team. Requires authentication.
- URL:
/team-members - Method:
GET - URL Params: none
- Success Response:
- Code:
200 - Content: ``
- Code:
- 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: ``
- Code:
- 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 teamday-breakdown-chart- Breakdown of sentiment results between teams for a given daygrid-chart- High-level overvier of average sentiment for all teamsmessage-chart- Visual display of annomised team-member comments for each teamoverview-chart- Donut chart showing proportions of sentiment for a given teamtime-chart- Shows sentiment over time, for a given team
Tech Stack
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
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
Legal
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 Licensor’s 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 Licensor’s 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







