diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..ba050038
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+app/bower_components
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 00000000..e88f0250
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,494 @@
+// Generated on 2014-05-30 using generator-angular-fullstack 1.4.0
+'use strict';
+
+// # Globbing
+// for performance reasons we're only matching one level down:
+// 'test/spec/{,*/}*.js'
+// use this if you want to recursively match all subfolders:
+// 'test/spec/**/*.js'
+
+process.env.NODE_ENV = process.env.NODE_ENV || 'development';
+var config = require('./lib/config/config');
+
+module.exports = function (grunt) {
+
+ // Load grunt tasks automatically
+ require('load-grunt-tasks')(grunt);
+
+ // Time how long tasks take. Can help when optimizing build times
+ require('time-grunt')(grunt);
+
+ // Define the configuration for all the tasks
+ grunt.initConfig({
+
+ // Project settings
+ yeoman: {
+ // configurable paths
+ app: require('./bower.json').appPath || 'app',
+ dist: 'dist'
+ },
+ express: {
+ options: {
+ port: config.port
+ },
+ dev: {
+ options: {
+ script: 'server.js',
+ debug: true
+ }
+ },
+ prod: {
+ options: {
+ script: 'dist/server.js',
+ node_env: 'production'
+ }
+ }
+ },
+ open: {
+ server: {
+ url: 'http://localhost:<%= express.options.port %>'
+ }
+ },
+ watch: {
+ js: {
+ files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
+ tasks: ['newer:jshint:all'],
+ options: {
+ livereload: true
+ }
+ },
+ mochaTest: {
+ files: ['test/server/{,*/}*.js'],
+ tasks: ['env:test', 'mochaTest']
+ },
+ jsTest: {
+ files: ['test/client/spec/{,*/}*.js'],
+ tasks: ['newer:jshint:test', 'karma']
+ },
+ styles: {
+ files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
+ tasks: ['newer:copy:styles', 'autoprefixer']
+ },
+ gruntfile: {
+ files: ['Gruntfile.js']
+ },
+ livereload: {
+ files: [
+ '<%= yeoman.app %>/views/{,*//*}*.{html,jade}',
+ '{.tmp,<%= yeoman.app %>}/styles/{,*//*}*.css',
+ '{.tmp,<%= yeoman.app %>}/scripts/{,*//*}*.js',
+ '<%= yeoman.app %>/images/{,*//*}*.{png,jpg,jpeg,gif,webp,svg}'
+ ],
+
+ options: {
+ livereload: true
+ }
+ },
+ express: {
+ files: [
+ 'server.js',
+ 'lib/**/*.{js,json}'
+ ],
+ tasks: ['newer:jshint:server', 'express:dev', 'wait'],
+ options: {
+ livereload: true,
+ nospawn: true //Without this option specified express won't be reloaded
+ }
+ }
+ },
+
+ // Empties folders to start fresh
+ clean: {
+ dist: {
+ files: [{
+ dot: true,
+ src: [
+ '.tmp',
+ '<%= yeoman.dist %>/*',
+ '!<%= yeoman.dist %>/.git*',
+ '!<%= yeoman.dist %>/Procfile'
+ ]
+ }]
+ },
+ heroku: {
+ files: [{
+ dot: true,
+ src: [
+ 'heroku/*',
+ '!heroku/.git*',
+ '!heroku/Procfile'
+ ]
+ }]
+ },
+ server: '.tmp'
+ },
+
+ // Add vendor prefixed styles
+ autoprefixer: {
+ options: {
+ browsers: ['last 1 version']
+ },
+ dist: {
+ files: [{
+ expand: true,
+ cwd: '.tmp/styles/',
+ src: '{,*/}*.css',
+ dest: '.tmp/styles/'
+ }]
+ }
+ },
+
+ // Debugging with node inspector
+ 'node-inspector': {
+ custom: {
+ options: {
+ 'web-host': 'localhost'
+ }
+ }
+ },
+
+ // Use nodemon to run server in debug mode with an initial breakpoint
+ nodemon: {
+ debug: {
+ script: 'server.js',
+ options: {
+ nodeArgs: ['--debug-brk'],
+ env: {
+ PORT: config.port
+ },
+ callback: function (nodemon) {
+ nodemon.on('log', function (event) {
+ console.log(event.colour);
+ });
+
+ // opens browser on initial server start
+ nodemon.on('config:update', function () {
+ setTimeout(function () {
+ require('open')('http://localhost:8080/debug?port=5858');
+ }, 500);
+ });
+ }
+ }
+ }
+ },
+
+ // Automatically inject Bower components into the app
+ 'bower-install': {
+ app: {
+ html: '<%= yeoman.app %>/views/index.html',
+ ignorePath: '<%= yeoman.app %>/'
+ }
+ },
+
+ // Renames files for browser caching purposes
+ rev: {
+ dist: {
+ files: {
+ src: [
+ '<%= yeoman.dist %>/public/scripts/{,*/}*.js',
+ '<%= yeoman.dist %>/public/styles/{,*/}*.css',
+ '<%= yeoman.dist %>/public/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
+ '<%= yeoman.dist %>/public/styles/fonts/*'
+ ]
+ }
+ }
+ },
+
+ // Reads HTML for usemin blocks to enable smart builds that automatically
+ // concat, minify and revision files. Creates configurations in memory so
+ // additional tasks can operate on them
+ useminPrepare: {
+ html: ['<%= yeoman.app %>/views/index.html',
+ '<%= yeoman.app %>/views/index.jade'],
+ options: {
+ dest: '<%= yeoman.dist %>/public'
+ }
+ },
+
+ // Performs rewrites based on rev and the useminPrepare configuration
+ usemin: {
+ html: ['<%= yeoman.dist %>/views/{,*/}*.html',
+ '<%= yeoman.dist %>/views/{,*/}*.jade'],
+ css: ['<%= yeoman.dist %>/public/styles/{,*/}*.css'],
+ options: {
+ assetsDirs: ['<%= yeoman.dist %>/public']
+ }
+ },
+
+ // The following *-min tasks produce minified files in the dist folder
+ imagemin: {
+ options : {
+ cache: false
+ },
+ dist: {
+ files: [{
+ expand: true,
+ cwd: '<%= yeoman.app %>/images',
+ src: '{,*/}*.{png,jpg,jpeg,gif}',
+ dest: '<%= yeoman.dist %>/public/images'
+ }]
+ }
+ },
+
+ svgmin: {
+ dist: {
+ files: [{
+ expand: true,
+ cwd: '<%= yeoman.app %>/images',
+ src: '{,*/}*.svg',
+ dest: '<%= yeoman.dist %>/public/images'
+ }]
+ }
+ },
+
+ htmlmin: {
+ dist: {
+ options: {
+ //collapseWhitespace: true,
+ //collapseBooleanAttributes: true,
+ //removeCommentsFromCDATA: true,
+ //removeOptionalTags: true
+ },
+ files: [{
+ expand: true,
+ cwd: '<%= yeoman.app %>/views',
+ src: ['*.html', 'partials/**/*.html'],
+ dest: '<%= yeoman.dist %>/views'
+ }]
+ }
+ },
+
+ // Allow the use of non-minsafe AngularJS files. Automatically makes it
+ // minsafe compatible so Uglify does not destroy the ng references
+ ngmin: {
+ dist: {
+ files: [{
+ expand: true,
+ cwd: '.tmp/concat/scripts',
+ src: '*.js',
+ dest: '.tmp/concat/scripts'
+ }]
+ }
+ },
+
+ // Replace Google CDN references
+ cdnify: {
+ dist: {
+ html: ['<%= yeoman.dist %>/views/*.html']
+ }
+ },
+
+ // Copies remaining files to places other tasks can use
+ copy: {
+ dist: {
+ files: [{
+ expand: true,
+ dot: true,
+ cwd: '<%= yeoman.app %>',
+ dest: '<%= yeoman.dist %>/public',
+ src: [
+ '*.{ico,png,txt}',
+ '.htaccess',
+ 'bower_components/**/*',
+ 'images/{,*/}*.{webp}',
+ 'fonts/**/*'
+ ]
+ }, {
+ expand: true,
+ dot: true,
+ cwd: '<%= yeoman.app %>/views',
+ dest: '<%= yeoman.dist %>/views',
+ src: '**/*.jade'
+ }, {
+ expand: true,
+ cwd: '.tmp/images',
+ dest: '<%= yeoman.dist %>/public/images',
+ src: ['generated/*']
+ }, {
+ expand: true,
+ dest: '<%= yeoman.dist %>',
+ src: [
+ 'package.json',
+ 'server.js',
+ 'lib/**/*'
+ ]
+ }]
+ },
+ styles: {
+ expand: true,
+ cwd: '<%= yeoman.app %>/styles',
+ dest: '.tmp/styles/',
+ src: '{,*/}*.css'
+ }
+ },
+
+ // Run some tasks in parallel to speed up the build process
+ concurrent: {
+ server: [
+ 'copy:styles'
+ ],
+ test: [
+ 'copy:styles'
+ ],
+ debug: {
+ tasks: [
+ 'nodemon',
+ 'node-inspector'
+ ],
+ options: {
+ logConcurrentOutput: true
+ }
+ },
+ dist: [
+ 'copy:styles',
+ 'imagemin',
+ 'svgmin',
+ 'htmlmin'
+ ]
+ },
+
+ // By default, your `index.html`'s will take care of
+ // minification. These next options are pre-configured if you do not wish
+ // to use the Usemin blocks.
+ // cssmin: {
+ // dist: {
+ // files: {
+ // '<%= yeoman.dist %>/styles/main.css': [
+ // '.tmp/styles/{,*/}*.css',
+ // '<%= yeoman.app %>/styles/{,*/}*.css'
+ // ]
+ // }
+ // }
+ // },
+ // uglify: {
+ // dist: {
+ // files: {
+ // '<%= yeoman.dist %>/scripts/scripts.js': [
+ // '<%= yeoman.dist %>/scripts/scripts.js'
+ // ]
+ // }
+ // }
+ // },
+ // concat: {
+ // dist: {}
+ // },
+
+ // Test settings
+ karma: {
+ unit: {
+ configFile: 'karma.conf.js',
+ singleRun: true
+ }
+ },
+
+ mochaTest: {
+ options: {
+ reporter: 'spec'
+ },
+ src: ['test/server/**/*.js']
+ },
+
+ env: {
+ test: {
+ NODE_ENV: 'test'
+ }
+ }
+ });
+
+ // Used for delaying livereload until after server has restarted
+ grunt.registerTask('wait', function () {
+ grunt.log.ok('Waiting for server reload...');
+
+ var done = this.async();
+
+ setTimeout(function () {
+ grunt.log.writeln('Done waiting!');
+ done();
+ }, 500);
+ });
+
+ grunt.registerTask('express-keepalive', 'Keep grunt running', function() {
+ this.async();
+ });
+
+ grunt.registerTask('serve', function (target) {
+ if (target === 'dist') {
+ return grunt.task.run(['build', 'express:prod', 'open', 'express-keepalive']);
+ }
+
+ if (target === 'debug') {
+ return grunt.task.run([
+ 'clean:server',
+ 'bower-install',
+ 'concurrent:server',
+ 'autoprefixer',
+ 'concurrent:debug'
+ ]);
+ }
+
+ grunt.task.run([
+ 'clean:server',
+ 'bower-install',
+ 'concurrent:server',
+ 'autoprefixer',
+ 'express:dev',
+ 'open',
+ 'watch'
+ ]);
+ });
+
+ grunt.registerTask('server', function () {
+ grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
+ grunt.task.run(['serve']);
+ });
+
+ grunt.registerTask('test', function(target) {
+ if (target === 'server') {
+ return grunt.task.run([
+ 'env:test',
+ 'mochaTest'
+ ]);
+ }
+
+ else if (target === 'client') {
+ return grunt.task.run([
+ 'clean:server',
+ 'concurrent:test',
+ 'autoprefixer',
+ 'karma'
+ ]);
+ }
+
+ else grunt.task.run([
+ 'test:server',
+ 'test:client'
+ ]);
+ });
+
+ grunt.registerTask('build', [
+ 'clean:dist',
+ 'bower-install',
+ 'useminPrepare',
+ 'concurrent:dist',
+ 'autoprefixer',
+ 'concat',
+ 'ngmin',
+ 'copy:dist',
+ 'cdnify',
+ 'cssmin',
+ 'uglify',
+ 'rev',
+ 'usemin'
+ ]);
+
+ grunt.registerTask('heroku', function () {
+ grunt.log.warn('The `heroku` task has been deprecated. Use `grunt build` to build for deployment.');
+ grunt.task.run(['build']);
+ });
+
+ grunt.registerTask('default', [
+ 'newer:jshint',
+ 'test',
+ 'build'
+ ]);
+};
diff --git a/README.md b/README.md
index 7fa9f715..60693249 100644
--- a/README.md
+++ b/README.md
@@ -14,3 +14,25 @@ section 5: link all buttons (use current donate.sanguinebio.com site for links)
Use donate.sanguinebio.com for copy and reference.
let me know if you have any questions feel free to email or call keaton@sangiunebio.com, mmarple@sanguinebio.com.
+
+
+
+
+
+*************************************
+=====================================
+*************************************
+
+
+Teja Rudraraju - NOTES:
+
+ To start app from Terminal:
+
+ 1) "npm install"
+ 2) "bower install"
+
+ 3) "grunt serve"
+
+ PORT: 9000
+
+**********
\ No newline at end of file
diff --git a/Sanguine_mobile.psd b/Sanguine_mobile.psd
deleted file mode 100755
index 2f23954c..00000000
Binary files a/Sanguine_mobile.psd and /dev/null differ
diff --git a/app/.buildignore b/app/.buildignore
new file mode 100644
index 00000000..fc98b8eb
--- /dev/null
+++ b/app/.buildignore
@@ -0,0 +1 @@
+*.coffee
\ No newline at end of file
diff --git a/app/.htaccess b/app/.htaccess
new file mode 100644
index 00000000..cb84cb91
--- /dev/null
+++ b/app/.htaccess
@@ -0,0 +1,543 @@
+# Apache Configuration File
+
+# (!) Using `.htaccess` files slows down Apache, therefore, if you have access
+# to the main server config file (usually called `httpd.conf`), you should add
+# this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html.
+
+# ##############################################################################
+# # CROSS-ORIGIN RESOURCE SHARING (CORS) #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | Cross-domain AJAX requests |
+# ------------------------------------------------------------------------------
+
+# Enable cross-origin AJAX requests.
+# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
+# http://enable-cors.org/
+
+#
+# Header set Access-Control-Allow-Origin "*"
+#
+
+# ------------------------------------------------------------------------------
+# | CORS-enabled images |
+# ------------------------------------------------------------------------------
+
+# Send the CORS header for images when browsers request it.
+# https://developer.mozilla.org/en/CORS_Enabled_Image
+# http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html
+# http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/
+
+
+
+
+ SetEnvIf Origin ":" IS_CORS
+ Header set Access-Control-Allow-Origin "*" env=IS_CORS
+
+
+
+
+# ------------------------------------------------------------------------------
+# | Web fonts access |
+# ------------------------------------------------------------------------------
+
+# Allow access from all domains for web fonts
+
+
+
+ Header set Access-Control-Allow-Origin "*"
+
+
+
+
+# ##############################################################################
+# # ERRORS #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | 404 error prevention for non-existing redirected folders |
+# ------------------------------------------------------------------------------
+
+# Prevent Apache from returning a 404 error for a rewrite if a directory
+# with the same name does not exist.
+# http://httpd.apache.org/docs/current/content-negotiation.html#multiviews
+# http://www.webmasterworld.com/apache/3808792.htm
+
+Options -MultiViews
+
+# ------------------------------------------------------------------------------
+# | Custom error messages / pages |
+# ------------------------------------------------------------------------------
+
+# You can customize what Apache returns to the client in case of an error (see
+# http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.:
+
+ErrorDocument 404 /404.html
+
+
+# ##############################################################################
+# # INTERNET EXPLORER #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | Better website experience |
+# ------------------------------------------------------------------------------
+
+# Force IE to render pages in the highest available mode in the various
+# cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf.
+
+
+ Header set X-UA-Compatible "IE=edge"
+ # `mod_headers` can't match based on the content-type, however, we only
+ # want to send this header for HTML pages and not for the other resources
+
+ Header unset X-UA-Compatible
+
+
+
+# ------------------------------------------------------------------------------
+# | Cookie setting from iframes |
+# ------------------------------------------------------------------------------
+
+# Allow cookies to be set from iframes in IE.
+
+#
+# Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\""
+#
+
+# ------------------------------------------------------------------------------
+# | Screen flicker |
+# ------------------------------------------------------------------------------
+
+# Stop screen flicker in IE on CSS rollovers (this only works in
+# combination with the `ExpiresByType` directives for images from below).
+
+# BrowserMatch "MSIE" brokenvary=1
+# BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1
+# BrowserMatch "Opera" !brokenvary
+# SetEnvIf brokenvary 1 force-no-vary
+
+
+# ##############################################################################
+# # MIME TYPES AND ENCODING #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | Proper MIME types for all files |
+# ------------------------------------------------------------------------------
+
+
+
+ # Audio
+ AddType audio/mp4 m4a f4a f4b
+ AddType audio/ogg oga ogg
+
+ # JavaScript
+ # Normalize to standard type (it's sniffed in IE anyways):
+ # http://tools.ietf.org/html/rfc4329#section-7.2
+ AddType application/javascript js jsonp
+ AddType application/json json
+
+ # Video
+ AddType video/mp4 mp4 m4v f4v f4p
+ AddType video/ogg ogv
+ AddType video/webm webm
+ AddType video/x-flv flv
+
+ # Web fonts
+ AddType application/font-woff woff
+ AddType application/vnd.ms-fontobject eot
+
+ # Browsers usually ignore the font MIME types and sniff the content,
+ # however, Chrome shows a warning if other MIME types are used for the
+ # following fonts.
+ AddType application/x-font-ttf ttc ttf
+ AddType font/opentype otf
+
+ # Make SVGZ fonts work on iPad:
+ # https://twitter.com/FontSquirrel/status/14855840545
+ AddType image/svg+xml svg svgz
+ AddEncoding gzip svgz
+
+ # Other
+ AddType application/octet-stream safariextz
+ AddType application/x-chrome-extension crx
+ AddType application/x-opera-extension oex
+ AddType application/x-shockwave-flash swf
+ AddType application/x-web-app-manifest+json webapp
+ AddType application/x-xpinstall xpi
+ AddType application/xml atom rdf rss xml
+ AddType image/webp webp
+ AddType image/x-icon ico
+ AddType text/cache-manifest appcache manifest
+ AddType text/vtt vtt
+ AddType text/x-component htc
+ AddType text/x-vcard vcf
+
+
+
+# ------------------------------------------------------------------------------
+# | UTF-8 encoding |
+# ------------------------------------------------------------------------------
+
+# Use UTF-8 encoding for anything served as `text/html` or `text/plain`.
+AddDefaultCharset utf-8
+
+# Force UTF-8 for certain file formats.
+
+ AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml
+
+
+
+# ##############################################################################
+# # URL REWRITES #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | Rewrite engine |
+# ------------------------------------------------------------------------------
+
+# Turning on the rewrite engine and enabling the `FollowSymLinks` option is
+# necessary for the following directives to work.
+
+# If your web host doesn't allow the `FollowSymlinks` option, you may need to
+# comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the
+# performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks
+
+# Also, some cloud hosting services require `RewriteBase` to be set:
+# http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site
+
+
+ Options +FollowSymlinks
+ # Options +SymLinksIfOwnerMatch
+ RewriteEngine On
+ # RewriteBase /
+
+
+# ------------------------------------------------------------------------------
+# | Suppressing / Forcing the "www." at the beginning of URLs |
+# ------------------------------------------------------------------------------
+
+# The same content should never be available under two different URLs especially
+# not with and without "www." at the beginning. This can cause SEO problems
+# (duplicate content), therefore, you should choose one of the alternatives and
+# redirect the other one.
+
+# By default option 1 (no "www.") is activated:
+# http://no-www.org/faq.php?q=class_b
+
+# If you'd prefer to use option 2, just comment out all the lines from option 1
+# and uncomment the ones from option 2.
+
+# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME!
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+# Option 1: rewrite www.example.com → example.com
+
+
+ RewriteCond %{HTTPS} !=on
+ RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
+ RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+# Option 2: rewrite example.com → www.example.com
+
+# Be aware that the following might not be a good idea if you use "real"
+# subdomains for certain parts of your website.
+
+#
+# RewriteCond %{HTTPS} !=on
+# RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
+# RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
+#
+
+
+# ##############################################################################
+# # SECURITY #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | Content Security Policy (CSP) |
+# ------------------------------------------------------------------------------
+
+# You can mitigate the risk of cross-site scripting and other content-injection
+# attacks by setting a Content Security Policy which whitelists trusted sources
+# of content for your site.
+
+# The example header below allows ONLY scripts that are loaded from the current
+# site's origin (no inline scripts, no CDN, etc). This almost certainly won't
+# work as-is for your site!
+
+# To get all the details you'll need to craft a reasonable policy for your site,
+# read: http://html5rocks.com/en/tutorials/security/content-security-policy (or
+# see the specification: http://w3.org/TR/CSP).
+
+#
+# Header set Content-Security-Policy "script-src 'self'; object-src 'self'"
+#
+# Header unset Content-Security-Policy
+#
+#
+
+# ------------------------------------------------------------------------------
+# | File access |
+# ------------------------------------------------------------------------------
+
+# Block access to directories without a default document.
+# Usually you should leave this uncommented because you shouldn't allow anyone
+# to surf through every directory on your server (which may includes rather
+# private places like the CMS's directories).
+
+
+ Options -Indexes
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+# Block access to hidden files and directories.
+# This includes directories used by version control systems such as Git and SVN.
+
+
+ RewriteCond %{SCRIPT_FILENAME} -d [OR]
+ RewriteCond %{SCRIPT_FILENAME} -f
+ RewriteRule "(^|/)\." - [F]
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+# Block access to backup and source files.
+# These files may be left by some text editors and can pose a great security
+# danger when anyone has access to them.
+
+
+ Order allow,deny
+ Deny from all
+ Satisfy All
+
+
+# ------------------------------------------------------------------------------
+# | Secure Sockets Layer (SSL) |
+# ------------------------------------------------------------------------------
+
+# Rewrite secure requests properly to prevent SSL certificate warnings, e.g.:
+# prevent `https://www.example.com` when your certificate only allows
+# `https://secure.example.com`.
+
+#
+# RewriteCond %{SERVER_PORT} !^443
+# RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L]
+#
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+# Force client-side SSL redirection.
+
+# If a user types "example.com" in his browser, the above rule will redirect him
+# to the secure version of the site. That still leaves a window of opportunity
+# (the initial HTTP connection) for an attacker to downgrade or redirect the
+# request. The following header ensures that browser will ONLY connect to your
+# server via HTTPS, regardless of what the users type in the address bar.
+# http://www.html5rocks.com/en/tutorials/security/transport-layer-security/
+
+#
+# Header set Strict-Transport-Security max-age=16070400;
+#
+
+# ------------------------------------------------------------------------------
+# | Server software information |
+# ------------------------------------------------------------------------------
+
+# Avoid displaying the exact Apache version number, the description of the
+# generic OS-type and the information about Apache's compiled-in modules.
+
+# ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`!
+
+# ServerTokens Prod
+
+
+# ##############################################################################
+# # WEB PERFORMANCE #
+# ##############################################################################
+
+# ------------------------------------------------------------------------------
+# | Compression |
+# ------------------------------------------------------------------------------
+
+
+
+ # Force compression for mangled headers.
+ # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping
+
+
+ SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
+ RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
+
+
+
+ # Compress all output labeled with one of the following MIME-types
+ # (for Apache versions below 2.3.7, you don't need to enable `mod_filter`
+ # and can remove the `` and ` ` lines
+ # as `AddOutputFilterByType` is still in the core directives).
+
+ AddOutputFilterByType DEFLATE application/atom+xml \
+ application/javascript \
+ application/json \
+ application/rss+xml \
+ application/vnd.ms-fontobject \
+ application/x-font-ttf \
+ application/x-web-app-manifest+json \
+ application/xhtml+xml \
+ application/xml \
+ font/opentype \
+ image/svg+xml \
+ image/x-icon \
+ text/css \
+ text/html \
+ text/plain \
+ text/x-component \
+ text/xml
+
+
+
+
+# ------------------------------------------------------------------------------
+# | Content transformations |
+# ------------------------------------------------------------------------------
+
+# Prevent some of the mobile network providers from modifying the content of
+# your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5.
+
+#
+# Header set Cache-Control "no-transform"
+#
+
+# ------------------------------------------------------------------------------
+# | ETag removal |
+# ------------------------------------------------------------------------------
+
+# Since we're sending far-future expires headers (see below), ETags can
+# be removed: http://developer.yahoo.com/performance/rules.html#etags.
+
+# `FileETag None` is not enough for every server.
+
+ Header unset ETag
+
+
+FileETag None
+
+# ------------------------------------------------------------------------------
+# | Expires headers (for better cache control) |
+# ------------------------------------------------------------------------------
+
+# The following expires headers are set pretty far in the future. If you don't
+# control versioning with filename-based cache busting, consider lowering the
+# cache time for resources like CSS and JS to something like 1 week.
+
+
+
+ ExpiresActive on
+ ExpiresDefault "access plus 1 month"
+
+ # CSS
+ ExpiresByType text/css "access plus 1 year"
+
+ # Data interchange
+ ExpiresByType application/json "access plus 0 seconds"
+ ExpiresByType application/xml "access plus 0 seconds"
+ ExpiresByType text/xml "access plus 0 seconds"
+
+ # Favicon (cannot be renamed!)
+ ExpiresByType image/x-icon "access plus 1 week"
+
+ # HTML components (HTCs)
+ ExpiresByType text/x-component "access plus 1 month"
+
+ # HTML
+ ExpiresByType text/html "access plus 0 seconds"
+
+ # JavaScript
+ ExpiresByType application/javascript "access plus 1 year"
+
+ # Manifest files
+ ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
+ ExpiresByType text/cache-manifest "access plus 0 seconds"
+
+ # Media
+ ExpiresByType audio/ogg "access plus 1 month"
+ ExpiresByType image/gif "access plus 1 month"
+ ExpiresByType image/jpeg "access plus 1 month"
+ ExpiresByType image/png "access plus 1 month"
+ ExpiresByType video/mp4 "access plus 1 month"
+ ExpiresByType video/ogg "access plus 1 month"
+ ExpiresByType video/webm "access plus 1 month"
+
+ # Web feeds
+ ExpiresByType application/atom+xml "access plus 1 hour"
+ ExpiresByType application/rss+xml "access plus 1 hour"
+
+ # Web fonts
+ ExpiresByType application/font-woff "access plus 1 month"
+ ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
+ ExpiresByType application/x-font-ttf "access plus 1 month"
+ ExpiresByType font/opentype "access plus 1 month"
+ ExpiresByType image/svg+xml "access plus 1 month"
+
+
+
+# ------------------------------------------------------------------------------
+# | Filename-based cache busting |
+# ------------------------------------------------------------------------------
+
+# If you're not using a build process to manage your filename version revving,
+# you might want to consider enabling the following directives to route all
+# requests such as `/css/style.12345.css` to `/css/style.css`.
+
+# To understand why this is important and a better idea than `*.css?v231`, read:
+# http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring
+
+#
+# RewriteCond %{REQUEST_FILENAME} !-f
+# RewriteCond %{REQUEST_FILENAME} !-d
+# RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L]
+#
+
+# ------------------------------------------------------------------------------
+# | File concatenation |
+# ------------------------------------------------------------------------------
+
+# Allow concatenation from within specific CSS and JS files, e.g.:
+# Inside of `script.combined.js` you could have
+#
+#
+# and they would be included into this single file.
+
+#
+#
+# Options +Includes
+# AddOutputFilterByType INCLUDES application/javascript application/json
+# SetOutputFilter INCLUDES
+#
+#
+# Options +Includes
+# AddOutputFilterByType INCLUDES text/css
+# SetOutputFilter INCLUDES
+#
+#
+
+# ------------------------------------------------------------------------------
+# | Persistent connections |
+# ------------------------------------------------------------------------------
+
+# Allow multiple requests to be sent over the same TCP connection:
+# http://httpd.apache.org/docs/current/en/mod/core.html#keepalive.
+
+# Enable if you serve a lot of static content but, be aware of the
+# possible disadvantages!
+
+#
+# Header set Connection Keep-Alive
+#
diff --git a/app/favicon.ico b/app/favicon.ico
new file mode 100644
index 00000000..65279053
Binary files /dev/null and b/app/favicon.ico differ
diff --git a/app/images/donate_image.png b/app/images/donate_image.png
new file mode 100644
index 00000000..d8a800ba
Binary files /dev/null and b/app/images/donate_image.png differ
diff --git a/app/images/how_bkg.png b/app/images/how_bkg.png
new file mode 100644
index 00000000..eb5fac79
Binary files /dev/null and b/app/images/how_bkg.png differ
diff --git a/app/images/join_image_1.png b/app/images/join_image_1.png
new file mode 100644
index 00000000..36392815
Binary files /dev/null and b/app/images/join_image_1.png differ
diff --git a/app/images/la_bkg.jpg b/app/images/la_bkg.jpg
new file mode 100644
index 00000000..e6a97c22
Binary files /dev/null and b/app/images/la_bkg.jpg differ
diff --git a/app/images/play_btn_orange.png b/app/images/play_btn_orange.png
new file mode 100644
index 00000000..dcc3d3a9
Binary files /dev/null and b/app/images/play_btn_orange.png differ
diff --git a/app/images/sanguine_logo_white.png b/app/images/sanguine_logo_white.png
new file mode 100644
index 00000000..bc4f84af
Binary files /dev/null and b/app/images/sanguine_logo_white.png differ
diff --git a/app/images/schedule_image_1.png b/app/images/schedule_image_1.png
new file mode 100644
index 00000000..1d22c3d1
Binary files /dev/null and b/app/images/schedule_image_1.png differ
diff --git a/app/images/signup_image_1.png b/app/images/signup_image_1.png
new file mode 100644
index 00000000..4d54acca
Binary files /dev/null and b/app/images/signup_image_1.png differ
diff --git a/app/images/urls.txt b/app/images/urls.txt
new file mode 100644
index 00000000..1f12e929
--- /dev/null
+++ b/app/images/urls.txt
@@ -0,0 +1,30 @@
+"tree back" = https://d2xrs3qqoda7l2.cloudfront.net/asset/la_bkg.jpg
+"back pattern"= https://d2xrs3qqoda7l2.cloudfront.net/asset/bkg_pattern.png
+
+"18+" = https://d2xrs3qqoda7l2.cloudfront.net/asset/18.png
+"test tubes" = https://d2xrs3qqoda7l2.cloudfront.net/asset/tubes.png
+"calendar" = https://d2xrs3qqoda7l2.cloudfront.net/asset/calendar.png
+"where" = https://d2xrs3qqoda7l2.cloudfront.net/asset/house.png
+"steth scope" = https://d2xrs3qqoda7l2.cloudfront.net/asset/steth.png
+"require" = https://d2xrs3qqoda7l2.cloudfront.net/asset/study.png
+
+
+"blood circle"= https://d2xrs3qqoda7l2.cloudfront.net/asset/blood_circle.png
+
+
+"left-arrow" = https://d2xrs3qqoda7l2.cloudfront.net/asset/how_arrow_left.png
+"right-arrow" = https://d2xrs3qqoda7l2.cloudfront.net/asset/how_arrow_right.png
+
+
+"linkedin" = https://d2xrs3qqoda7l2.cloudfront.net/asset/linkedin_connectw.png
+"blog" = https://d2xrs3qqoda7l2.cloudfront.net/asset/blogspot_connectw.png
+"facebook" = https://d2xrs3qqoda7l2.cloudfront.net/asset/fb_connectw.png
+"vimeo" = https://d2xrs3qqoda7l2.cloudfront.net/asset/vimeo_connectw.png
+"twitter" = https://d2xrs3qqoda7l2.cloudfront.net/asset/twitter_connectw.png
+
+
+"linkedin" = https://www.linkedin.com/company/1004902
+"blog" = http://blog.sanguinebio.com/
+"facebook" = https://www.facebook.com/PatientsLeadingResearch
+"vimeo" = https://vimeo.com/sanguinebio
+"twitter" = https://twitter.com/sanguinebio
\ No newline at end of file
diff --git a/app/images/yeoman.png b/app/images/yeoman.png
new file mode 100644
index 00000000..92497add
Binary files /dev/null and b/app/images/yeoman.png differ
diff --git a/app/robots.txt b/app/robots.txt
new file mode 100644
index 00000000..94174950
--- /dev/null
+++ b/app/robots.txt
@@ -0,0 +1,3 @@
+# robotstxt.org
+
+User-agent: *
diff --git a/app/scripts/app.js b/app/scripts/app.js
new file mode 100644
index 00000000..d6c1b4cd
--- /dev/null
+++ b/app/scripts/app.js
@@ -0,0 +1,27 @@
+'use strict';
+
+var sanguineTestApp = angular.module('sanguineTestApp', [
+ 'ngRoute',
+ 'ui.bootstrap'
+]);
+
+sanguineTestApp.config(function ($routeProvider, $locationProvider) {
+ $routeProvider
+ .when('/', {
+ templateUrl: 'partials/main',
+ })
+ .otherwise({
+ redirectTo: '/'
+ });
+
+ $locationProvider.html5Mode(true);
+ });
+
+sanguineTestApp.directive('href', function() {
+ return {
+ compile: function(element) {
+ element.attr('target', '_blank');
+ }
+ };
+});
+
diff --git a/app/scripts/controllers/connect.js b/app/scripts/controllers/connect.js
new file mode 100644
index 00000000..7703f22a
--- /dev/null
+++ b/app/scripts/controllers/connect.js
@@ -0,0 +1,29 @@
+'use strict';
+
+sanguineTestApp.controller('connectControl', function ($scope, $http) {
+
+ $scope.connectItems = [
+ {
+ src: "https://twitter.com/sanguinebio",
+ imgSrc: "https://d2xrs3qqoda7l2.cloudfront.net/asset/twitter_connectw.png"
+ },
+ {
+ src: "https://vimeo.com/sanguinebio",
+ imgSrc: "https://d2xrs3qqoda7l2.cloudfront.net/asset/vimeo_connectw.png"
+ },
+ {
+ src: "https://www.facebook.com/PatientsLeadingResearch",
+ imgSrc: "https://d2xrs3qqoda7l2.cloudfront.net/asset/fb_connectw.png"
+ },
+ {
+ src: "http://blog.sanguinebio.com/",
+ imgSrc: "https://d2xrs3qqoda7l2.cloudfront.net/asset/blogspot_connectw.png"
+ },
+ {
+ src: "https://www.linkedin.com/company/1004902",
+ imgSrc: "https://d2xrs3qqoda7l2.cloudfront.net/asset/linkedin_connectw.png"
+ }
+
+ ];
+
+ });
\ No newline at end of file
diff --git a/app/scripts/controllers/footer.js b/app/scripts/controllers/footer.js
new file mode 100644
index 00000000..0d436e55
--- /dev/null
+++ b/app/scripts/controllers/footer.js
@@ -0,0 +1,5 @@
+'use strict';
+
+sanguineTestApp.controller('footerControl', function ($scope, $http) {
+
+});
\ No newline at end of file
diff --git a/app/scripts/controllers/form.js b/app/scripts/controllers/form.js
new file mode 100644
index 00000000..5a9202bf
--- /dev/null
+++ b/app/scripts/controllers/form.js
@@ -0,0 +1,5 @@
+'use strict';
+
+sanguineTestApp.controller('formControl', function ($scope, $http) {
+
+});
\ No newline at end of file
diff --git a/app/scripts/controllers/main.js b/app/scripts/controllers/main.js
new file mode 100644
index 00000000..5361f3af
--- /dev/null
+++ b/app/scripts/controllers/main.js
@@ -0,0 +1,5 @@
+'use strict';
+
+sanguineTestApp.controller('mainControl', function ($scope, $http) {
+
+});
diff --git a/app/scripts/controllers/process.js b/app/scripts/controllers/process.js
new file mode 100644
index 00000000..7dd9a56c
--- /dev/null
+++ b/app/scripts/controllers/process.js
@@ -0,0 +1,64 @@
+'use strict';
+
+sanguineTestApp.controller('processControl', function ($scope, $http, $interval) {
+
+ var slides = $scope.slides = [
+ {
+ step: 1,
+ title: 'step one: Sign Up',
+ desc: 'Start advancing research by signing up online or calling for more information. A study coordinator will call you to explain the donation process, answer any questions and collect some basic health information.',
+ imgSrc: 'images/signup_image_1.png'
+ },
+ {
+ step: 2,
+ title: 'step two: Schedule',
+ desc: 'After you are screened, you will join our list of eligible donors! We will work to match you to a current research study. As soon as we do, we will call to schedule a convenient time for you to donate.',
+ imgSrc: 'images/schedule_image_1.png'
+ },
+ {
+ step: 3,
+ title: 'step three: Donate',
+ desc: 'Your appointment takes place in the comfort of your home. During the appointment you will get your blood drawn and receive compensation. Our patient advocates (P.A.’s) are expert phlebotomists, dedicated researchers and true patient advocates.',
+ imgSrc: 'images/donate_image.png'
+ },
+ {
+ step: 4,
+ title: 'step four: Join',
+ desc: 'It all starts with YOU!',
+ imgSrc: 'images/join_image_1.png'
+ }
+ ];
+
+ $scope.stepIndex = 1;
+ $scope.currentSlide = slides[0];
+
+ $scope.$watch('stepIndex', function() {
+ $scope.currentSlide = slides[$scope.stepIndex-1];
+ });
+
+ $scope.nextStep = function() {
+ if($scope.stepIndex===4) {
+ $scope.stepIndex=1;
+ }
+ else {
+ $scope.stepIndex++;
+ }
+ };
+
+ $scope.prevStep = function() {
+ if($scope.stepIndex===1) {
+ $scope.stepIndex=4;
+ }
+ else {
+ $scope.stepIndex--;
+ }
+ };
+
+ $scope.stepLoop = function() {
+ $scope.nextStep();
+ console.log("test: ", $scope.stepIndex);
+ };
+
+ $scope.initLoop = $interval($scope.stepLoop, 8000);
+
+ });
\ No newline at end of file
diff --git a/app/scripts/controllers/question.js b/app/scripts/controllers/question.js
new file mode 100644
index 00000000..96074db0
--- /dev/null
+++ b/app/scripts/controllers/question.js
@@ -0,0 +1,64 @@
+'use strict';
+
+sanguineTestApp.controller('questionControl', function ($scope, $http, $modal) {
+
+ $scope.questionContent = [
+ {
+ title: 'Who?',
+ desc: 'Anyone over 18 years of age',
+ imgSrc: 'https://d2xrs3qqoda7l2.cloudfront.net/asset/18.png'
+ },
+ {
+ title: 'What?',
+ desc: '6 tbsp of blood (less than 1/5 of a blood donation)',
+ imgSrc: 'https://d2xrs3qqoda7l2.cloudfront.net/asset/tubes.png'
+ },
+ {
+ title: 'When?',
+ desc: 'You decide. We work with your schedule',
+ imgSrc: 'https://d2xrs3qqoda7l2.cloudfront.net/asset/calendar.png'
+ },
+ {
+ title: 'Where?',
+ desc: 'The comfort of your own home. We come to you',
+ imgSrc: 'https://d2xrs3qqoda7l2.cloudfront.net/asset/house.png'
+ },
+ {
+ title: 'Why?',
+ desc: 'Because medicine doesn\'t move forward without you',
+ imgSrc: 'https://d2xrs3qqoda7l2.cloudfront.net/asset/steth.png'
+ },
+ {
+ title: 'Study Requirements',
+ desc: 'Click here to view this study\'s requirements',
+ imgSrc: 'https://d2xrs3qqoda7l2.cloudfront.net/asset/study.png'
+ }
+ ];
+
+
+ $scope.open = function () {
+ console.log(this);
+ if (this.item.title === 'Study Requirements') {
+ var modalInstance = $modal.open({
+ templateUrl: '/partials/requirements-modal.html',
+ controller: 'modalControl',
+ size: 'sm',
+ resolve: {
+ items: function () {
+ return $scope.items;
+ }
+ }
+ });
+ };
+ };
+
+});
+
+
+sanguineTestApp.controller('modalControl', function ($scope, $modalInstance, items) {
+
+ $scope.cancel = function () {
+ $modalInstance.dismiss('cancel');
+ };
+
+});
diff --git a/app/scripts/controllers/splash.js b/app/scripts/controllers/splash.js
new file mode 100644
index 00000000..8936976f
--- /dev/null
+++ b/app/scripts/controllers/splash.js
@@ -0,0 +1,7 @@
+'use strict';
+
+sanguineTestApp.controller('splashControl', function ($scope, $http) {
+
+ $scope.vidCaption = 'Bridging the gap between patients and researchers. Click the play button to learn more about us.';
+
+ });
\ No newline at end of file
diff --git a/app/styles/main.css b/app/styles/main.css
new file mode 100644
index 00000000..f0f16b4c
--- /dev/null
+++ b/app/styles/main.css
@@ -0,0 +1,429 @@
+*, *:before, *:after {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.text-white {
+ color: #FFF;
+}
+
+.text-grey {
+ color: #595959;
+}
+
+.text-orange {
+ color: #FF7825;
+}
+
+.text-blue {
+ color: #286275;
+}
+
+.all-caps {
+ text-transform: uppercase;
+}
+
+
+body {
+ width: 100%;
+ height: 100%;
+ font-family: 'Open Sans Condensed',sans-serif;
+ background-color: #333;
+}
+
+
+#main-container {
+ max-width: 320px;
+ background-image: url(https://d2xrs3qqoda7l2.cloudfront.net/asset/bkg_pattern.png);
+ background-repeat: repeat;
+}
+
+#splash {
+ background: url('/images/la_bkg.jpg');
+ background-position: center center;
+ background-size: cover;
+ padding: 20px 2px 0px 2px;
+}
+
+.logo {
+ padding: 0% 5%;
+ width: 100%;
+}
+
+.video-caption {
+ padding: 5%;
+ margin-bottom: 15px;
+ font-size: 18px;
+ font-weight: 300;
+ text-shadow: 1px 1px 3px #666666;
+ letter-spacing: 1.4px;
+ word-spacing: 2px;
+ text-align: justify;
+ text-align-last: justify;
+ -moz-text-align-last: justify;
+}
+
+.play-btn {
+ text-align: center;
+}
+
+.play-btn img {
+ max-width: 30%;
+ margin: 15% 15%;
+}
+
+.form-border {
+ height: 20px;
+ width: 320px;
+ margin-left: -15px;
+ background: rgba(232,232,232,1);
+ background: -moz-linear-gradient(top, rgba(232,232,232,1) 0%, rgba(224,224,224,1) 75%, rgba(168,168,168,1) 95%, rgba(168,168,168,1) 100%);
+ background: -webkit-gradient(left top, left bottom, color-stop(0%, rgba(232,232,232,1)), color-stop(75%, rgba(224,224,224,1)), color-stop(95%, rgba(168,168,168,1)), color-stop(100%, rgba(168,168,168,1)));
+ background: -webkit-linear-gradient(top, rgba(232,232,232,1) 0%, rgba(224,224,224,1) 75%, rgba(168,168,168,1) 95%, rgba(168,168,168,1) 100%);
+ background: -o-linear-gradient(top, rgba(232,232,232,1) 0%, rgba(224,224,224,1) 75%, rgba(168,168,168,1) 95%, rgba(168,168,168,1) 100%);
+ background: -ms-linear-gradient(top, rgba(232,232,232,1) 0%, rgba(224,224,224,1) 75%, rgba(168,168,168,1) 95%, rgba(168,168,168,1) 100%);
+ background: linear-gradient(to bottom, rgba(232,232,232,1) 0%, rgba(224,224,224,1) 75%, rgba(168,168,168,1) 95%, rgba(168,168,168,1) 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e8e8e8', endColorstr='#a8a8a8', GradientType=0 );
+}
+
+#form {
+ background-color: #BFBFBF;
+}
+
+#form form {
+ background-color: #EBEBEB;
+ margin: 20px auto;
+ padding: 20px;
+ border-radius: 10px;
+}
+
+.form-header, .or-elem, .facebook-btn {
+ background-color: #2A6174;
+ color: #FFF;
+}
+
+.signup-btn, .input-group-addon{
+ background-color: #FF7825;
+ color: #FFF;
+}
+
+.input-group-addon {
+ padding: 0px 6px;
+ min-width: 69px;
+ letter-spacing: 1.1px;
+ text-align: left;
+ border: none;
+ border-radius: none;
+}
+
+#form .form-group {
+ border: 1px solid #FF7825;
+ border-radius: 9px;
+ overflow: hidden;
+ margin-bottom: 5px;
+}
+
+#form .form-control {
+ height: 22px;
+}
+
+#form .btn[disabled] {
+opacity: 1;
+}
+
+.form-header {
+ border-radius: 9px;
+ width: 100%;
+ font-size: 24px;
+ margin-bottom: 20px;
+}
+
+.form-buttons {
+ margin-top: 30px;
+}
+
+.signup-btn {
+ border-radius: 9px;
+ width: 100%;
+ font-size: 22px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+}
+
+.signup-col {
+ padding-right: 0px;
+}
+
+.facebook-btn {
+ height: 33px;
+ border-radius: 9px;
+ width: 100%;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ background-image: url('https://d2xrs3qqoda7l2.cloudfront.net/asset/facebook_btn.png');
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+ cursor: pointer;
+}
+
+.facebook-col {
+ padding-left: 0px;
+}
+
+.or-elem {
+ border-radius: 50px;
+ font-size: 10px;
+ padding: 4px 7px;
+ margin: 5px auto 0px auto;
+
+}
+
+.or-col {
+ padding: 0px;
+ text-align: center;
+}
+
+.header {
+ font-weight: 600;
+ font-size: 23px;
+ margin: 5px 0px 0px 0px;
+ line-height: 28px;
+}
+
+#question .divider {
+ height: 1px;
+ border-top: 2px solid #FF7825;
+ margin: 20px auto 15px auto;
+ width: 60%;
+}
+
+#question .header {
+ padding-right: 0px;
+}
+
+#question .subheader{
+ margin-left: -10px;
+}
+
+#question .header p {
+ text-align: right;
+}
+
+#question .subheader p {
+ font-size: 13px;
+ margin: 16px 0px 13px 0px;
+ padding-right: 10%;
+ line-height: 14px;
+ word-spacing: 1.5px;
+}
+
+.question-item{
+ display: table-cell;
+ vertical-align: middle;
+ text-align: center;
+ margin-top: 5%;
+ z-index: 1001;
+}
+
+.question-item img {
+ max-width: 150%;
+ margin-left: -25%;
+}
+
+.question-item h3 {
+ font-weight: 300;
+ font-size: 26px;
+ margin-bottom: 5px;
+}
+
+.question-item p {
+ font-weight: 300;
+ font-size: 15px;
+ padding: 0px 10px;
+ word-spacing: 1.4px;
+}
+
+.question-item:nth-of-type(odd) {
+ margin-left: -7px;
+}
+
+.question-item:nth-of-type(9) {
+ margin-top: -12px;
+ cursor: pointer;
+ margin-bottom: 100px;
+}
+
+.modal-dialog {
+ max-width: 300px;
+ margin: auto;
+}
+
+.modal-header {
+ margin: 0px;
+ text-align: center;
+}
+
+.modal-title {
+ font-size: 20px;
+ font-weight: 600;
+}
+
+.modal-header .btn {
+ background: none;
+ border: none;
+ color: #FF7825;
+ font-weight: 600;
+}
+
+.study-image img {
+ max-width: 100%;
+}
+
+.study-image {
+ margin-bottom: 20px;
+ margin-top: -20px;
+}
+
+.study-text {
+ font-size: 16px;
+}
+
+.circle-divider {
+ position: relative;
+ width: 100%;
+ margin: 0px;
+ z-index: 1000;
+}
+
+.circle-divider img {
+ position: absolute;
+ width: 30%;
+ bottom: -40px;
+ right: 110px;
+}
+
+.divider-bar-left, .divider-bar-right {
+ position: absolute;
+ width: 30%;
+ height: 2px;
+ background-color: #FF7825;
+ bottom: 0px;
+}
+
+.divider-bar-left {
+ left: 0px;
+}
+
+.divider-bar-right {
+ right: 0px;
+}
+
+#process {
+ background-image: url('/images/how_bkg.png');
+ background-repeat: repeat-x;
+ height: 566px;
+}
+
+#process .header {
+ text-align: center;
+ margin-top: 30px;
+}
+
+.slides {
+ position: relative;
+}
+
+.step-btn {
+ position: absolute;
+ cursor: pointer;
+ width: 30px;
+}
+
+.step-left {
+ top: 101px;
+ left: 30px;
+}
+
+.step-right {
+ top: 101px;
+ right: 30px;
+}
+
+.step-btn img {
+ max-width: 100%;
+}
+
+.step-title {
+ text-align: center;
+ font-size: 23px;
+ letter-spacing: 1.3px;
+ word-spacing: 1.5px;
+ margin-top: 5px;
+ margin-bottom: none;
+}
+
+.step-img {
+ padding: 0px;
+}
+
+.step-img img {
+ max-width: 100%;
+}
+
+.step-desc {
+ padding: 5px 30px;
+ margin-top: 5px;
+ margin-bottom: 50px;
+ letter-spacing: 1px;
+ font-size: 16px;
+ text-align: justify;
+ text-align-last: justify;
+ -moz-text-align-last: justify;
+}
+
+#connect {
+ background-image: url('https://d2xrs3qqoda7l2.cloudfront.net/asset/sanguine_connectwithus_bkg.png');
+ background-repeat: repeat-x;
+ padding: 25px 0px;
+ height: 267px;
+}
+
+#connect h3 {
+ text-align: center;
+ font-size: 32px;
+ letter-spacing: 3px;
+ word-spacing: 1.2px;
+ margin-top: 0px;
+ margin-bottom: 20px;
+}
+
+.connect-item img{
+ max-width: 100%;
+}
+
+.connect-item:nth-last-of-type(2) {
+ margin-left: 17%;
+}
+
+#footer {
+ text-align: center;
+ margin: 10px 0px 10px -5px;
+}
+
+#footer a {
+ font-size: 14px;
+ letter-spacing: 1px;
+ line-height: 16px;
+}
+
+#footer span {
+ border-right: 2px solid #286275;
+ padding: 0px 6px 0px 8px;
+ vertical-align: middle;
+ text-align: center;
+}
+
+#footer span:nth-last-of-type(-n+1) {
+ border: none;
+}
diff --git a/app/views/404.html b/app/views/404.html
new file mode 100644
index 00000000..ec98e3c2
--- /dev/null
+++ b/app/views/404.html
@@ -0,0 +1,157 @@
+
+
+
+
+ Page Not Found :(
+
+
+
+
+
Not found :(
+
Sorry, but the page you were trying to view does not exist.
+
It looks like this was the result of either:
+
+ a mistyped address
+ an out-of-date link
+
+
+
+
+
+
diff --git a/app/views/index.html b/app/views/index.html
new file mode 100644
index 00000000..cd48e0a7
--- /dev/null
+++ b/app/views/index.html
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/views/partials/connect.html b/app/views/partials/connect.html
new file mode 100644
index 00000000..2b2a780e
--- /dev/null
+++ b/app/views/partials/connect.html
@@ -0,0 +1,11 @@
+
+
+
Connect with us
+
+
+
+
\ No newline at end of file
diff --git a/app/views/partials/footer.html b/app/views/partials/footer.html
new file mode 100644
index 00000000..a0a75de3
--- /dev/null
+++ b/app/views/partials/footer.html
@@ -0,0 +1,21 @@
+
\ No newline at end of file
diff --git a/app/views/partials/form.html b/app/views/partials/form.html
new file mode 100644
index 00000000..75a8bbe2
--- /dev/null
+++ b/app/views/partials/form.html
@@ -0,0 +1,52 @@
+
\ No newline at end of file
diff --git a/app/views/partials/main.html b/app/views/partials/main.html
new file mode 100644
index 00000000..a28c5bca
--- /dev/null
+++ b/app/views/partials/main.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/views/partials/process.html b/app/views/partials/process.html
new file mode 100644
index 00000000..b49e3474
--- /dev/null
+++ b/app/views/partials/process.html
@@ -0,0 +1,23 @@
+
+
+
+
+
{{currentSlide.title}}
+
+
+
+
{{currentSlide.desc}}
+
+
\ No newline at end of file
diff --git a/app/views/partials/question.html b/app/views/partials/question.html
new file mode 100644
index 00000000..cc4f534e
--- /dev/null
+++ b/app/views/partials/question.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
{{item.title}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/views/partials/requirements-modal.html b/app/views/partials/requirements-modal.html
new file mode 100644
index 00000000..efdae33a
--- /dev/null
+++ b/app/views/partials/requirements-modal.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
In order to partipate in this study you must meet the following criteria:
+
+ At least 18 years of age
+ A resident of the United States
+ Have proof of diagnosis
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/views/partials/splash.html b/app/views/partials/splash.html
new file mode 100644
index 00000000..5792f20c
--- /dev/null
+++ b/app/views/partials/splash.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bower.json b/bower.json
new file mode 100644
index 00000000..66add414
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,18 @@
+{
+ "name": "sanguine-test",
+ "version": "0.0.0",
+ "dependencies": {
+ "angular": ">=1.2.*",
+ "json3": "~3.2.6",
+ "es5-shim": "~2.1.0",
+ "angular-route": ">=1.2.*",
+ "angular-bootstrap": "~0.11.0",
+ "bootstrap-css-only": "~3.1.1",
+ "angular-touch": "~1.2.16"
+ },
+ "devDependencies": {
+ "angular-mocks": ">=1.2.*",
+ "angular-scenario": ">=1.2.*"
+ },
+ "testPath": "test/client/spec"
+}
diff --git a/karma-e2e.conf.js b/karma-e2e.conf.js
new file mode 100644
index 00000000..a3d2ba78
--- /dev/null
+++ b/karma-e2e.conf.js
@@ -0,0 +1,54 @@
+// Karma configuration
+// http://karma-runner.github.io/0.10/config/configuration-file.html
+
+module.exports = function(config) {
+ config.set({
+ // base path, that will be used to resolve files and exclude
+ basePath: '',
+
+ // testing framework to use (jasmine/mocha/qunit/...)
+ frameworks: ['ng-scenario'],
+
+ // list of files / patterns to load in the browser
+ files: [
+ 'test/client/e2e/**/*.js'
+ ],
+
+ // list of files / patterns to exclude
+ exclude: [],
+
+ // web server port
+ port: 8080,
+
+ // level of logging
+ // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
+ logLevel: config.LOG_INFO,
+
+
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: false,
+
+
+ // Start these browsers, currently available:
+ // - Chrome
+ // - ChromeCanary
+ // - Firefox
+ // - Opera
+ // - Safari (only Mac)
+ // - PhantomJS
+ // - IE (only Windows)
+ browsers: ['Chrome'],
+
+
+ // Continuous Integration mode
+ // if true, it capture browsers, run tests and exit
+ singleRun: false
+
+ // Uncomment the following lines if you are using grunt's server to run the tests
+ // proxies: {
+ // '/': 'http://localhost:9000/'
+ // },
+ // URL root prevent conflicts with the site root
+ // urlRoot: '_karma_'
+ });
+};
diff --git a/karma.conf.js b/karma.conf.js
new file mode 100644
index 00000000..d239c870
--- /dev/null
+++ b/karma.conf.js
@@ -0,0 +1,53 @@
+// Karma configuration
+// http://karma-runner.github.io/0.10/config/configuration-file.html
+
+module.exports = function(config) {
+ config.set({
+ // base path, that will be used to resolve files and exclude
+ basePath: '',
+
+ // testing framework to use (jasmine/mocha/qunit/...)
+ frameworks: ['jasmine'],
+
+ // list of files / patterns to load in the browser
+ files: [
+ 'app/bower_components/angular/angular.js',
+ 'app/bower_components/angular-mocks/angular-mocks.js',
+ 'app/bower_components/angular-route/angular-route.js',
+ 'app/scripts/*.js',
+ 'app/scripts/**/*.js',
+ 'test/client/mock/**/*.js',
+ 'test/client/spec/**/*.js'
+ ],
+
+ // list of files / patterns to exclude
+ exclude: [],
+
+ // web server port
+ port: 8080,
+
+ // level of logging
+ // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
+ logLevel: config.LOG_INFO,
+
+
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: false,
+
+
+ // Start these browsers, currently available:
+ // - Chrome
+ // - ChromeCanary
+ // - Firefox
+ // - Opera
+ // - Safari (only Mac)
+ // - PhantomJS
+ // - IE (only Windows)
+ browsers: ['Chrome'],
+
+
+ // Continuous Integration mode
+ // if true, it capture browsers, run tests and exit
+ singleRun: false
+ });
+};
diff --git a/lib/.jshintrc b/lib/.jshintrc
new file mode 100644
index 00000000..7dcb186e
--- /dev/null
+++ b/lib/.jshintrc
@@ -0,0 +1,13 @@
+{
+ "node": true,
+ "esnext": true,
+ "bitwise": true,
+ "eqeqeq": true,
+ "immed": true,
+ "latedef": true,
+ "newcap": true,
+ "noarg": true,
+ "regexp": true,
+ "undef": true,
+ "smarttabs": true
+}
\ No newline at end of file
diff --git a/lib/config/config.js b/lib/config/config.js
new file mode 100644
index 00000000..67777d15
--- /dev/null
+++ b/lib/config/config.js
@@ -0,0 +1,10 @@
+'use strict';
+
+var _ = require('lodash');
+
+/**
+ * Load environment configuration
+ */
+module.exports = _.merge(
+ require('./env/all.js'),
+ require('./env/' + process.env.NODE_ENV + '.js') || {});
\ No newline at end of file
diff --git a/lib/config/env/all.js b/lib/config/env/all.js
new file mode 100644
index 00000000..f91a40a8
--- /dev/null
+++ b/lib/config/env/all.js
@@ -0,0 +1,10 @@
+'use strict';
+
+var path = require('path');
+
+var rootPath = path.normalize(__dirname + '/../../..');
+
+module.exports = {
+ root: rootPath,
+ port: process.env.PORT || 9000
+};
\ No newline at end of file
diff --git a/lib/config/env/development.js b/lib/config/env/development.js
new file mode 100644
index 00000000..2ba1ce59
--- /dev/null
+++ b/lib/config/env/development.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = {
+ env: 'development'
+};
\ No newline at end of file
diff --git a/lib/config/env/production.js b/lib/config/env/production.js
new file mode 100644
index 00000000..6eb541c0
--- /dev/null
+++ b/lib/config/env/production.js
@@ -0,0 +1,11 @@
+'use strict';
+
+module.exports = {
+ env: 'production',
+ ip: process.env.OPENSHIFT_NODEJS_IP ||
+ process.env.IP ||
+ '0.0.0.0',
+ port: process.env.OPENSHIFT_NODEJS_PORT ||
+ process.env.PORT ||
+ 8080
+};
\ No newline at end of file
diff --git a/lib/config/env/test.js b/lib/config/env/test.js
new file mode 100644
index 00000000..544ae5e4
--- /dev/null
+++ b/lib/config/env/test.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = {
+ env: 'test'
+};
\ No newline at end of file
diff --git a/lib/config/express.js b/lib/config/express.js
new file mode 100644
index 00000000..04e2c5eb
--- /dev/null
+++ b/lib/config/express.js
@@ -0,0 +1,56 @@
+'use strict';
+
+var express = require('express'),
+ favicon = require('static-favicon'),
+ morgan = require('morgan'),
+ compression = require('compression'),
+ bodyParser = require('body-parser'),
+ methodOverride = require('method-override'),
+ cookieParser = require('cookie-parser'),
+ session = require('express-session'),
+ errorHandler = require('errorhandler'),
+ path = require('path'),
+ config = require('./config');
+
+/**
+ * Express configuration
+ */
+module.exports = function(app) {
+ var env = app.get('env');
+
+ if ('development' === env) {
+ app.use(require('connect-livereload')());
+
+ // Disable caching of scripts for easier testing
+ app.use(function noCache(req, res, next) {
+ if (req.url.indexOf('/scripts/') === 0) {
+ res.header('Cache-Control', 'no-cache, no-store, must-revalidate');
+ res.header('Pragma', 'no-cache');
+ res.header('Expires', 0);
+ }
+ next();
+ });
+
+ app.use(express.static(path.join(config.root, '.tmp')));
+ app.use(express.static(path.join(config.root, 'app')));
+ app.set('views', config.root + '/app/views');
+ }
+
+ if ('production' === env) {
+ app.use(compression());
+ app.use(favicon(path.join(config.root, 'public', 'favicon.ico')));
+ app.use(express.static(path.join(config.root, 'public')));
+ app.set('views', config.root + '/views');
+ }
+
+ app.engine('html', require('ejs').renderFile);
+ app.set('view engine', 'html');
+ app.use(morgan('dev'));
+ app.use(bodyParser());
+ app.use(methodOverride());
+
+ // Error handler - has to be last
+ if ('development' === app.get('env')) {
+ app.use(errorHandler());
+ }
+};
\ No newline at end of file
diff --git a/lib/controllers/api.js b/lib/controllers/api.js
new file mode 100644
index 00000000..9d3a30ee
--- /dev/null
+++ b/lib/controllers/api.js
@@ -0,0 +1,26 @@
+'use strict';
+
+/**
+ * Get awesome things
+ */
+exports.awesomeThings = function(req, res) {
+ res.json([
+ {
+ name : 'HTML5 Boilerplate',
+ info : 'HTML5 Boilerplate is a professional front-end template for building fast, robust, and adaptable web apps or sites.',
+ awesomeness: 10
+ }, {
+ name : 'AngularJS',
+ info : 'AngularJS is a toolset for building the framework most suited to your application development.',
+ awesomeness: 10
+ }, {
+ name : 'Karma',
+ info : 'Spectacular Test Runner for JavaScript.',
+ awesomeness: 10
+ }, {
+ name : 'Express',
+ info : 'Flexible and minimalist web application framework for node.js.',
+ awesomeness: 10
+ }
+ ]);
+};
\ No newline at end of file
diff --git a/lib/controllers/index.js b/lib/controllers/index.js
new file mode 100644
index 00000000..5b781787
--- /dev/null
+++ b/lib/controllers/index.js
@@ -0,0 +1,27 @@
+'use strict';
+
+var path = require('path');
+
+/**
+ * Send partial, or 404 if it doesn't exist
+ */
+exports.partials = function(req, res) {
+ var stripped = req.url.split('.')[0];
+ var requestedView = path.join('./', stripped);
+ res.render(requestedView, function(err, html) {
+ if(err) {
+ console.log("Error rendering partial '" + requestedView + "'\n", err);
+ res.status(404);
+ res.send(404);
+ } else {
+ res.send(html);
+ }
+ });
+};
+
+/**
+ * Send our single page app
+ */
+exports.index = function(req, res) {
+ res.render('index');
+};
diff --git a/lib/routes.js b/lib/routes.js
new file mode 100644
index 00000000..61c4de0d
--- /dev/null
+++ b/lib/routes.js
@@ -0,0 +1,27 @@
+'use strict';
+
+var api = require('./controllers/api'),
+ index = require('./controllers');
+
+/**
+ * Application routes
+ */
+module.exports = function(app) {
+
+ // Server API Routes
+ app.route('/api/awesomeThings')
+ .get(api.awesomeThings);
+
+
+ // All undefined api routes should return a 404
+ app.route('/api/*')
+ .get(function(req, res) {
+ res.send(404);
+ });
+
+ // All other routes to use Angular routing in app/scripts/app.js
+ app.route('/partials/*')
+ .get(index.partials);
+ app.route('/*')
+ .get( index.index);
+};
\ No newline at end of file
diff --git a/mobile_assets.zip b/mobile_assets.zip
deleted file mode 100644
index 1e6f9ff7..00000000
Binary files a/mobile_assets.zip and /dev/null differ
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..2696dce3
--- /dev/null
+++ b/package.json
@@ -0,0 +1,72 @@
+{
+ "name": "sanguinetest",
+ "version": "0.0.0",
+ "dependencies": {
+ "express": "~4.0.0",
+ "morgan": "~1.0.0",
+ "body-parser": "~1.0.0",
+ "method-override": "~1.0.0",
+ "static-favicon": "~1.0.1",
+ "cookie-parser": "~1.0.1",
+ "express-session": "~1.0.2",
+ "errorhandler": "~1.0.0",
+ "compression": "~1.0.1",
+ "lodash": "~2.4.1",
+ "ejs": "~0.8.4"
+ },
+ "devDependencies": {
+ "grunt": "~0.4.1",
+ "grunt-autoprefixer": "~0.4.0",
+ "grunt-bower-install": "~0.7.0",
+ "grunt-concurrent": "~0.4.1",
+ "grunt-contrib-clean": "~0.5.0",
+ "grunt-contrib-coffee": "~0.7.0",
+ "grunt-contrib-compass": "~0.6.0",
+ "grunt-contrib-concat": "~0.3.0",
+ "grunt-contrib-copy": "~0.4.1",
+ "grunt-contrib-cssmin": "~0.7.0",
+ "grunt-contrib-htmlmin": "~0.1.3",
+ "grunt-contrib-imagemin": "~0.5.0",
+ "grunt-contrib-jshint": "~0.7.1",
+ "grunt-contrib-uglify": "~0.2.0",
+ "grunt-contrib-watch": "~0.5.2",
+ "grunt-google-cdn": "~0.2.0",
+ "grunt-newer": "~0.5.4",
+ "grunt-ngmin": "~0.0.2",
+ "grunt-rev": "~0.1.0",
+ "grunt-svgmin": "~0.2.0",
+ "grunt-usemin": "~2.0.0",
+ "jshint-stylish": "~0.1.3",
+ "load-grunt-tasks": "~0.2.0",
+ "time-grunt": "~0.2.1",
+ "grunt-express-server": "~0.4.5",
+ "grunt-open": "~0.2.0",
+ "connect-livereload": "~0.3.0",
+ "karma-ng-scenario": "~0.1.0",
+ "grunt-karma": "~0.6.2",
+ "karma-firefox-launcher": "~0.1.3",
+ "karma-script-launcher": "~0.1.0",
+ "karma-html2js-preprocessor": "~0.1.0",
+ "karma-jasmine": "~0.1.5",
+ "karma-chrome-launcher": "~0.1.2",
+ "requirejs": "~2.1.10",
+ "karma-requirejs": "~0.2.1",
+ "karma-coffee-preprocessor": "~0.1.2",
+ "karma-phantomjs-launcher": "~0.1.1",
+ "karma": "~0.10.9",
+ "karma-ng-html2js-preprocessor": "~0.1.0",
+ "grunt-mocha-test": "~0.8.1",
+ "supertest": "~0.8.2",
+ "should": "~2.1.0",
+ "grunt-env": "~0.4.1",
+ "grunt-node-inspector": "~0.1.3",
+ "grunt-nodemon": "~0.2.0",
+ "open": "~0.0.4"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "scripts": {
+ "test": "grunt test"
+ }
+}
\ No newline at end of file
diff --git a/server.js b/server.js
new file mode 100644
index 00000000..4a4474eb
--- /dev/null
+++ b/server.js
@@ -0,0 +1,27 @@
+'use strict';
+
+var express = require('express');
+
+/**
+ * Main application file
+ */
+
+// Set default node environment to development
+process.env.NODE_ENV = process.env.NODE_ENV || 'development';
+
+var config = require('./lib/config/config');
+
+// Setup Express
+var app = express();
+require('./lib/config/express')(app);
+require('./lib/routes')(app);
+
+// Start server
+app.listen(config.port, config.ip, function () {
+ console.log('Express server listening on %s:%d, in %s mode', config.ip, config.port, app.get('env'));
+});
+
+// Expose app
+exports = module.exports = app;
+
+//Comment
\ No newline at end of file
diff --git a/test/client/.jshintrc b/test/client/.jshintrc
new file mode 100644
index 00000000..b1be025b
--- /dev/null
+++ b/test/client/.jshintrc
@@ -0,0 +1,36 @@
+{
+ "node": true,
+ "browser": true,
+ "esnext": true,
+ "bitwise": true,
+ "camelcase": true,
+ "curly": true,
+ "eqeqeq": true,
+ "immed": true,
+ "indent": 2,
+ "latedef": true,
+ "newcap": true,
+ "noarg": true,
+ "quotmark": "single",
+ "regexp": true,
+ "undef": true,
+ "unused": true,
+ "strict": true,
+ "trailing": true,
+ "smarttabs": true,
+ "globals": {
+ "after": false,
+ "afterEach": false,
+ "angular": false,
+ "before": false,
+ "beforeEach": false,
+ "browser": false,
+ "describe": false,
+ "expect": false,
+ "inject": false,
+ "it": false,
+ "jasmine": false,
+ "spyOn": false
+ }
+}
+
diff --git a/test/client/runner.html b/test/client/runner.html
new file mode 100644
index 00000000..f4a00a12
--- /dev/null
+++ b/test/client/runner.html
@@ -0,0 +1,10 @@
+
+
+
+ End2end Test Runner
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/client/spec/controllers/main.js b/test/client/spec/controllers/main.js
new file mode 100644
index 00000000..ee7790c9
--- /dev/null
+++ b/test/client/spec/controllers/main.js
@@ -0,0 +1,28 @@
+'use strict';
+
+describe('Controller: MainCtrl', function () {
+
+ // load the controller's module
+ beforeEach(module('sanguineTestApp'));
+
+ var MainCtrl,
+ scope,
+ $httpBackend;
+
+ // Initialize the controller and a mock scope
+ beforeEach(inject(function (_$httpBackend_, $controller, $rootScope) {
+ $httpBackend = _$httpBackend_;
+ $httpBackend.expectGET('/api/awesomeThings')
+ .respond(['HTML5 Boilerplate', 'AngularJS', 'Karma', 'Express']);
+ scope = $rootScope.$new();
+ MainCtrl = $controller('MainCtrl', {
+ $scope: scope
+ });
+ }));
+
+ it('should attach a list of awesomeThings to the scope', function () {
+ expect(scope.awesomeThings).toBeUndefined();
+ $httpBackend.flush();
+ expect(scope.awesomeThings.length).toBe(4);
+ });
+});
diff --git a/test/server/thing/api.js b/test/server/thing/api.js
new file mode 100644
index 00000000..21713d65
--- /dev/null
+++ b/test/server/thing/api.js
@@ -0,0 +1,20 @@
+'use strict';
+
+var should = require('should'),
+ app = require('../../../server'),
+ request = require('supertest');
+
+describe('GET /api/awesomeThings', function() {
+
+ it('should respond with JSON array', function(done) {
+ request(app)
+ .get('/api/awesomeThings')
+ .expect(200)
+ .expect('Content-Type', /json/)
+ .end(function(err, res) {
+ if (err) return done(err);
+ res.body.should.be.instanceof(Array);
+ done();
+ });
+ });
+});
\ No newline at end of file