From 4d9f9fc83bce3f407a7efc6c473b8780c9598440 Mon Sep 17 00:00:00 2001 From: Samuel Laulhau Date: Sat, 30 Apr 2016 20:00:11 +0300 Subject: [PATCH 1/8] avoid unstable mongoose Some of the mongoose version are tagged as unstable. It's better to freeze the version to avoid them --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ad7a0eed..6292f980 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "math": "0.0.3", "method-override": "~2.3.0", "mkdirp": "^0.5.1", - "mongoose": "^3.8.40", + "mongoose": "3.8.40", "mongoose-utilities": "~0.1.1", "morgan": "~1.6.1", "multer": "~1.1.0", From 883a944c830b3ed3c60426978383638673a5e51b Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Mon, 9 May 2016 23:30:09 -0700 Subject: [PATCH 2/8] got setup script to work --- a.txt | 14 + app/models/user.server.model.js | 3 +- config/env/all.js | 10 +- config/env/development.js | 3 - gruntfile.js | 191 +- npm-debug.log.1568303069 | 3903 ------------------------------- package.json | 5 +- public/dist/application.js | 101 +- public/dist/application.min.js | 4 +- scripts/setup.js | 201 ++ 10 files changed, 381 insertions(+), 4054 deletions(-) create mode 100644 a.txt delete mode 100644 npm-debug.log.1568303069 create mode 100644 scripts/setup.js diff --git a/a.txt b/a.txt new file mode 100644 index 00000000..f6491dff --- /dev/null +++ b/a.txt @@ -0,0 +1,14 @@ +APP_NAME= +APP_DESC= +APP_KEYWORDS= +SIGNUP_DISABLED=false +NODE_ENV=dev +MAILER_SERVICE_PROVIDER=1und1 +MAILER_EMAIL_ID= +MAILER_PASSWORD= +MAILER_FROM= +BASE_URL=127.0.0.1 +PORT=3000 +GOOGLE_ANALYTICS_ID= +email= +password= diff --git a/app/models/user.server.model.js b/app/models/user.server.model.js index f016826c..7458e7d2 100755 --- a/app/models/user.server.model.js +++ b/app/models/user.server.model.js @@ -80,7 +80,8 @@ var UserSchema = new Schema({ }, provider: { type: String, - required: 'Provider is required' + required: 'Provider is required', + default: 'local' }, providerData: {}, additionalProvidersData: {}, diff --git a/config/env/all.js b/config/env/all.js index 663f2769..7172f61e 100755 --- a/config/env/all.js +++ b/config/env/all.js @@ -3,9 +3,9 @@ module.exports = { app: { google_analytics_id: process.env.GOOGLE_ANALYTICS_ID || '', - title: 'TellForm', - description: 'Opensource form builder alternative to TypeForm', - keywords: 'typeform, pdfs, forms, opensource, formbuilder, google forms, nodejs', + title: process.env.APP_NAME || 'TellForm', + description: process.env.APP_DESC || 'Opensource form builder alternative to TypeForm', + keywords: process.env.APP_KEYWORDS || 'typeform, pdfs, forms, opensource, formbuilder, google forms, nodejs' }, port: process.env.PORT || 3000, templateEngine: 'swig', @@ -16,7 +16,7 @@ module.exports = { mailosaur: { key: process.env.MAILOSAUR_KEY || '', - mailbox_id: process.env.MAILOSAUR_MAILBOX || '', + mailbox_id: process.env.MAILOSAUR_MAILBOX || '' }, //Sentry DSN Client Key @@ -38,7 +38,7 @@ module.exports = { secure: false, // Only set the maxAge to null if the cookie shouldn't be expired // at all. The cookie will expunge when the browser is closed. - maxAge: null, + maxAge: null // To set the cookie in a specific domain uncomment the following // setting: // domain: 'tellform.com' diff --git a/config/env/development.js b/config/env/development.js index 6678e1ea..6de85e2b 100755 --- a/config/env/development.js +++ b/config/env/development.js @@ -18,9 +18,6 @@ module.exports = { // stream: 'access.log' } }, - app: { - title: 'TellForm' - }, sessionCookie: { domain: process.env.BASE_URL || 'http://localhost:3000' }, diff --git a/gruntfile.js b/gruntfile.js index bfeb8a08..11f3d26c 100755 --- a/gruntfile.js +++ b/gruntfile.js @@ -1,4 +1,6 @@ 'use strict'; +var spawn = require('child_process').spawn; + module.exports = function(grunt) { require('jit-grunt')(grunt); @@ -69,81 +71,81 @@ module.exports = function(grunt) { options: { jshintrc: true } - }, - allTests: { + }, + allTests: { src: watchFiles.allTests, options: { - jshintrc: true + jshintrc: true } - } - }, - csslint: { - options: { + } + }, + csslint: { + options: { csslintrc: '.csslintrc' - }, - all: { + }, + all: { src: watchFiles.clientCSS - } - }, -uglify: { -production: { -options: { -mangle: false - }, -files: { - 'public/dist/application.min.js': 'public/dist/application.js' - } - } - }, -cssmin: { -combine: { -files: { - 'public/dist/application.min.css': '<%= applicationCSSFiles %>' - } - } - }, -nodemon: { -dev: { -script: 'server.js', - options: { -nodeArgs: ['--debug'], - ext: 'js,html', - watch: watchFiles.serverViews.concat(watchFiles.serverJS) - } - } - }, - 'node-inspector': { -custom: { -options: { - 'web-port': 1337, - 'web-host': 'localhost', - 'debug-port': 5858, - 'save-live-edit': true, - 'no-preload': true, - 'stack-trace-limit': 50, - 'hidden': [] - } - } - }, -ngAnnotate: { -production: { -files: { - 'public/dist/application.js': '<%= applicationJavaScriptFiles %>' - } - } - }, -concurrent: { + } + }, + uglify: { + production: { + options: { + mangle: false + }, + files: { + 'public/dist/application.min.js': 'public/dist/application.js' + } + } + }, + cssmin: { + combine: { + files: { + 'public/dist/application.min.css': '<%= applicationCSSFiles %>' + } + } + }, + nodemon: { + dev: { + script: 'server.js', + options: { + nodeArgs: ['--debug'], + ext: 'js,html', + watch: watchFiles.serverViews.concat(watchFiles.serverJS) + } + } + }, + 'node-inspector': { + custom: { + options: { + 'web-port': 1337, + 'web-host': 'localhost', + 'debug-port': 5858, + 'save-live-edit': true, + 'no-preload': true, + 'stack-trace-limit': 50, + 'hidden': [] + } + } + }, + ngAnnotate: { + production: { + files: { + 'public/dist/application.js': '<%= applicationJavaScriptFiles %>' + } + } + }, + concurrent: { default: ['nodemon', 'watch'], -debug: ['nodemon', 'watch', 'node-inspector'], - options: { -logConcurrentOutput: true, - limit: 10 - } + debug: ['nodemon', 'watch', 'node-inspector'], + options: { + logConcurrentOutput: true, + limit: 10 + } }, -env: { -test: { -NODE_ENV: 'test', - src: '.env' + env: { + test: { + NODE_ENV: 'test', + src: '.env' }, secure: { NODE_ENV: 'secure', @@ -156,7 +158,7 @@ NODE_ENV: 'test', dev: { NODE_ENV: 'development', src: '.env' - }, + } }, mochaTest: { src: watchFiles.serverTests, @@ -230,26 +232,31 @@ NODE_ENV: 'test', } } }, - html2js: { - options: { - base: 'NodeForm', - watch: true, - module: 'NodeForm.templates', - singleModule: true, - useStrict: true, - htmlmin: { - collapseBooleanAttributes: true, - collapseWhitespace: true, - removeAttributeQuotes: true, - removeComments: true, - removeEmptyAttributes: true, - removeRedundantAttributes: true - } - }, - main: { - src: ['public/modules/**/views/**.html', 'public/modules/**/views/**/*.html'], - dest: 'public/dist/populate_template_cache.js' - } + html2js: { + options: { + base: 'NodeForm', + watch: true, + module: 'NodeForm.templates', + singleModule: true, + useStrict: true, + htmlmin: { + collapseBooleanAttributes: true, + collapseWhitespace: true, + removeAttributeQuotes: true, + removeComments: true, + removeEmptyAttributes: true, + removeRedundantAttributes: true + } + }, + main: { + src: ['public/modules/**/views/**.html', 'public/modules/**/views/**/*.html'], + dest: 'public/dist/populate_template_cache.js' + } + }, + execute: { + target: { + src: ['./scripts/setup.js'] + } } }); @@ -278,7 +285,6 @@ NODE_ENV: 'test', grunt.config.set('applicationCSSFiles', config.assets.css); }); - // Code coverage tasks. grunt.registerTask('coveralls', ['env:test','mocha_istanbul:coveralls']); grunt.registerTask('coverage', ['env:test', 'mocha_istanbul:coverage']); @@ -288,9 +294,11 @@ NODE_ENV: 'test', // Default task(s). grunt.registerTask('default', ['lint', 'html2js:main', 'env', 'concurrent:default']); grunt.registerTask('dev', ['lint', 'html2js:main', 'env:dev', 'concurrent:default']); + // Debug task. grunt.registerTask('debug', ['lint', 'html2js:main', 'concurrent:debug']); + // Secure task(s). grunt.registerTask('secure', ['env:secure', 'lint', 'html2js:main', 'concurrent:default']); @@ -301,6 +309,9 @@ NODE_ENV: 'test', // Build task(s). grunt.registerTask('build', ['lint', 'loadConfig', 'cssmin', 'ngAnnotate', 'uglify', 'html2js:main']); + //Setup task(s). + grunt.registerTask('setup', ['execute']); + // Test task(s). grunt.registerTask('test', ['lint:tests', 'test:server', 'test:client']); grunt.registerTask('test:server', ['lint:tests', 'env:test', 'mochaTest']); diff --git a/npm-debug.log.1568303069 b/npm-debug.log.1568303069 deleted file mode 100644 index 8698b4e0..00000000 --- a/npm-debug.log.1568303069 +++ /dev/null @@ -1,3903 +0,0 @@ -0 info it worked if it ends with ok -1 verbose cli [ 'node', '/usr/local/bin/npm', 'install' ] -2 info using npm@3.8.6 -3 info using node@v0.12.7 -4 silly loadCurrentTree Starting -5 silly install loadCurrentTree -6 silly install readLocalPackageData -7 silly install normalizeTree -8 silly loadCurrentTree Finishing -9 silly loadIdealTree Starting -10 silly install loadIdealTree -11 silly cloneCurrentTree Starting -12 silly install cloneCurrentTreeToIdealTree -13 silly cloneCurrentTree Finishing -14 silly loadShrinkwrap Starting -15 silly install loadShrinkwrap -16 silly loadShrinkwrap Finishing -17 silly loadAllDepsIntoIdealTree Starting -18 silly install loadAllDepsIntoIdealTree -19 silly fetchNamedPackageData fsevents -20 silly mapToRegistry name fsevents -21 silly mapToRegistry using default registry -22 silly mapToRegistry registry https://registry.npmjs.org/ -23 silly mapToRegistry data { raw: 'fsevents', -23 silly mapToRegistry scope: null, -23 silly mapToRegistry name: 'fsevents', -23 silly mapToRegistry rawSpec: '', -23 silly mapToRegistry spec: 'latest', -23 silly mapToRegistry type: 'tag' } -24 silly mapToRegistry uri https://registry.npmjs.org/fsevents -25 verbose request uri https://registry.npmjs.org/fsevents -26 verbose request no auth needed -27 info attempt registry request try #1 at 13:59:22 -28 verbose request id 07acde0c5237ee69 -29 verbose etag "8PVGYBXJZ0N7A0VP5BLLIVEG2" -30 http request GET https://registry.npmjs.org/fsevents -31 http 304 https://registry.npmjs.org/fsevents -32 verbose headers { date: 'Sun, 24 Apr 2016 17:59:22 GMT', -32 verbose headers via: '1.1 varnish', -32 verbose headers 'cache-control': 'max-age=300', -32 verbose headers etag: '"8PVGYBXJZ0N7A0VP5BLLIVEG2"', -32 verbose headers age: '147', -32 verbose headers connection: 'keep-alive', -32 verbose headers 'x-served-by': 'cache-ord1748-ORD', -32 verbose headers 'x-cache': 'HIT', -32 verbose headers 'x-cache-hits': '3', -32 verbose headers 'x-timer': 'S1461520762.202248,VS0,VE0', -32 verbose headers vary: 'Accept-Encoding' } -33 silly get cb [ 304, -33 silly get { date: 'Sun, 24 Apr 2016 17:59:22 GMT', -33 silly get via: '1.1 varnish', -33 silly get 'cache-control': 'max-age=300', -33 silly get etag: '"8PVGYBXJZ0N7A0VP5BLLIVEG2"', -33 silly get age: '147', -33 silly get connection: 'keep-alive', -33 silly get 'x-served-by': 'cache-ord1748-ORD', -33 silly get 'x-cache': 'HIT', -33 silly get 'x-cache-hits': '3', -33 silly get 'x-timer': 'S1461520762.202248,VS0,VE0', -33 silly get vary: 'Accept-Encoding' } ] -34 verbose etag https://registry.npmjs.org/fsevents from cache -35 verbose get saving fsevents to /home/polydaic/.npm/registry.npmjs.org/fsevents/.cache.json -36 verbose correctMkdir /home/polydaic/.npm correctMkdir not in flight; initializing -37 silly resolveWithNewModule fsevents@1.0.11 checking installable status -38 silly loadAllDepsIntoIdealTree Finishing -39 silly idealTree:prePrune TellForm@1.2.1 -39 silly idealTree:prePrune ├── MD5@1.3.0 -39 silly idealTree:prePrune ├── abbrev@1.0.7 -39 silly idealTree:prePrune ├── accepts@1.3.2 -39 silly idealTree:prePrune ├─┬ acorn-globals@1.0.9 -39 silly idealTree:prePrune │ └── acorn@2.7.0 -39 silly idealTree:prePrune ├── acorn@1.2.2 -39 silly idealTree:prePrune ├── addressparser@0.3.2 -39 silly idealTree:prePrune ├── after@0.8.1 -39 silly idealTree:prePrune ├── align-text@0.1.4 -39 silly idealTree:prePrune ├── alter@0.2.0 -39 silly idealTree:prePrune ├── amdefine@1.0.0 -39 silly idealTree:prePrune ├── ansi-regex@2.0.0 -39 silly idealTree:prePrune ├── ansi-styles@2.2.1 -39 silly idealTree:prePrune ├── ansi@0.3.1 -39 silly idealTree:prePrune ├── anymatch@1.3.0 -39 silly idealTree:prePrune ├── append-field@0.1.0 -39 silly idealTree:prePrune ├─┬ are-we-there-yet@1.1.2 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ └── readable-stream@2.1.0 -39 silly idealTree:prePrune ├─┬ argparse@0.1.16 -39 silly idealTree:prePrune │ └── underscore.string@2.4.0 -39 silly idealTree:prePrune ├── arr-diff@2.0.0 -39 silly idealTree:prePrune ├── arr-flatten@1.0.1 -39 silly idealTree:prePrune ├── array-differ@1.0.0 -39 silly idealTree:prePrune ├── array-find-index@1.0.1 -39 silly idealTree:prePrune ├── array-flatten@1.1.1 -39 silly idealTree:prePrune ├── array-slice@0.2.3 -39 silly idealTree:prePrune ├── array-union@1.0.1 -39 silly idealTree:prePrune ├── array-uniq@1.0.2 -39 silly idealTree:prePrune ├── array-unique@0.2.1 -39 silly idealTree:prePrune ├── arraybuffer.slice@0.0.6 -39 silly idealTree:prePrune ├── arrify@1.0.1 -39 silly idealTree:prePrune ├── asap@1.0.0 -39 silly idealTree:prePrune ├── asn1@0.2.3 -39 silly idealTree:prePrune ├── assert-plus@0.2.0 -39 silly idealTree:prePrune ├── ast-types@0.8.16 -39 silly idealTree:prePrune ├── async-each@1.0.0 -39 silly idealTree:prePrune ├── async@1.5.2 -39 silly idealTree:prePrune ├── aws-sign2@0.6.0 -39 silly idealTree:prePrune ├─┬ aws4@1.3.2 -39 silly idealTree:prePrune │ └── lru-cache@4.0.1 -39 silly idealTree:prePrune ├── backo2@1.0.2 -39 silly idealTree:prePrune ├── balanced-match@0.3.0 -39 silly idealTree:prePrune ├── base64-arraybuffer@0.1.2 -39 silly idealTree:prePrune ├── base64-js@0.0.8 -39 silly idealTree:prePrune ├── base64-url@1.2.1 -39 silly idealTree:prePrune ├── base64id@0.1.0 -39 silly idealTree:prePrune ├── basic-auth@1.0.3 -39 silly idealTree:prePrune ├── batch@0.5.3 -39 silly idealTree:prePrune ├─┬ bcrypt@0.8.6 -39 silly idealTree:prePrune │ └── nan@2.2.1 -39 silly idealTree:prePrune ├── benchmark@1.0.0 -39 silly idealTree:prePrune ├── better-assert@1.0.2 -39 silly idealTree:prePrune ├─┬ biased-opener@0.2.8 -39 silly idealTree:prePrune │ └── minimist@1.2.0 -39 silly idealTree:prePrune ├── big-integer@1.6.15 -39 silly idealTree:prePrune ├── binary-extensions@1.4.0 -39 silly idealTree:prePrune ├── bindings@1.2.1 -39 silly idealTree:prePrune ├─┬ bl@1.1.2 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ └── readable-stream@2.0.6 -39 silly idealTree:prePrune ├── blob@0.0.4 -39 silly idealTree:prePrune ├── block-stream@0.0.8 -39 silly idealTree:prePrune ├── bluebird@2.10.2 -39 silly idealTree:prePrune ├── body-parser@1.14.2 -39 silly idealTree:prePrune ├── boom@2.10.1 -39 silly idealTree:prePrune ├─┬ bower@1.6.9 -39 silly idealTree:prePrune │ ├── abbrev@1.0.7 -39 silly idealTree:prePrune │ ├── archy@1.0.0 -39 silly idealTree:prePrune │ ├─┬ bower-config@1.2.3 -39 silly idealTree:prePrune │ │ ├── graceful-fs@4.1.2 -39 silly idealTree:prePrune │ │ ├─┬ optimist@0.6.1 -39 silly idealTree:prePrune │ │ │ ├── minimist@0.0.10 -39 silly idealTree:prePrune │ │ │ └── wordwrap@0.0.3 -39 silly idealTree:prePrune │ │ └─┬ osenv@0.1.3 -39 silly idealTree:prePrune │ │ ├── os-homedir@1.0.1 -39 silly idealTree:prePrune │ │ └── os-tmpdir@1.0.1 -39 silly idealTree:prePrune │ ├── bower-endpoint-parser@0.2.2 -39 silly idealTree:prePrune │ ├─┬ bower-json@0.4.0 -39 silly idealTree:prePrune │ │ ├── deep-extend@0.2.11 -39 silly idealTree:prePrune │ │ ├── graceful-fs@2.0.3 -39 silly idealTree:prePrune │ │ └── intersect@0.0.3 -39 silly idealTree:prePrune │ ├── bower-logger@0.2.2 -39 silly idealTree:prePrune │ ├─┬ bower-registry-client@1.0.0 -39 silly idealTree:prePrune │ │ ├── async@0.2.10 -39 silly idealTree:prePrune │ │ ├── graceful-fs@4.1.2 -39 silly idealTree:prePrune │ │ ├── mkdirp@0.3.5 -39 silly idealTree:prePrune │ │ └── request-replay@0.2.0 -39 silly idealTree:prePrune │ ├─┬ cardinal@0.4.4 -39 silly idealTree:prePrune │ │ ├── ansicolors@0.2.1 -39 silly idealTree:prePrune │ │ └─┬ redeyed@0.4.4 -39 silly idealTree:prePrune │ │ └── esprima@1.0.4 -39 silly idealTree:prePrune │ ├─┬ chalk@1.1.1 -39 silly idealTree:prePrune │ │ ├── ansi-styles@2.1.0 -39 silly idealTree:prePrune │ │ ├── escape-string-regexp@1.0.3 -39 silly idealTree:prePrune │ │ ├─┬ has-ansi@2.0.0 -39 silly idealTree:prePrune │ │ │ └── ansi-regex@2.0.0 -39 silly idealTree:prePrune │ │ ├─┬ strip-ansi@3.0.0 -39 silly idealTree:prePrune │ │ │ └── ansi-regex@2.0.0 -39 silly idealTree:prePrune │ │ └── supports-color@2.0.0 -39 silly idealTree:prePrune │ ├── chmodr@1.0.2 -39 silly idealTree:prePrune │ ├─┬ configstore@0.3.2 -39 silly idealTree:prePrune │ │ ├─┬ js-yaml@3.4.6 -39 silly idealTree:prePrune │ │ │ ├─┬ argparse@1.0.3 -39 silly idealTree:prePrune │ │ │ │ ├── lodash@3.10.1 -39 silly idealTree:prePrune │ │ │ │ └── sprintf-js@1.0.3 -39 silly idealTree:prePrune │ │ │ ├── esprima@2.7.0 -39 silly idealTree:prePrune │ │ │ └── inherit@2.2.2 -39 silly idealTree:prePrune │ │ ├── object-assign@2.1.1 -39 silly idealTree:prePrune │ │ ├─┬ osenv@0.1.3 -39 silly idealTree:prePrune │ │ │ ├── os-homedir@1.0.1 -39 silly idealTree:prePrune │ │ │ └── os-tmpdir@1.0.1 -39 silly idealTree:prePrune │ │ ├── uuid@2.0.1 -39 silly idealTree:prePrune │ │ └── xdg-basedir@1.0.1 -39 silly idealTree:prePrune │ ├─┬ decompress-zip@0.1.0 -39 silly idealTree:prePrune │ │ ├─┬ binary@0.3.0 -39 silly idealTree:prePrune │ │ │ ├── buffers@0.1.1 -39 silly idealTree:prePrune │ │ │ └─┬ chainsaw@0.1.0 -39 silly idealTree:prePrune │ │ │ └── traverse@0.3.9 -39 silly idealTree:prePrune │ │ ├── mkpath@0.1.0 -39 silly idealTree:prePrune │ │ ├─┬ readable-stream@1.1.13 -39 silly idealTree:prePrune │ │ │ ├── core-util-is@1.0.2 -39 silly idealTree:prePrune │ │ │ ├── inherits@2.0.1 -39 silly idealTree:prePrune │ │ │ ├── isarray@0.0.1 -39 silly idealTree:prePrune │ │ │ └── string_decoder@0.10.31 -39 silly idealTree:prePrune │ │ └─┬ touch@0.0.3 -39 silly idealTree:prePrune │ │ └── nopt@1.0.10 -39 silly idealTree:prePrune │ ├── destroy@1.0.3 -39 silly idealTree:prePrune │ ├─┬ fs-write-stream-atomic@1.0.5 -39 silly idealTree:prePrune │ │ ├── graceful-fs@4.1.2 -39 silly idealTree:prePrune │ │ └── imurmurhash@0.1.4 -39 silly idealTree:prePrune │ ├─┬ fstream-ignore@1.0.3 -39 silly idealTree:prePrune │ │ ├── inherits@2.0.1 -39 silly idealTree:prePrune │ │ └─┬ minimatch@3.0.0 -39 silly idealTree:prePrune │ │ └─┬ brace-expansion@1.1.2 -39 silly idealTree:prePrune │ │ ├── balanced-match@0.3.0 -39 silly idealTree:prePrune │ │ └── concat-map@0.0.1 -39 silly idealTree:prePrune │ ├─┬ fstream@1.0.8 -39 silly idealTree:prePrune │ │ ├── graceful-fs@4.1.2 -39 silly idealTree:prePrune │ │ └── inherits@2.0.1 -39 silly idealTree:prePrune │ ├─┬ github@0.2.4 -39 silly idealTree:prePrune │ │ └── mime@1.3.4 -39 silly idealTree:prePrune │ ├─┬ glob@4.5.3 -39 silly idealTree:prePrune │ │ ├─┬ inflight@1.0.4 -39 silly idealTree:prePrune │ │ │ └── wrappy@1.0.1 -39 silly idealTree:prePrune │ │ ├── inherits@2.0.1 -39 silly idealTree:prePrune │ │ ├─┬ minimatch@2.0.10 -39 silly idealTree:prePrune │ │ │ └─┬ brace-expansion@1.1.2 -39 silly idealTree:prePrune │ │ │ ├── balanced-match@0.3.0 -39 silly idealTree:prePrune │ │ │ └── concat-map@0.0.1 -39 silly idealTree:prePrune │ │ └─┬ once@1.3.3 -39 silly idealTree:prePrune │ │ └── wrappy@1.0.1 -39 silly idealTree:prePrune │ ├── graceful-fs@3.0.8 -39 silly idealTree:prePrune │ ├─┬ handlebars@2.0.0 -39 silly idealTree:prePrune │ │ ├─┬ optimist@0.3.7 -39 silly idealTree:prePrune │ │ │ └── wordwrap@0.0.3 -39 silly idealTree:prePrune │ │ └─┬ uglify-js@2.3.6 -39 silly idealTree:prePrune │ │ ├── async@0.2.10 -39 silly idealTree:prePrune │ │ └─┬ source-map@0.1.43 -39 silly idealTree:prePrune │ │ └── amdefine@1.0.0 -39 silly idealTree:prePrune │ ├─┬ inquirer@0.10.0 -39 silly idealTree:prePrune │ │ ├── ansi-escapes@1.1.0 -39 silly idealTree:prePrune │ │ ├── ansi-regex@2.0.0 -39 silly idealTree:prePrune │ │ ├─┬ cli-cursor@1.0.2 -39 silly idealTree:prePrune │ │ │ └─┬ restore-cursor@1.0.1 -39 silly idealTree:prePrune │ │ │ ├── exit-hook@1.1.1 -39 silly idealTree:prePrune │ │ │ └── onetime@1.0.0 -39 silly idealTree:prePrune │ │ ├── cli-width@1.1.0 -39 silly idealTree:prePrune │ │ ├── figures@1.4.0 -39 silly idealTree:prePrune │ │ ├── lodash@3.10.1 -39 silly idealTree:prePrune │ │ ├─┬ readline2@1.0.1 -39 silly idealTree:prePrune │ │ │ ├─┬ code-point-at@1.0.0 -39 silly idealTree:prePrune │ │ │ │ └── number-is-nan@1.0.0 -39 silly idealTree:prePrune │ │ │ ├─┬ is-fullwidth-code-point@1.0.0 -39 silly idealTree:prePrune │ │ │ │ └── number-is-nan@1.0.0 -39 silly idealTree:prePrune │ │ │ └── mute-stream@0.0.5 -39 silly idealTree:prePrune │ │ ├─┬ run-async@0.1.0 -39 silly idealTree:prePrune │ │ │ └─┬ once@1.3.3 -39 silly idealTree:prePrune │ │ │ └── wrappy@1.0.1 -39 silly idealTree:prePrune │ │ ├── rx-lite@3.1.2 -39 silly idealTree:prePrune │ │ ├── strip-ansi@3.0.0 -39 silly idealTree:prePrune │ │ └── through@2.3.8 -39 silly idealTree:prePrune │ ├─┬ insight@0.7.0 -39 silly idealTree:prePrune │ │ ├── async@1.5.0 -39 silly idealTree:prePrune │ │ ├─┬ configstore@1.3.0 -39 silly idealTree:prePrune │ │ │ ├── graceful-fs@4.1.2 -39 silly idealTree:prePrune │ │ │ ├── os-tmpdir@1.0.1 -39 silly idealTree:prePrune │ │ │ ├─┬ osenv@0.1.3 -39 silly idealTree:prePrune │ │ │ │ └── os-homedir@1.0.1 -39 silly idealTree:prePrune │ │ │ ├── uuid@2.0.1 -39 silly idealTree:prePrune │ │ │ ├─┬ write-file-atomic@1.1.4 -39 silly idealTree:prePrune │ │ │ │ ├── imurmurhash@0.1.4 -39 silly idealTree:prePrune │ │ │ │ └── slide@1.1.6 -39 silly idealTree:prePrune │ │ │ └─┬ xdg-basedir@2.0.0 -39 silly idealTree:prePrune │ │ │ └── os-homedir@1.0.1 -39 silly idealTree:prePrune │ │ ├─┬ lodash.debounce@3.1.1 -39 silly idealTree:prePrune │ │ │ └── lodash._getnative@3.9.1 -39 silly idealTree:prePrune │ │ ├── object-assign@4.0.1 -39 silly idealTree:prePrune │ │ ├─┬ os-name@1.0.3 -39 silly idealTree:prePrune │ │ │ ├─┬ osx-release@1.1.0 -39 silly idealTree:prePrune │ │ │ │ └── minimist@1.2.0 -39 silly idealTree:prePrune │ │ │ └─┬ win-release@1.1.1 -39 silly idealTree:prePrune │ │ │ └── semver@5.1.0 -39 silly idealTree:prePrune │ │ └── tough-cookie@2.2.1 -39 silly idealTree:prePrune │ ├── is-root@1.0.0 -39 silly idealTree:prePrune │ ├── junk@1.0.2 -39 silly idealTree:prePrune │ ├── lockfile@1.0.1 -39 silly idealTree:prePrune │ ├── lru-cache@2.7.3 -39 silly idealTree:prePrune │ ├─┬ md5-hex@1.1.0 -39 silly idealTree:prePrune │ │ └── md5-o-matic@0.1.1 -39 silly idealTree:prePrune │ ├─┬ mkdirp@0.5.0 -39 silly idealTree:prePrune │ │ └── minimist@0.0.8 -39 silly idealTree:prePrune │ ├── mout@0.11.1 -39 silly idealTree:prePrune │ ├── nopt@3.0.6 -39 silly idealTree:prePrune │ ├── opn@1.0.2 -39 silly idealTree:prePrune │ ├─┬ p-throttler@0.1.1 -39 silly idealTree:prePrune │ │ └── q@0.9.7 -39 silly idealTree:prePrune │ ├─┬ promptly@0.2.0 -39 silly idealTree:prePrune │ │ └─┬ read@1.0.7 -39 silly idealTree:prePrune │ │ └── mute-stream@0.0.5 -39 silly idealTree:prePrune │ ├── q@1.4.1 -39 silly idealTree:prePrune │ ├─┬ request-progress@0.3.1 -39 silly idealTree:prePrune │ │ └── throttleit@0.0.2 -39 silly idealTree:prePrune │ ├─┬ request@2.53.0 -39 silly idealTree:prePrune │ │ ├── aws-sign2@0.5.0 -39 silly idealTree:prePrune │ │ ├─┬ bl@0.9.4 -39 silly idealTree:prePrune │ │ │ └─┬ readable-stream@1.0.33 -39 silly idealTree:prePrune │ │ │ ├── core-util-is@1.0.2 -39 silly idealTree:prePrune │ │ │ ├── inherits@2.0.1 -39 silly idealTree:prePrune │ │ │ ├── isarray@0.0.1 -39 silly idealTree:prePrune │ │ │ └── string_decoder@0.10.31 -39 silly idealTree:prePrune │ │ ├── caseless@0.9.0 -39 silly idealTree:prePrune │ │ ├─┬ combined-stream@0.0.7 -39 silly idealTree:prePrune │ │ │ └── delayed-stream@0.0.5 -39 silly idealTree:prePrune │ │ ├── forever-agent@0.5.2 -39 silly idealTree:prePrune │ │ ├─┬ form-data@0.2.0 -39 silly idealTree:prePrune │ │ │ └── async@0.9.2 -39 silly idealTree:prePrune │ │ ├─┬ hawk@2.3.1 -39 silly idealTree:prePrune │ │ │ ├── boom@2.10.1 -39 silly idealTree:prePrune │ │ │ ├── cryptiles@2.0.5 -39 silly idealTree:prePrune │ │ │ ├── hoek@2.16.3 -39 silly idealTree:prePrune │ │ │ └── sntp@1.0.9 -39 silly idealTree:prePrune │ │ ├─┬ http-signature@0.10.1 -39 silly idealTree:prePrune │ │ │ ├── asn1@0.1.11 -39 silly idealTree:prePrune │ │ │ ├── assert-plus@0.1.5 -39 silly idealTree:prePrune │ │ │ └── ctype@0.5.3 -39 silly idealTree:prePrune │ │ ├── isstream@0.1.2 -39 silly idealTree:prePrune │ │ ├── json-stringify-safe@5.0.1 -39 silly idealTree:prePrune │ │ ├─┬ mime-types@2.0.14 -39 silly idealTree:prePrune │ │ │ └── mime-db@1.12.0 -39 silly idealTree:prePrune │ │ ├── node-uuid@1.4.7 -39 silly idealTree:prePrune │ │ ├── oauth-sign@0.6.0 -39 silly idealTree:prePrune │ │ ├── qs@2.3.3 -39 silly idealTree:prePrune │ │ ├── stringstream@0.0.5 -39 silly idealTree:prePrune │ │ ├── tough-cookie@2.2.1 -39 silly idealTree:prePrune │ │ └── tunnel-agent@0.4.1 -39 silly idealTree:prePrune │ ├── retry@0.6.1 -39 silly idealTree:prePrune │ ├─┬ rimraf@2.4.4 -39 silly idealTree:prePrune │ │ └─┬ glob@5.0.15 -39 silly idealTree:prePrune │ │ ├─┬ inflight@1.0.4 -39 silly idealTree:prePrune │ │ │ └── wrappy@1.0.1 -39 silly idealTree:prePrune │ │ ├── inherits@2.0.1 -39 silly idealTree:prePrune │ │ ├─┬ minimatch@3.0.0 -39 silly idealTree:prePrune │ │ │ └─┬ brace-expansion@1.1.2 -39 silly idealTree:prePrune │ │ │ ├── balanced-match@0.3.0 -39 silly idealTree:prePrune │ │ │ └── concat-map@0.0.1 -39 silly idealTree:prePrune │ │ ├─┬ once@1.3.3 -39 silly idealTree:prePrune │ │ │ └── wrappy@1.0.1 -39 silly idealTree:prePrune │ │ └── path-is-absolute@1.0.0 -39 silly idealTree:prePrune │ ├── semver@2.3.2 -39 silly idealTree:prePrune │ ├─┬ shell-quote@1.4.3 -39 silly idealTree:prePrune │ │ ├── array-filter@0.0.1 -39 silly idealTree:prePrune │ │ ├── array-map@0.0.0 -39 silly idealTree:prePrune │ │ ├── array-reduce@0.0.0 -39 silly idealTree:prePrune │ │ └── jsonify@0.0.0 -39 silly idealTree:prePrune │ ├── stringify-object@1.0.1 -39 silly idealTree:prePrune │ ├─┬ tar-fs@1.8.1 -39 silly idealTree:prePrune │ │ ├─┬ pump@1.0.1 -39 silly idealTree:prePrune │ │ │ ├── end-of-stream@1.1.0 -39 silly idealTree:prePrune │ │ │ └─┬ once@1.3.3 -39 silly idealTree:prePrune │ │ │ └── wrappy@1.0.1 -39 silly idealTree:prePrune │ │ └─┬ tar-stream@1.3.1 -39 silly idealTree:prePrune │ │ ├── bl@1.0.0 -39 silly idealTree:prePrune │ │ ├─┬ end-of-stream@1.1.0 -39 silly idealTree:prePrune │ │ │ └─┬ once@1.3.3 -39 silly idealTree:prePrune │ │ │ └── wrappy@1.0.1 -39 silly idealTree:prePrune │ │ ├─┬ readable-stream@2.0.4 -39 silly idealTree:prePrune │ │ │ ├── core-util-is@1.0.2 -39 silly idealTree:prePrune │ │ │ ├── inherits@2.0.1 -39 silly idealTree:prePrune │ │ │ ├── isarray@0.0.1 -39 silly idealTree:prePrune │ │ │ ├── process-nextick-args@1.0.6 -39 silly idealTree:prePrune │ │ │ ├── string_decoder@0.10.31 -39 silly idealTree:prePrune │ │ │ └── util-deprecate@1.0.2 -39 silly idealTree:prePrune │ │ └── xtend@4.0.1 -39 silly idealTree:prePrune │ ├── tmp@0.0.24 -39 silly idealTree:prePrune │ ├─┬ update-notifier@0.3.2 -39 silly idealTree:prePrune │ │ ├── is-npm@1.0.0 -39 silly idealTree:prePrune │ │ ├─┬ latest-version@1.0.1 -39 silly idealTree:prePrune │ │ │ └─┬ package-json@1.2.0 -39 silly idealTree:prePrune │ │ │ ├─┬ got@3.3.1 -39 silly idealTree:prePrune │ │ │ │ ├─┬ duplexify@3.4.2 -39 silly idealTree:prePrune │ │ │ │ │ ├─┬ end-of-stream@1.0.0 -39 silly idealTree:prePrune │ │ │ │ │ │ └─┬ once@1.3.3 -39 silly idealTree:prePrune │ │ │ │ │ │ └── wrappy@1.0.1 -39 silly idealTree:prePrune │ │ │ │ │ └─┬ readable-stream@2.0.4 -39 silly idealTree:prePrune │ │ │ │ │ ├── core-util-is@1.0.2 -39 silly idealTree:prePrune │ │ │ │ │ ├── inherits@2.0.1 -39 silly idealTree:prePrune │ │ │ │ │ ├── isarray@0.0.1 -39 silly idealTree:prePrune │ │ │ │ │ ├── process-nextick-args@1.0.6 -39 silly idealTree:prePrune │ │ │ │ │ ├── string_decoder@0.10.31 -39 silly idealTree:prePrune │ │ │ │ │ └── util-deprecate@1.0.2 -39 silly idealTree:prePrune │ │ │ │ ├── infinity-agent@2.0.3 -39 silly idealTree:prePrune │ │ │ │ ├── is-redirect@1.0.0 -39 silly idealTree:prePrune │ │ │ │ ├── is-stream@1.0.1 -39 silly idealTree:prePrune │ │ │ │ ├── lowercase-keys@1.0.0 -39 silly idealTree:prePrune │ │ │ │ ├─┬ nested-error-stacks@1.0.2 -39 silly idealTree:prePrune │ │ │ │ │ └── inherits@2.0.1 -39 silly idealTree:prePrune │ │ │ │ ├── object-assign@3.0.0 -39 silly idealTree:prePrune │ │ │ │ ├── prepend-http@1.0.3 -39 silly idealTree:prePrune │ │ │ │ ├─┬ read-all-stream@3.0.1 -39 silly idealTree:prePrune │ │ │ │ │ ├─┬ pinkie-promise@1.0.0 -39 silly idealTree:prePrune │ │ │ │ │ │ └── pinkie@1.0.0 -39 silly idealTree:prePrune │ │ │ │ │ └─┬ readable-stream@2.0.4 -39 silly idealTree:prePrune │ │ │ │ │ ├── core-util-is@1.0.2 -39 silly idealTree:prePrune │ │ │ │ │ ├── inherits@2.0.1 -39 silly idealTree:prePrune │ │ │ │ │ ├── isarray@0.0.1 -39 silly idealTree:prePrune │ │ │ │ │ ├── process-nextick-args@1.0.6 -39 silly idealTree:prePrune │ │ │ │ │ ├── string_decoder@0.10.31 -39 silly idealTree:prePrune │ │ │ │ │ └── util-deprecate@1.0.2 -39 silly idealTree:prePrune │ │ │ │ └── timed-out@2.0.0 -39 silly idealTree:prePrune │ │ │ └─┬ registry-url@3.0.3 -39 silly idealTree:prePrune │ │ │ └─┬ rc@1.1.5 -39 silly idealTree:prePrune │ │ │ ├── deep-extend@0.4.0 -39 silly idealTree:prePrune │ │ │ ├── ini@1.3.4 -39 silly idealTree:prePrune │ │ │ ├── minimist@1.2.0 -39 silly idealTree:prePrune │ │ │ └── strip-json-comments@1.0.4 -39 silly idealTree:prePrune │ │ ├─┬ semver-diff@2.1.0 -39 silly idealTree:prePrune │ │ │ └── semver@5.1.0 -39 silly idealTree:prePrune │ │ └─┬ string-length@1.0.1 -39 silly idealTree:prePrune │ │ └─┬ strip-ansi@3.0.0 -39 silly idealTree:prePrune │ │ └── ansi-regex@2.0.0 -39 silly idealTree:prePrune │ ├── user-home@1.1.1 -39 silly idealTree:prePrune │ └─┬ which@1.2.0 -39 silly idealTree:prePrune │ └─┬ is-absolute@0.1.7 -39 silly idealTree:prePrune │ └── is-relative@0.1.3 -39 silly idealTree:prePrune ├── bplist-parser@0.1.1 -39 silly idealTree:prePrune ├── brace-expansion@1.1.3 -39 silly idealTree:prePrune ├── braces@1.8.4 -39 silly idealTree:prePrune ├─┬ broadway@0.3.6 -39 silly idealTree:prePrune │ ├── async@0.2.10 -39 silly idealTree:prePrune │ ├── cliff@0.1.9 -39 silly idealTree:prePrune │ └── winston@0.8.0 -39 silly idealTree:prePrune ├─┬ browser-launcher2@0.4.6 -39 silly idealTree:prePrune │ └── rimraf@2.2.8 -39 silly idealTree:prePrune ├── browserify-zlib@0.1.4 -39 silly idealTree:prePrune ├── bson@0.4.23 -39 silly idealTree:prePrune ├─┬ buildmail@2.0.0 -39 silly idealTree:prePrune │ └── needle@0.10.0 -39 silly idealTree:prePrune ├── builtin-modules@1.1.1 -39 silly idealTree:prePrune ├─┬ busboy@0.2.13 -39 silly idealTree:prePrune │ └── readable-stream@1.1.14 -39 silly idealTree:prePrune ├── bytes@2.2.0 -39 silly idealTree:prePrune ├── caller@0.0.1 -39 silly idealTree:prePrune ├── callsite@1.0.0 -39 silly idealTree:prePrune ├── camel-case@1.2.2 -39 silly idealTree:prePrune ├── camelcase-keys@2.1.0 -39 silly idealTree:prePrune ├── camelcase@2.1.1 -39 silly idealTree:prePrune ├── camelize@1.0.0 -39 silly idealTree:prePrune ├── caseless@0.11.0 -39 silly idealTree:prePrune ├── center-align@0.1.3 -39 silly idealTree:prePrune ├── chalk@1.1.3 -39 silly idealTree:prePrune ├── change-case@2.1.6 -39 silly idealTree:prePrune ├── character-parser@1.2.1 -39 silly idealTree:prePrune ├── charenc@0.0.1 -39 silly idealTree:prePrune ├── chokidar@1.4.3 -39 silly idealTree:prePrune ├─┬ clean-css@3.4.12 -39 silly idealTree:prePrune │ └── source-map@0.4.4 -39 silly idealTree:prePrune ├─┬ cli@0.6.6 -39 silly idealTree:prePrune │ ├── glob@3.2.11 -39 silly idealTree:prePrune │ └── minimatch@0.3.0 -39 silly idealTree:prePrune ├─┬ cliff@0.1.10 -39 silly idealTree:prePrune │ └── colors@1.0.3 -39 silly idealTree:prePrune ├─┬ cliui@2.1.0 -39 silly idealTree:prePrune │ └── wordwrap@0.0.2 -39 silly idealTree:prePrune ├── clone-stats@0.0.1 -39 silly idealTree:prePrune ├── clone@1.0.2 -39 silly idealTree:prePrune ├── coffee-script@1.3.3 -39 silly idealTree:prePrune ├── colors@0.6.2 -39 silly idealTree:prePrune ├── combined-stream@1.0.5 -39 silly idealTree:prePrune ├── commander@2.8.1 -39 silly idealTree:prePrune ├── component-bind@1.0.0 -39 silly idealTree:prePrune ├── component-emitter@1.1.2 -39 silly idealTree:prePrune ├── component-inherit@0.0.3 -39 silly idealTree:prePrune ├── compressible@2.0.7 -39 silly idealTree:prePrune ├── compression@1.6.1 -39 silly idealTree:prePrune ├── concat-map@0.0.1 -39 silly idealTree:prePrune ├─┬ concat-stream@1.5.1 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ └── readable-stream@2.0.6 -39 silly idealTree:prePrune ├─┬ configstore@1.4.0 -39 silly idealTree:prePrune │ └── object-assign@4.0.1 -39 silly idealTree:prePrune ├── connect-flash@0.1.1 -39 silly idealTree:prePrune ├── connect-mongo@0.8.2 -39 silly idealTree:prePrune ├─┬ connect@3.4.0 -39 silly idealTree:prePrune │ ├── escape-html@1.0.2 -39 silly idealTree:prePrune │ └── finalhandler@0.4.0 -39 silly idealTree:prePrune ├── console-browserify@1.1.0 -39 silly idealTree:prePrune ├── consolidate@0.13.1 -39 silly idealTree:prePrune ├── constant-case@1.1.2 -39 silly idealTree:prePrune ├─┬ constantinople@3.0.2 -39 silly idealTree:prePrune │ └── acorn@2.7.0 -39 silly idealTree:prePrune ├── content-disposition@0.5.1 -39 silly idealTree:prePrune ├── content-security-policy-builder@0.2.0 -39 silly idealTree:prePrune ├── content-type@1.0.1 -39 silly idealTree:prePrune ├── convert-source-map@1.1.3 -39 silly idealTree:prePrune ├── cookie-parser@1.4.1 -39 silly idealTree:prePrune ├── cookie-signature@1.0.6 -39 silly idealTree:prePrune ├── cookie@0.2.3 -39 silly idealTree:prePrune ├── cookiejar@2.0.6 -39 silly idealTree:prePrune ├── core-js@2.2.2 -39 silly idealTree:prePrune ├── core-util-is@1.0.2 -39 silly idealTree:prePrune ├─┬ coveralls@2.11.9 -39 silly idealTree:prePrune │ ├── bl@1.0.3 -39 silly idealTree:prePrune │ ├── esprima@1.0.4 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ ├── js-yaml@3.0.1 -39 silly idealTree:prePrune │ ├── minimist@1.2.0 -39 silly idealTree:prePrune │ ├── readable-stream@2.0.6 -39 silly idealTree:prePrune │ └── request@2.67.0 -39 silly idealTree:prePrune ├── crc@3.3.0 -39 silly idealTree:prePrune ├── crypt@0.0.1 -39 silly idealTree:prePrune ├── cryptiles@2.0.5 -39 silly idealTree:prePrune ├── css-parse@1.0.4 -39 silly idealTree:prePrune ├── css-stringify@1.0.5 -39 silly idealTree:prePrune ├── css@1.0.8 -39 silly idealTree:prePrune ├── csslint@0.10.0 -39 silly idealTree:prePrune ├── ctype@0.5.3 -39 silly idealTree:prePrune ├── custom-event@1.0.0 -39 silly idealTree:prePrune ├── cycle@1.0.3 -39 silly idealTree:prePrune ├─┬ dashdash@1.13.0 -39 silly idealTree:prePrune │ └── assert-plus@1.0.0 -39 silly idealTree:prePrune ├── dashify@0.1.0 -39 silly idealTree:prePrune ├── date-now@0.1.4 -39 silly idealTree:prePrune ├── dateformat@1.0.2-1.2.3 -39 silly idealTree:prePrune ├── debug@2.2.0 -39 silly idealTree:prePrune ├── decamelize@1.2.0 -39 silly idealTree:prePrune ├── deep-equal@1.0.1 -39 silly idealTree:prePrune ├── deep-extend@0.4.1 -39 silly idealTree:prePrune ├── deep-is@0.1.3 -39 silly idealTree:prePrune ├── default-browser-id@1.0.4 -39 silly idealTree:prePrune ├── defined@0.0.0 -39 silly idealTree:prePrune ├── delayed-stream@1.0.0 -39 silly idealTree:prePrune ├── delegates@1.0.0 -39 silly idealTree:prePrune ├── depd@1.1.0 -39 silly idealTree:prePrune ├── destroy@1.0.4 -39 silly idealTree:prePrune ├── device@0.3.6 -39 silly idealTree:prePrune ├── di@0.0.1 -39 silly idealTree:prePrune ├─┬ dicer@0.2.5 -39 silly idealTree:prePrune │ └── readable-stream@1.1.14 -39 silly idealTree:prePrune ├── diff@1.4.0 -39 silly idealTree:prePrune ├── director@1.2.7 -39 silly idealTree:prePrune ├── dom-serialize@2.2.1 -39 silly idealTree:prePrune ├─┬ dom-serializer@0.1.0 -39 silly idealTree:prePrune │ ├── domelementtype@1.1.3 -39 silly idealTree:prePrune │ └── entities@1.1.1 -39 silly idealTree:prePrune ├── domelementtype@1.3.0 -39 silly idealTree:prePrune ├── domhandler@2.3.0 -39 silly idealTree:prePrune ├── domutils@1.5.1 -39 silly idealTree:prePrune ├── dont-sniff-mimetype@0.1.0 -39 silly idealTree:prePrune ├── dot-case@1.1.2 -39 silly idealTree:prePrune ├── double-ended-queue@2.1.0-0 -39 silly idealTree:prePrune ├── duplexer@0.1.1 -39 silly idealTree:prePrune ├─┬ duplexify@3.4.3 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ └── readable-stream@2.1.0 -39 silly idealTree:prePrune ├── ecc-jsbn@0.1.1 -39 silly idealTree:prePrune ├── ee-first@1.1.1 -39 silly idealTree:prePrune ├── email-addresses@2.0.2 -39 silly idealTree:prePrune ├── email-verification@0.1.9 -39 silly idealTree:prePrune ├── end-of-stream@1.0.0 -39 silly idealTree:prePrune ├─┬ engine.io-client@1.6.8 -39 silly idealTree:prePrune │ └── ws@1.0.1 -39 silly idealTree:prePrune ├─┬ engine.io-parser@1.2.4 -39 silly idealTree:prePrune │ └── has-binary@0.1.6 -39 silly idealTree:prePrune ├─┬ engine.io@1.6.8 -39 silly idealTree:prePrune │ ├── accepts@1.1.4 -39 silly idealTree:prePrune │ ├── mime-db@1.12.0 -39 silly idealTree:prePrune │ ├── mime-types@2.0.14 -39 silly idealTree:prePrune │ ├── negotiator@0.4.9 -39 silly idealTree:prePrune │ └── ws@1.0.1 -39 silly idealTree:prePrune ├── ent@2.2.0 -39 silly idealTree:prePrune ├── entities@1.0.0 -39 silly idealTree:prePrune ├── error-ex@1.3.0 -39 silly idealTree:prePrune ├── es6-promise@2.1.1 -39 silly idealTree:prePrune ├── escape-html@1.0.3 -39 silly idealTree:prePrune ├── escape-string-regexp@1.0.5 -39 silly idealTree:prePrune ├─┬ escodegen@1.8.0 -39 silly idealTree:prePrune │ └── source-map@0.2.0 -39 silly idealTree:prePrune ├── esmangle-evaluator@1.0.0 -39 silly idealTree:prePrune ├── esprima@2.7.2 -39 silly idealTree:prePrune ├── estraverse@1.9.3 -39 silly idealTree:prePrune ├── esutils@2.0.2 -39 silly idealTree:prePrune ├── etag@1.7.0 -39 silly idealTree:prePrune ├─┬ event-stream@0.5.3 -39 silly idealTree:prePrune │ └── optimist@0.2.8 -39 silly idealTree:prePrune ├── eventemitter2@0.4.14 -39 silly idealTree:prePrune ├── eventemitter3@1.2.0 -39 silly idealTree:prePrune ├── exit@0.1.2 -39 silly idealTree:prePrune ├─┬ expand-braces@0.1.2 -39 silly idealTree:prePrune │ ├── braces@0.1.5 -39 silly idealTree:prePrune │ ├── expand-range@0.1.1 -39 silly idealTree:prePrune │ ├── is-number@0.1.1 -39 silly idealTree:prePrune │ └── repeat-string@0.2.2 -39 silly idealTree:prePrune ├── expand-brackets@0.1.5 -39 silly idealTree:prePrune ├── expand-range@1.8.1 -39 silly idealTree:prePrune ├── express-device@0.4.2 -39 silly idealTree:prePrune ├── express-partials@0.3.0 -39 silly idealTree:prePrune ├── express-session@1.12.1 -39 silly idealTree:prePrune ├─┬ express@4.13.4 -39 silly idealTree:prePrune │ ├── accepts@1.2.13 -39 silly idealTree:prePrune │ ├── cookie@0.1.5 -39 silly idealTree:prePrune │ ├── negotiator@0.5.3 -39 silly idealTree:prePrune │ ├── qs@4.0.0 -39 silly idealTree:prePrune │ └── vary@1.0.1 -39 silly idealTree:prePrune ├── extend@3.0.0 -39 silly idealTree:prePrune ├── extglob@0.3.2 -39 silly idealTree:prePrune ├─┬ extract-zip@1.5.0 -39 silly idealTree:prePrune │ ├── concat-stream@1.5.0 -39 silly idealTree:prePrune │ ├── debug@0.7.4 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ ├── minimist@0.0.8 -39 silly idealTree:prePrune │ ├── mkdirp@0.5.0 -39 silly idealTree:prePrune │ └── readable-stream@2.0.6 -39 silly idealTree:prePrune ├── extsprintf@1.0.2 -39 silly idealTree:prePrune ├── eyes@0.1.8 -39 silly idealTree:prePrune ├── falafel@1.2.0 -39 silly idealTree:prePrune ├── fast-levenshtein@1.1.3 -39 silly idealTree:prePrune ├── faye-websocket@0.4.4 -39 silly idealTree:prePrune ├── fd-slicer@1.0.1 -39 silly idealTree:prePrune ├── fdf@0.0.0 -39 silly idealTree:prePrune ├── figures@1.5.0 -39 silly idealTree:prePrune ├── filename-regex@2.0.0 -39 silly idealTree:prePrune ├─┬ fileset@0.2.1 -39 silly idealTree:prePrune │ ├── glob@5.0.15 -39 silly idealTree:prePrune │ └── minimatch@2.0.10 -39 silly idealTree:prePrune ├── fill-range@2.2.3 -39 silly idealTree:prePrune ├── finalhandler@0.4.1 -39 silly idealTree:prePrune ├── find-index@0.1.1 -39 silly idealTree:prePrune ├── find-up@1.1.2 -39 silly idealTree:prePrune ├─┬ findup-sync@0.1.3 -39 silly idealTree:prePrune │ ├── glob@3.2.11 -39 silly idealTree:prePrune │ └── minimatch@0.3.0 -39 silly idealTree:prePrune ├── first-chunk-stream@1.0.0 -39 silly idealTree:prePrune ├─┬ flatiron@0.4.3 -39 silly idealTree:prePrune │ └── optimist@0.6.0 -39 silly idealTree:prePrune ├── for-in@0.1.5 -39 silly idealTree:prePrune ├── for-own@0.1.4 -39 silly idealTree:prePrune ├── foreach@2.0.5 -39 silly idealTree:prePrune ├── forever-agent@0.6.1 -39 silly idealTree:prePrune ├─┬ forever-monitor@1.6.0 -39 silly idealTree:prePrune │ └── minimatch@2.0.10 -39 silly idealTree:prePrune ├── forever@0.15.1 -39 silly idealTree:prePrune ├── form-data@1.0.0-rc4 -39 silly idealTree:prePrune ├── formidable@1.0.17 -39 silly idealTree:prePrune ├── forwarded@0.1.0 -39 silly idealTree:prePrune ├── frameguard@0.2.2 -39 silly idealTree:prePrune ├── fresh@0.3.0 -39 silly idealTree:prePrune ├── from@0.1.3 -39 silly idealTree:prePrune ├── fs-access@1.0.0 -39 silly idealTree:prePrune ├── fs-extra@0.26.7 -39 silly idealTree:prePrune ├── fstream-ignore@1.0.3 -39 silly idealTree:prePrune ├── fstream@1.0.8 -39 silly idealTree:prePrune ├── gauge@1.2.7 -39 silly idealTree:prePrune ├── gaze@0.5.2 -39 silly idealTree:prePrune ├── generate-function@2.0.0 -39 silly idealTree:prePrune ├── generate-object-property@1.2.0 -39 silly idealTree:prePrune ├── get-stdin@4.0.1 -39 silly idealTree:prePrune ├── getobject@0.1.0 -39 silly idealTree:prePrune ├── glob-base@0.3.0 -39 silly idealTree:prePrune ├── glob-parent@2.0.0 -39 silly idealTree:prePrune ├─┬ glob-stream@4.1.1 -39 silly idealTree:prePrune │ ├── glob@4.5.3 -39 silly idealTree:prePrune │ └── minimatch@2.0.10 -39 silly idealTree:prePrune ├── glob-watcher@0.0.8 -39 silly idealTree:prePrune ├── glob2base@0.0.12 -39 silly idealTree:prePrune ├── glob@7.0.3 -39 silly idealTree:prePrune ├─┬ globby@2.1.0 -39 silly idealTree:prePrune │ └── glob@5.0.15 -39 silly idealTree:prePrune ├─┬ globule@0.1.0 -39 silly idealTree:prePrune │ ├── glob@3.1.21 -39 silly idealTree:prePrune │ ├── graceful-fs@1.2.3 -39 silly idealTree:prePrune │ ├── inherits@1.0.2 -39 silly idealTree:prePrune │ ├── lodash@1.0.2 -39 silly idealTree:prePrune │ └── minimatch@0.2.14 -39 silly idealTree:prePrune ├── got@3.3.1 -39 silly idealTree:prePrune ├── graceful-fs@4.1.3 -39 silly idealTree:prePrune ├── graceful-readlink@1.0.1 -39 silly idealTree:prePrune ├── growl@1.8.1 -39 silly idealTree:prePrune ├── grunt-cli@0.1.13 -39 silly idealTree:prePrune ├── grunt-concurrent@2.3.0 -39 silly idealTree:prePrune ├─┬ grunt-contrib-csslint@0.5.0 -39 silly idealTree:prePrune │ ├── lodash@3.10.1 -39 silly idealTree:prePrune │ └── strip-json-comments@1.0.4 -39 silly idealTree:prePrune ├── grunt-contrib-cssmin@0.14.0 -39 silly idealTree:prePrune ├── grunt-contrib-jshint@0.11.3 -39 silly idealTree:prePrune ├─┬ grunt-contrib-uglify@0.11.1 -39 silly idealTree:prePrune │ ├── gzip-size@3.0.0 -39 silly idealTree:prePrune │ ├── lodash@4.11.1 -39 silly idealTree:prePrune │ ├── maxmin@2.1.0 -39 silly idealTree:prePrune │ └── pretty-bytes@3.0.1 -39 silly idealTree:prePrune ├─┬ grunt-contrib-watch@0.6.1 -39 silly idealTree:prePrune │ └── async@0.2.10 -39 silly idealTree:prePrune ├── grunt-env@0.4.4 -39 silly idealTree:prePrune ├── grunt-html2js@0.3.6 -39 silly idealTree:prePrune ├─┬ grunt-karma@0.12.2 -39 silly idealTree:prePrune │ └── lodash@3.10.1 -39 silly idealTree:prePrune ├─┬ grunt-legacy-log-utils@0.1.1 -39 silly idealTree:prePrune │ └── underscore.string@2.3.3 -39 silly idealTree:prePrune ├─┬ grunt-legacy-log@0.1.3 -39 silly idealTree:prePrune │ └── underscore.string@2.3.3 -39 silly idealTree:prePrune ├─┬ grunt-legacy-util@0.2.0 -39 silly idealTree:prePrune │ ├── async@0.1.22 -39 silly idealTree:prePrune │ └── lodash@0.9.2 -39 silly idealTree:prePrune ├── grunt-mocha-istanbul@3.0.1 -39 silly idealTree:prePrune ├── grunt-mocha-test@0.12.7 -39 silly idealTree:prePrune ├─┬ grunt-newer@1.1.2 -39 silly idealTree:prePrune │ ├── async@0.9.0 -39 silly idealTree:prePrune │ └── rimraf@2.2.8 -39 silly idealTree:prePrune ├── grunt-ng-annotate@1.0.1 -39 silly idealTree:prePrune ├── grunt-node-inspector@0.4.1 -39 silly idealTree:prePrune ├── grunt-nodemon@0.4.2 -39 silly idealTree:prePrune ├─┬ grunt@0.4.5 -39 silly idealTree:prePrune │ ├── async@0.1.22 -39 silly idealTree:prePrune │ ├── glob@3.1.21 -39 silly idealTree:prePrune │ ├── graceful-fs@1.2.3 -39 silly idealTree:prePrune │ ├── iconv-lite@0.2.11 -39 silly idealTree:prePrune │ ├── inherits@1.0.2 -39 silly idealTree:prePrune │ ├── lodash@0.9.2 -39 silly idealTree:prePrune │ ├── minimatch@0.2.14 -39 silly idealTree:prePrune │ └── rimraf@2.2.8 -39 silly idealTree:prePrune ├── gzip-size@1.0.0 -39 silly idealTree:prePrune ├─┬ handlebars@4.0.5 -39 silly idealTree:prePrune │ └── source-map@0.4.4 -39 silly idealTree:prePrune ├─┬ har-validator@2.0.6 -39 silly idealTree:prePrune │ └── commander@2.9.0 -39 silly idealTree:prePrune ├── has-ansi@2.0.0 -39 silly idealTree:prePrune ├── has-binary@0.1.7 -39 silly idealTree:prePrune ├── has-cors@1.1.0 -39 silly idealTree:prePrune ├── has-flag@1.0.0 -39 silly idealTree:prePrune ├── has-unicode@2.0.0 -39 silly idealTree:prePrune ├── hasha@2.2.0 -39 silly idealTree:prePrune ├── hawk@3.1.3 -39 silly idealTree:prePrune ├── headless@0.1.7 -39 silly idealTree:prePrune ├── helmet-crossdomain@0.1.0 -39 silly idealTree:prePrune ├── helmet-csp@0.3.0 -39 silly idealTree:prePrune ├── helmet@0.14.0 -39 silly idealTree:prePrune ├── hide-powered-by@0.1.0 -39 silly idealTree:prePrune ├── hoek@2.16.3 -39 silly idealTree:prePrune ├── hooker@0.2.3 -39 silly idealTree:prePrune ├── hooks@0.2.1 -39 silly idealTree:prePrune ├── hosted-git-info@2.1.4 -39 silly idealTree:prePrune ├── hpkp@0.2.0 -39 silly idealTree:prePrune ├─┬ hsts@0.2.0 -39 silly idealTree:prePrune │ └── core-util-is@1.0.1 -39 silly idealTree:prePrune ├─┬ html-minifier@0.6.9 -39 silly idealTree:prePrune │ ├── async@0.2.10 -39 silly idealTree:prePrune │ ├── camelcase@1.2.1 -39 silly idealTree:prePrune │ ├── clean-css@2.2.23 -39 silly idealTree:prePrune │ ├── commander@2.2.0 -39 silly idealTree:prePrune │ ├── source-map@0.1.34 -39 silly idealTree:prePrune │ ├── uglify-js@2.4.24 -39 silly idealTree:prePrune │ ├── wordwrap@0.0.2 -39 silly idealTree:prePrune │ └── yargs@3.5.4 -39 silly idealTree:prePrune ├─┬ htmlparser2@3.8.3 -39 silly idealTree:prePrune │ └── readable-stream@1.1.14 -39 silly idealTree:prePrune ├── http-errors@1.3.1 -39 silly idealTree:prePrune ├── http-proxy@1.13.2 -39 silly idealTree:prePrune ├── http-signature@1.1.1 -39 silly idealTree:prePrune ├── i@0.3.4 -39 silly idealTree:prePrune ├── iconv-lite@0.4.13 -39 silly idealTree:prePrune ├── ienoopen@0.1.0 -39 silly idealTree:prePrune ├── ignore-by-default@1.0.1 -39 silly idealTree:prePrune ├── imurmurhash@0.1.4 -39 silly idealTree:prePrune ├── indent-string@2.1.0 -39 silly idealTree:prePrune ├── indexof@0.0.1 -39 silly idealTree:prePrune ├── infinity-agent@2.0.3 -39 silly idealTree:prePrune ├── inflight@1.0.4 -39 silly idealTree:prePrune ├── inherits@2.0.1 -39 silly idealTree:prePrune ├── ini@1.3.4 -39 silly idealTree:prePrune ├── inline-process-browser@2.0.1 -39 silly idealTree:prePrune ├── ipaddr.js@1.0.5 -39 silly idealTree:prePrune ├── is-absolute@0.1.7 -39 silly idealTree:prePrune ├── is-arrayish@0.2.1 -39 silly idealTree:prePrune ├── is-binary-path@1.0.1 -39 silly idealTree:prePrune ├── is-buffer@1.1.3 -39 silly idealTree:prePrune ├── is-builtin-module@1.0.0 -39 silly idealTree:prePrune ├── is-dotfile@1.0.2 -39 silly idealTree:prePrune ├── is-equal-shallow@0.1.3 -39 silly idealTree:prePrune ├── is-extendable@0.1.1 -39 silly idealTree:prePrune ├── is-extglob@1.0.0 -39 silly idealTree:prePrune ├── is-finite@1.0.1 -39 silly idealTree:prePrune ├── is-glob@2.0.1 -39 silly idealTree:prePrune ├── is-lower-case@1.1.3 -39 silly idealTree:prePrune ├── is-my-json-valid@2.13.1 -39 silly idealTree:prePrune ├── is-npm@1.0.0 -39 silly idealTree:prePrune ├── is-number@2.1.0 -39 silly idealTree:prePrune ├── is-posix-bracket@0.1.1 -39 silly idealTree:prePrune ├── is-primitive@2.0.0 -39 silly idealTree:prePrune ├── is-promise@2.1.0 -39 silly idealTree:prePrune ├── is-property@1.0.2 -39 silly idealTree:prePrune ├── is-redirect@1.0.0 -39 silly idealTree:prePrune ├── is-relative@0.1.3 -39 silly idealTree:prePrune ├── is-stream@1.1.0 -39 silly idealTree:prePrune ├── is-typedarray@1.0.0 -39 silly idealTree:prePrune ├── is-upper-case@1.1.2 -39 silly idealTree:prePrune ├── is-utf8@0.2.1 -39 silly idealTree:prePrune ├── isarray@0.0.1 -39 silly idealTree:prePrune ├── isbinaryfile@3.0.0 -39 silly idealTree:prePrune ├── isexe@1.1.2 -39 silly idealTree:prePrune ├── isobject@2.0.0 -39 silly idealTree:prePrune ├── isstream@0.1.2 -39 silly idealTree:prePrune ├─┬ istanbul@0.4.3 -39 silly idealTree:prePrune │ ├── argparse@1.0.7 -39 silly idealTree:prePrune │ ├── js-yaml@3.6.0 -39 silly idealTree:prePrune │ ├── nopt@3.0.6 -39 silly idealTree:prePrune │ ├── resolve@1.1.7 -39 silly idealTree:prePrune │ ├── supports-color@3.1.2 -39 silly idealTree:prePrune │ ├── which@1.2.4 -39 silly idealTree:prePrune │ └── wordwrap@1.0.0 -39 silly idealTree:prePrune ├─┬ jade@1.11.0 -39 silly idealTree:prePrune │ └── commander@2.6.0 -39 silly idealTree:prePrune ├── jasmine-core@2.4.1 -39 silly idealTree:prePrune ├── jit-grunt@0.9.1 -39 silly idealTree:prePrune ├── jodid25519@1.0.2 -39 silly idealTree:prePrune ├─┬ js-yaml@2.0.5 -39 silly idealTree:prePrune │ └── esprima@1.0.4 -39 silly idealTree:prePrune ├── jsbn@0.1.0 -39 silly idealTree:prePrune ├─┬ jshint@2.8.0 -39 silly idealTree:prePrune │ ├── lodash@3.7.0 -39 silly idealTree:prePrune │ ├── minimatch@2.0.10 -39 silly idealTree:prePrune │ └── strip-json-comments@1.0.4 -39 silly idealTree:prePrune ├── json-schema@0.2.2 -39 silly idealTree:prePrune ├── json-stable-stringify@1.0.1 -39 silly idealTree:prePrune ├── json-stringify-safe@5.0.1 -39 silly idealTree:prePrune ├── json3@3.2.6 -39 silly idealTree:prePrune ├── jsonfile@2.3.0 -39 silly idealTree:prePrune ├── jsonify@0.0.0 -39 silly idealTree:prePrune ├── jsonpointer@2.0.0 -39 silly idealTree:prePrune ├── jsprim@1.2.2 -39 silly idealTree:prePrune ├── jstransformer@0.0.2 -39 silly idealTree:prePrune ├─┬ karma-chrome-launcher@0.2.3 -39 silly idealTree:prePrune │ └── which@1.2.4 -39 silly idealTree:prePrune ├─┬ karma-coverage@0.5.5 -39 silly idealTree:prePrune │ └── dateformat@1.0.12 -39 silly idealTree:prePrune ├── karma-firefox-launcher@0.1.7 -39 silly idealTree:prePrune ├─┬ karma-jasmine-html-reporter@0.1.8 -39 silly idealTree:prePrune │ └── karma-jasmine@0.2.3 -39 silly idealTree:prePrune ├── karma-jasmine@0.3.8 -39 silly idealTree:prePrune ├─┬ karma-mocha-reporter@1.3.0 -39 silly idealTree:prePrune │ └── chalk@1.1.1 -39 silly idealTree:prePrune ├── karma-ng-html2js-preprocessor@0.2.2 -39 silly idealTree:prePrune ├─┬ karma-phantomjs-launcher@0.2.3 -39 silly idealTree:prePrune │ └── lodash@3.10.1 -39 silly idealTree:prePrune ├─┬ karma@0.13.22 -39 silly idealTree:prePrune │ ├── colors@1.1.2 -39 silly idealTree:prePrune │ └── lodash@3.10.1 -39 silly idealTree:prePrune ├── kerberos@0.0.11 -39 silly idealTree:prePrune ├── kew@0.7.0 -39 silly idealTree:prePrune ├── kind-of@3.0.2 -39 silly idealTree:prePrune ├── klaw@1.2.0 -39 silly idealTree:prePrune ├── latest-version@1.0.1 -39 silly idealTree:prePrune ├── lazy-cache@1.0.3 -39 silly idealTree:prePrune ├── lazy@1.0.11 -39 silly idealTree:prePrune ├── lcov-parse@0.0.6 -39 silly idealTree:prePrune ├── levn@0.3.0 -39 silly idealTree:prePrune ├── libbase64@0.1.0 -39 silly idealTree:prePrune ├── libmime@1.2.0 -39 silly idealTree:prePrune ├── libqp@1.1.0 -39 silly idealTree:prePrune ├── load-json-file@1.1.0 -39 silly idealTree:prePrune ├── lodash._arraycopy@3.0.0 -39 silly idealTree:prePrune ├── lodash._arrayeach@3.0.0 -39 silly idealTree:prePrune ├── lodash._baseassign@3.2.0 -39 silly idealTree:prePrune ├── lodash._baseclone@3.3.0 -39 silly idealTree:prePrune ├── lodash._basecopy@3.0.1 -39 silly idealTree:prePrune ├── lodash._baseflatten@3.1.4 -39 silly idealTree:prePrune ├── lodash._basefor@3.0.3 -39 silly idealTree:prePrune ├── lodash._baseslice@4.0.0 -39 silly idealTree:prePrune ├── lodash._bindcallback@3.0.1 -39 silly idealTree:prePrune ├── lodash._createassigner@3.1.1 -39 silly idealTree:prePrune ├── lodash._getnative@3.9.1 -39 silly idealTree:prePrune ├── lodash._isiterateecall@3.0.9 -39 silly idealTree:prePrune ├── lodash._pickbyarray@3.0.2 -39 silly idealTree:prePrune ├── lodash._pickbycallback@3.0.0 -39 silly idealTree:prePrune ├── lodash.assign@3.2.0 -39 silly idealTree:prePrune ├── lodash.clonedeep@3.0.2 -39 silly idealTree:prePrune ├── lodash.defaults@3.1.2 -39 silly idealTree:prePrune ├── lodash.isarguments@3.0.8 -39 silly idealTree:prePrune ├── lodash.isarray@3.0.4 -39 silly idealTree:prePrune ├── lodash.isstring@3.0.1 -39 silly idealTree:prePrune ├── lodash.keys@3.1.2 -39 silly idealTree:prePrune ├── lodash.keysin@3.0.8 -39 silly idealTree:prePrune ├── lodash.pad@4.3.0 -39 silly idealTree:prePrune ├── lodash.padend@4.4.0 -39 silly idealTree:prePrune ├── lodash.padstart@4.4.0 -39 silly idealTree:prePrune ├── lodash.pick@3.1.0 -39 silly idealTree:prePrune ├── lodash.restparam@3.6.1 -39 silly idealTree:prePrune ├── lodash.tostring@4.1.2 -39 silly idealTree:prePrune ├── lodash@2.4.2 -39 silly idealTree:prePrune ├── log-driver@1.2.4 -39 silly idealTree:prePrune ├─┬ log4js@0.6.35 -39 silly idealTree:prePrune │ └── semver@4.3.6 -39 silly idealTree:prePrune ├── longest@1.0.1 -39 silly idealTree:prePrune ├── loud-rejection@1.3.0 -39 silly idealTree:prePrune ├── lower-case@1.1.3 -39 silly idealTree:prePrune ├── lowercase-keys@1.0.0 -39 silly idealTree:prePrune ├── lru-cache@2.2.4 -39 silly idealTree:prePrune ├── lsmod@0.0.3 -39 silly idealTree:prePrune ├── mailcomposer@2.1.0 -39 silly idealTree:prePrune ├─┬ mailosaur@1.0.1 -39 silly idealTree:prePrune │ ├── asn1@0.1.11 -39 silly idealTree:prePrune │ ├── assert-plus@0.1.5 -39 silly idealTree:prePrune │ ├── async@0.9.2 -39 silly idealTree:prePrune │ ├── aws-sign2@0.5.0 -39 silly idealTree:prePrune │ ├── boom@0.4.2 -39 silly idealTree:prePrune │ ├── combined-stream@0.0.7 -39 silly idealTree:prePrune │ ├── cryptiles@0.2.2 -39 silly idealTree:prePrune │ ├── delayed-stream@0.0.5 -39 silly idealTree:prePrune │ ├── forever-agent@0.5.2 -39 silly idealTree:prePrune │ ├── form-data@0.1.4 -39 silly idealTree:prePrune │ ├── hawk@1.0.0 -39 silly idealTree:prePrune │ ├── hoek@0.9.1 -39 silly idealTree:prePrune │ ├── http-signature@0.10.1 -39 silly idealTree:prePrune │ ├── mime@1.2.11 -39 silly idealTree:prePrune │ ├── oauth-sign@0.3.0 -39 silly idealTree:prePrune │ ├── qs@0.6.6 -39 silly idealTree:prePrune │ ├── request@2.36.0 -39 silly idealTree:prePrune │ └── sntp@0.2.4 -39 silly idealTree:prePrune ├─┬ main-bower-files@2.9.0 -39 silly idealTree:prePrune │ ├── extend@2.0.1 -39 silly idealTree:prePrune │ ├── path-exists@1.0.0 -39 silly idealTree:prePrune │ └── strip-json-comments@1.0.4 -39 silly idealTree:prePrune ├── mandrill-api@1.0.45 -39 silly idealTree:prePrune ├── map-obj@1.0.1 -39 silly idealTree:prePrune ├── map-stream@0.1.0 -39 silly idealTree:prePrune ├── math@0.0.3 -39 silly idealTree:prePrune ├── maxmin@1.1.0 -39 silly idealTree:prePrune ├── media-typer@0.3.0 -39 silly idealTree:prePrune ├─┬ meow@3.7.0 -39 silly idealTree:prePrune │ ├── minimist@1.2.0 -39 silly idealTree:prePrune │ └── object-assign@4.0.1 -39 silly idealTree:prePrune ├── merge-descriptors@1.0.1 -39 silly idealTree:prePrune ├── merge-stream@0.1.8 -39 silly idealTree:prePrune ├─┬ method-override@2.3.5 -39 silly idealTree:prePrune │ └── vary@1.0.1 -39 silly idealTree:prePrune ├── methods@1.1.2 -39 silly idealTree:prePrune ├── micromatch@2.3.7 -39 silly idealTree:prePrune ├── mime-db@1.22.0 -39 silly idealTree:prePrune ├── mime-types@2.1.10 -39 silly idealTree:prePrune ├── mime@1.3.4 -39 silly idealTree:prePrune ├── minimatch@3.0.0 -39 silly idealTree:prePrune ├── minimist@0.0.10 -39 silly idealTree:prePrune ├─┬ mkdirp@0.5.1 -39 silly idealTree:prePrune │ └── minimist@0.0.8 -39 silly idealTree:prePrune ├── mocha-lcov-reporter@1.2.0 -39 silly idealTree:prePrune ├─┬ mocha@2.4.5 -39 silly idealTree:prePrune │ ├── commander@2.3.0 -39 silly idealTree:prePrune │ ├── escape-string-regexp@1.0.2 -39 silly idealTree:prePrune │ ├── glob@3.2.3 -39 silly idealTree:prePrune │ ├── graceful-fs@2.0.3 -39 silly idealTree:prePrune │ ├─┬ jade@0.26.3 -39 silly idealTree:prePrune │ │ ├── commander@0.6.1 -39 silly idealTree:prePrune │ │ └── mkdirp@0.3.0 -39 silly idealTree:prePrune │ ├── minimatch@0.2.14 -39 silly idealTree:prePrune │ └── supports-color@1.2.0 -39 silly idealTree:prePrune ├── mongodb-core@1.2.31 -39 silly idealTree:prePrune ├── mongodb@2.0.55 -39 silly idealTree:prePrune ├─┬ mongoose-utilities@0.1.1 -39 silly idealTree:prePrune │ ├── bson@0.2.2 -39 silly idealTree:prePrune │ ├── kerberos@0.0.3 -39 silly idealTree:prePrune │ ├── mongodb@1.3.19 -39 silly idealTree:prePrune │ ├── mongoose@3.6.20 -39 silly idealTree:prePrune │ ├─┬ mpromise@0.2.1 -39 silly idealTree:prePrune │ │ └── sliced@0.0.4 -39 silly idealTree:prePrune │ ├── ms@0.1.0 -39 silly idealTree:prePrune │ └── muri@0.3.1 -39 silly idealTree:prePrune ├─┬ mongoose@3.8.39 -39 silly idealTree:prePrune │ ├── bson@0.2.22 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ ├── mongodb@1.4.38 -39 silly idealTree:prePrune │ ├── ms@0.1.0 -39 silly idealTree:prePrune │ └── readable-stream@2.1.0 -39 silly idealTree:prePrune ├─┬ morgan@1.6.1 -39 silly idealTree:prePrune │ └── depd@1.0.1 -39 silly idealTree:prePrune ├── mpath@0.1.1 -39 silly idealTree:prePrune ├── mpromise@0.4.3 -39 silly idealTree:prePrune ├─┬ mquery@1.6.1 -39 silly idealTree:prePrune │ └── bluebird@2.9.26 -39 silly idealTree:prePrune ├── ms@0.7.1 -39 silly idealTree:prePrune ├── multer@1.1.0 -39 silly idealTree:prePrune ├── multimatch@2.1.0 -39 silly idealTree:prePrune ├── muri@1.1.0 -39 silly idealTree:prePrune ├── mute-stream@0.0.6 -39 silly idealTree:prePrune ├── nan@1.8.4 -39 silly idealTree:prePrune ├─┬ nconf@0.6.9 -39 silly idealTree:prePrune │ ├── async@0.2.9 -39 silly idealTree:prePrune │ └── optimist@0.6.0 -39 silly idealTree:prePrune ├── ncp@0.4.2 -39 silly idealTree:prePrune ├── needle@0.11.0 -39 silly idealTree:prePrune ├── negotiator@0.6.0 -39 silly idealTree:prePrune ├── nested-error-stacks@1.0.2 -39 silly idealTree:prePrune ├─┬ ng-annotate@1.2.1 -39 silly idealTree:prePrune │ └── acorn@2.6.4 -39 silly idealTree:prePrune ├── nocache@0.4.0 -39 silly idealTree:prePrune ├── node-freegeoip@0.0.1 -39 silly idealTree:prePrune ├─┬ node-inspector@0.12.8 -39 silly idealTree:prePrune │ ├── async@0.9.2 -39 silly idealTree:prePrune │ ├── glob@5.0.15 -39 silly idealTree:prePrune │ ├── semver@4.3.6 -39 silly idealTree:prePrune │ └── which@1.2.4 -39 silly idealTree:prePrune ├── node-mandrill@1.0.1 -39 silly idealTree:prePrune ├─┬ node-pre-gyp@0.6.26 -39 silly idealTree:prePrune │ └── nopt@3.0.6 -39 silly idealTree:prePrune ├── node-uuid@1.4.7 -39 silly idealTree:prePrune ├── nodemailer-direct-transport@1.1.0 -39 silly idealTree:prePrune ├── nodemailer-mandrill-transport@0.3.0 -39 silly idealTree:prePrune ├── nodemailer-smtp-transport@1.1.0 -39 silly idealTree:prePrune ├── nodemailer-wellknown@0.1.9 -39 silly idealTree:prePrune ├── nodemailer@1.10.0 -39 silly idealTree:prePrune ├─┬ nodemon@1.9.1 -39 silly idealTree:prePrune │ ├── es6-promise@3.1.2 -39 silly idealTree:prePrune │ ├── event-stream@3.3.2 -39 silly idealTree:prePrune │ └── ps-tree@1.0.1 -39 silly idealTree:prePrune ├── nopt@1.0.10 -39 silly idealTree:prePrune ├─┬ noptify@0.0.3 -39 silly idealTree:prePrune │ └── nopt@2.0.0 -39 silly idealTree:prePrune ├── normalize-package-data@2.3.5 -39 silly idealTree:prePrune ├── normalize-path@2.0.1 -39 silly idealTree:prePrune ├── npmlog@2.0.3 -39 silly idealTree:prePrune ├── nssocket@0.5.3 -39 silly idealTree:prePrune ├── null-check@1.0.0 -39 silly idealTree:prePrune ├── number-is-nan@1.0.0 -39 silly idealTree:prePrune ├── oauth-sign@0.8.1 -39 silly idealTree:prePrune ├── oauth@0.9.14 -39 silly idealTree:prePrune ├── object-assign@3.0.0 -39 silly idealTree:prePrune ├── object-component@0.0.3 -39 silly idealTree:prePrune ├── object-keys@1.0.9 -39 silly idealTree:prePrune ├── object.omit@2.0.0 -39 silly idealTree:prePrune ├── on-finished@2.3.0 -39 silly idealTree:prePrune ├── on-headers@1.0.1 -39 silly idealTree:prePrune ├── once@1.3.3 -39 silly idealTree:prePrune ├── optimist@0.6.1 -39 silly idealTree:prePrune ├─┬ optionator@0.8.1 -39 silly idealTree:prePrune │ └── wordwrap@1.0.0 -39 silly idealTree:prePrune ├── options@0.0.6 -39 silly idealTree:prePrune ├── ordered-ast-traverse@1.1.1 -39 silly idealTree:prePrune ├── ordered-esprima-props@1.1.0 -39 silly idealTree:prePrune ├── ordered-read-streams@0.1.0 -39 silly idealTree:prePrune ├── os-homedir@1.0.1 -39 silly idealTree:prePrune ├── os-tmpdir@1.0.1 -39 silly idealTree:prePrune ├── osenv@0.1.3 -39 silly idealTree:prePrune ├── package-json@1.2.0 -39 silly idealTree:prePrune ├─┬ pad-stream@1.2.0 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ ├── readable-stream@2.0.6 -39 silly idealTree:prePrune │ └── through2@2.0.1 -39 silly idealTree:prePrune ├── pako@0.2.8 -39 silly idealTree:prePrune ├── param-case@1.1.2 -39 silly idealTree:prePrune ├── parse-glob@3.0.4 -39 silly idealTree:prePrune ├── parse-json@2.2.0 -39 silly idealTree:prePrune ├── parsejson@0.0.1 -39 silly idealTree:prePrune ├── parseqs@0.0.2 -39 silly idealTree:prePrune ├── parserlib@0.2.5 -39 silly idealTree:prePrune ├── parseuri@0.0.4 -39 silly idealTree:prePrune ├── parseurl@1.3.1 -39 silly idealTree:prePrune ├── pascal-case@1.1.2 -39 silly idealTree:prePrune ├── passport-facebook@2.0.0 -39 silly idealTree:prePrune ├── passport-github@1.0.0 -39 silly idealTree:prePrune ├── passport-google-oauth@0.2.0 -39 silly idealTree:prePrune ├── passport-linkedin@1.0.0 -39 silly idealTree:prePrune ├── passport-local@1.0.0 -39 silly idealTree:prePrune ├── passport-oauth1@1.1.0 -39 silly idealTree:prePrune ├── passport-oauth2@1.3.0 -39 silly idealTree:prePrune ├── passport-oauth@1.0.0 -39 silly idealTree:prePrune ├── passport-strategy@1.0.0 -39 silly idealTree:prePrune ├── passport-twitter@1.0.4 -39 silly idealTree:prePrune ├── passport@0.3.2 -39 silly idealTree:prePrune ├── path-case@1.1.2 -39 silly idealTree:prePrune ├── path-exists@2.1.0 -39 silly idealTree:prePrune ├── path-is-absolute@1.0.0 -39 silly idealTree:prePrune ├── path-to-regexp@0.1.7 -39 silly idealTree:prePrune ├── path-type@1.1.0 -39 silly idealTree:prePrune ├── pause-stream@0.0.11 -39 silly idealTree:prePrune ├── pause@0.0.1 -39 silly idealTree:prePrune ├─┬ pdffiller@0.1.2 -39 silly idealTree:prePrune │ ├── lodash@3.8.0 -39 silly idealTree:prePrune │ ├── should-equal@0.3.1 -39 silly idealTree:prePrune │ ├── should-format@0.0.7 -39 silly idealTree:prePrune │ ├── should-type@0.0.4 -39 silly idealTree:prePrune │ └── should@6.0.1 -39 silly idealTree:prePrune ├── pend@1.2.0 -39 silly idealTree:prePrune ├─┬ phantomjs@1.9.20 -39 silly idealTree:prePrune │ ├── bl@1.0.3 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ ├── readable-stream@2.0.6 -39 silly idealTree:prePrune │ ├── request@2.67.0 -39 silly idealTree:prePrune │ └── which@1.2.4 -39 silly idealTree:prePrune ├── pify@2.3.0 -39 silly idealTree:prePrune ├── pinkie-promise@2.0.1 -39 silly idealTree:prePrune ├── pinkie@2.0.4 -39 silly idealTree:prePrune ├── pkginfo@0.3.1 -39 silly idealTree:prePrune ├── platform@1.3.0 -39 silly idealTree:prePrune ├── plist@1.2.0 -39 silly idealTree:prePrune ├── prelude-ls@1.1.2 -39 silly idealTree:prePrune ├── prepend-http@1.0.3 -39 silly idealTree:prePrune ├── prerender-node@2.2.1 -39 silly idealTree:prePrune ├── preserve@0.2.0 -39 silly idealTree:prePrune ├── pretty-bytes@1.0.4 -39 silly idealTree:prePrune ├─┬ prettyjson@1.1.3 -39 silly idealTree:prePrune │ ├── colors@1.1.2 -39 silly idealTree:prePrune │ └── minimist@1.2.0 -39 silly idealTree:prePrune ├── private@0.1.6 -39 silly idealTree:prePrune ├── process-nextick-args@1.0.6 -39 silly idealTree:prePrune ├── progress@1.1.8 -39 silly idealTree:prePrune ├── promise@6.1.0 -39 silly idealTree:prePrune ├── prompt@0.2.14 -39 silly idealTree:prePrune ├── proxy-addr@1.0.10 -39 silly idealTree:prePrune ├── ps-tree@0.0.3 -39 silly idealTree:prePrune ├── pseudomap@1.0.2 -39 silly idealTree:prePrune ├─┬ pump@1.0.1 -39 silly idealTree:prePrune │ └── end-of-stream@1.1.0 -39 silly idealTree:prePrune ├── pumpify@1.3.4 -39 silly idealTree:prePrune ├── qs@5.2.0 -39 silly idealTree:prePrune ├── rand-token@0.2.1 -39 silly idealTree:prePrune ├── randomatic@1.1.5 -39 silly idealTree:prePrune ├── range-parser@1.0.3 -39 silly idealTree:prePrune ├─┬ raven@0.9.0 -39 silly idealTree:prePrune │ ├── cookie@0.1.0 -39 silly idealTree:prePrune │ └── stack-trace@0.0.7 -39 silly idealTree:prePrune ├─┬ raw-body@2.1.6 -39 silly idealTree:prePrune │ └── bytes@2.3.0 -39 silly idealTree:prePrune ├─┬ rc@1.1.6 -39 silly idealTree:prePrune │ ├── minimist@1.2.0 -39 silly idealTree:prePrune │ └── strip-json-comments@1.0.4 -39 silly idealTree:prePrune ├─┬ read-all-stream@3.1.0 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ └── readable-stream@2.1.0 -39 silly idealTree:prePrune ├── read-pkg-up@1.0.1 -39 silly idealTree:prePrune ├── read-pkg@1.1.0 -39 silly idealTree:prePrune ├── read@1.0.7 -39 silly idealTree:prePrune ├── readable-stream@1.0.31 -39 silly idealTree:prePrune ├─┬ readdirp@2.0.0 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ ├── minimatch@2.0.10 -39 silly idealTree:prePrune │ └── readable-stream@2.1.0 -39 silly idealTree:prePrune ├── recast@0.11.5 -39 silly idealTree:prePrune ├── redent@1.0.0 -39 silly idealTree:prePrune ├── redis-commands@1.2.0 -39 silly idealTree:prePrune ├── redis-parser@1.3.0 -39 silly idealTree:prePrune ├── redis@2.5.3 -39 silly idealTree:prePrune ├── reduce-component@1.0.1 -39 silly idealTree:prePrune ├── regex-cache@0.4.3 -39 silly idealTree:prePrune ├── regexp-clone@0.0.1 -39 silly idealTree:prePrune ├── registry-url@3.1.0 -39 silly idealTree:prePrune ├── relateurl@0.2.6 -39 silly idealTree:prePrune ├── repeat-element@1.1.2 -39 silly idealTree:prePrune ├── repeat-string@1.5.4 -39 silly idealTree:prePrune ├── repeating@2.0.1 -39 silly idealTree:prePrune ├── request-progress@2.0.1 -39 silly idealTree:prePrune ├─┬ request@2.72.0 -39 silly idealTree:prePrune │ └── qs@6.1.0 -39 silly idealTree:prePrune ├── requires-port@1.0.0 -39 silly idealTree:prePrune ├── resolve@0.3.1 -39 silly idealTree:prePrune ├── resumer@0.0.0 -39 silly idealTree:prePrune ├── revalidator@0.1.8 -39 silly idealTree:prePrune ├── right-align@0.1.3 -39 silly idealTree:prePrune ├── rimraf@2.5.2 -39 silly idealTree:prePrune ├── sax@1.2.1 -39 silly idealTree:prePrune ├── selectn@0.9.6 -39 silly idealTree:prePrune ├── semver-diff@2.1.0 -39 silly idealTree:prePrune ├── semver@5.1.0 -39 silly idealTree:prePrune ├── send@0.13.1 -39 silly idealTree:prePrune ├── sentence-case@1.1.3 -39 silly idealTree:prePrune ├── serve-favicon@2.3.0 -39 silly idealTree:prePrune ├── serve-static@1.10.2 -39 silly idealTree:prePrune ├── shelljs@0.3.0 -39 silly idealTree:prePrune ├── should-equal@0.5.0 -39 silly idealTree:prePrune ├── should-format@0.3.1 -39 silly idealTree:prePrune ├── should-type@0.2.0 -39 silly idealTree:prePrune ├── should@7.1.1 -39 silly idealTree:prePrune ├── shush@1.0.0 -39 silly idealTree:prePrune ├── sigmund@1.0.1 -39 silly idealTree:prePrune ├── signal-exit@2.1.2 -39 silly idealTree:prePrune ├── simple-fmt@0.1.0 -39 silly idealTree:prePrune ├── simple-is@0.2.0 -39 silly idealTree:prePrune ├── sliced@0.0.5 -39 silly idealTree:prePrune ├── slide@1.1.6 -39 silly idealTree:prePrune ├── smtp-connection@1.3.8 -39 silly idealTree:prePrune ├── snake-case@1.1.2 -39 silly idealTree:prePrune ├── sntp@1.0.9 -39 silly idealTree:prePrune ├─┬ soap@0.11.4 -39 silly idealTree:prePrune │ ├── debug@0.7.4 -39 silly idealTree:prePrune │ ├── first-chunk-stream@0.1.0 -39 silly idealTree:prePrune │ └── strip-bom@0.3.1 -39 silly idealTree:prePrune ├─┬ socket.io-adapter@0.4.0 -39 silly idealTree:prePrune │ └─┬ socket.io-parser@2.2.2 -39 silly idealTree:prePrune │ └── debug@0.7.4 -39 silly idealTree:prePrune ├─┬ socket.io-client@1.4.5 -39 silly idealTree:prePrune │ └── component-emitter@1.2.0 -39 silly idealTree:prePrune ├─┬ socket.io-parser@2.2.6 -39 silly idealTree:prePrune │ └── json3@3.3.2 -39 silly idealTree:prePrune ├── socket.io@1.4.5 -39 silly idealTree:prePrune ├── source-map@0.5.3 -39 silly idealTree:prePrune ├── spdx-correct@1.0.2 -39 silly idealTree:prePrune ├── spdx-exceptions@1.0.4 -39 silly idealTree:prePrune ├── spdx-expression-parse@1.0.2 -39 silly idealTree:prePrune ├── spdx-license-ids@1.2.1 -39 silly idealTree:prePrune ├─┬ split2@1.1.1 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ ├── readable-stream@2.0.6 -39 silly idealTree:prePrune │ └── through2@2.0.1 -39 silly idealTree:prePrune ├── split@0.3.3 -39 silly idealTree:prePrune ├── sprintf-js@1.0.3 -39 silly idealTree:prePrune ├── sshpk@1.7.4 -39 silly idealTree:prePrune ├── stable@0.1.5 -39 silly idealTree:prePrune ├── stack-trace@0.0.9 -39 silly idealTree:prePrune ├── statuses@1.2.1 -39 silly idealTree:prePrune ├── stream-combiner@0.0.4 -39 silly idealTree:prePrune ├── streamsearch@0.1.2 -39 silly idealTree:prePrune ├── string-length@1.0.1 -39 silly idealTree:prePrune ├── string_decoder@0.10.31 -39 silly idealTree:prePrune ├── stringmap@0.2.2 -39 silly idealTree:prePrune ├── stringset@0.2.1 -39 silly idealTree:prePrune ├── stringstream@0.0.5 -39 silly idealTree:prePrune ├── strip-ansi@3.0.1 -39 silly idealTree:prePrune ├── strip-bom@2.0.0 -39 silly idealTree:prePrune ├── strip-indent@1.0.1 -39 silly idealTree:prePrune ├── strip-json-comments@0.1.3 -39 silly idealTree:prePrune ├── strong-data-uri@1.0.3 -39 silly idealTree:prePrune ├─┬ superagent@1.8.3 -39 silly idealTree:prePrune │ ├── component-emitter@1.2.1 -39 silly idealTree:prePrune │ ├── form-data@1.0.0-rc3 -39 silly idealTree:prePrune │ ├── qs@2.3.3 -39 silly idealTree:prePrune │ └── readable-stream@1.0.27-1 -39 silly idealTree:prePrune ├─┬ supertest-session@2.0.1 -39 silly idealTree:prePrune │ └── object-assign@4.0.1 -39 silly idealTree:prePrune ├── supertest@1.2.0 -39 silly idealTree:prePrune ├── supports-color@2.0.0 -39 silly idealTree:prePrune ├── swap-case@1.1.2 -39 silly idealTree:prePrune ├─┬ swig@1.4.2 -39 silly idealTree:prePrune │ ├── async@0.2.10 -39 silly idealTree:prePrune │ ├── camelcase@1.2.1 -39 silly idealTree:prePrune │ ├── source-map@0.1.34 -39 silly idealTree:prePrune │ ├── uglify-js@2.4.24 -39 silly idealTree:prePrune │ ├── wordwrap@0.0.2 -39 silly idealTree:prePrune │ └── yargs@3.5.4 -39 silly idealTree:prePrune ├─┬ tape@2.3.3 -39 silly idealTree:prePrune │ └── deep-equal@0.1.2 -39 silly idealTree:prePrune ├─┬ tar-pack@3.1.3 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ └── readable-stream@2.0.6 -39 silly idealTree:prePrune ├── tar@2.2.1 -39 silly idealTree:prePrune ├── throttleit@1.0.0 -39 silly idealTree:prePrune ├─┬ through2-filter@2.0.0 -39 silly idealTree:prePrune │ ├── isarray@1.0.0 -39 silly idealTree:prePrune │ ├── readable-stream@2.0.6 -39 silly idealTree:prePrune │ └── through2@2.0.1 -39 silly idealTree:prePrune ├─┬ through2@0.6.5 -39 silly idealTree:prePrune │ └── readable-stream@1.0.34 -39 silly idealTree:prePrune ├── through@2.3.8 -39 silly idealTree:prePrune ├── timed-out@2.0.0 -39 silly idealTree:prePrune ├── timespan@2.3.0 -39 silly idealTree:prePrune ├─┬ tiny-lr-fork@0.0.5 -39 silly idealTree:prePrune │ ├── debug@0.7.4 -39 silly idealTree:prePrune │ └── qs@0.5.6 -39 silly idealTree:prePrune ├── title-case@1.1.2 -39 silly idealTree:prePrune ├── to-array@0.1.4 -39 silly idealTree:prePrune ├── touch@1.0.0 -39 silly idealTree:prePrune ├── tough-cookie@2.2.2 -39 silly idealTree:prePrune ├─┬ transformers@2.1.0 -39 silly idealTree:prePrune │ ├── is-promise@1.0.1 -39 silly idealTree:prePrune │ ├── optimist@0.3.7 -39 silly idealTree:prePrune │ ├── promise@2.0.0 -39 silly idealTree:prePrune │ ├── source-map@0.1.43 -39 silly idealTree:prePrune │ └── uglify-js@2.2.5 -39 silly idealTree:prePrune ├── trim-newlines@1.0.0 -39 silly idealTree:prePrune ├── truncate@1.0.5 -39 silly idealTree:prePrune ├── tryor@0.1.2 -39 silly idealTree:prePrune ├── tunnel-agent@0.4.2 -39 silly idealTree:prePrune ├── tweetnacl@0.14.3 -39 silly idealTree:prePrune ├── type-check@0.3.2 -39 silly idealTree:prePrune ├── type-is@1.6.12 -39 silly idealTree:prePrune ├── typedarray@0.0.6 -39 silly idealTree:prePrune ├─┬ uglify-js@2.6.2 -39 silly idealTree:prePrune │ └── async@0.2.10 -39 silly idealTree:prePrune ├── uglify-to-browserify@1.0.2 -39 silly idealTree:prePrune ├── uid-number@0.0.6 -39 silly idealTree:prePrune ├── uid-safe@2.0.0 -39 silly idealTree:prePrune ├── uid2@0.0.3 -39 silly idealTree:prePrune ├── uid@0.0.2 -39 silly idealTree:prePrune ├── ultron@1.0.2 -39 silly idealTree:prePrune ├── undefsafe@0.0.3 -39 silly idealTree:prePrune ├── underscore.string@2.2.1 -39 silly idealTree:prePrune ├── underscore@1.7.0 -39 silly idealTree:prePrune ├── unique-stream@2.2.1 -39 silly idealTree:prePrune ├── unpipe@1.0.0 -39 silly idealTree:prePrune ├── unreachable-branch-transform@0.5.1 -39 silly idealTree:prePrune ├── untildify@2.1.0 -39 silly idealTree:prePrune ├─┬ update-notifier@0.5.0 -39 silly idealTree:prePrune │ └── repeating@1.1.3 -39 silly idealTree:prePrune ├── upper-case-first@1.1.2 -39 silly idealTree:prePrune ├── upper-case@1.1.3 -39 silly idealTree:prePrune ├── uri-path@1.0.0 -39 silly idealTree:prePrune ├── useragent@2.1.9 -39 silly idealTree:prePrune ├── utf8@2.1.0 -39 silly idealTree:prePrune ├── util-deprecate@1.0.2 -39 silly idealTree:prePrune ├─┬ utile@0.2.1 -39 silly idealTree:prePrune │ └── async@0.2.10 -39 silly idealTree:prePrune ├── utils-merge@1.0.0 -39 silly idealTree:prePrune ├── uuid@2.0.2 -39 silly idealTree:prePrune ├─┬ v8-debug@0.7.1 -39 silly idealTree:prePrune │ └── nan@2.2.1 -39 silly idealTree:prePrune ├─┬ v8-profiler@5.6.0 -39 silly idealTree:prePrune │ └── nan@2.0.9 -39 silly idealTree:prePrune ├── validate-npm-package-license@3.0.1 -39 silly idealTree:prePrune ├── vary@1.1.0 -39 silly idealTree:prePrune ├── verror@1.3.6 -39 silly idealTree:prePrune ├─┬ vinyl-fs@1.0.0 -39 silly idealTree:prePrune │ ├── graceful-fs@3.0.8 -39 silly idealTree:prePrune │ ├── object-assign@2.1.1 -39 silly idealTree:prePrune │ └── strip-bom@1.0.0 -39 silly idealTree:prePrune ├─┬ vinyl@0.4.6 -39 silly idealTree:prePrune │ └── clone@0.2.0 -39 silly idealTree:prePrune ├── void-elements@2.0.1 -39 silly idealTree:prePrune ├── which@1.0.9 -39 silly idealTree:prePrune ├─┬ win-detect-browsers@1.0.2 -39 silly idealTree:prePrune │ └── yargs@1.3.3 -39 silly idealTree:prePrune ├── window-size@0.1.0 -39 silly idealTree:prePrune ├─┬ winston@0.8.3 -39 silly idealTree:prePrune │ └── async@0.2.10 -39 silly idealTree:prePrune ├── with@4.0.3 -39 silly idealTree:prePrune ├── wordwrap@0.0.3 -39 silly idealTree:prePrune ├── wrappy@1.0.1 -39 silly idealTree:prePrune ├── write-file-atomic@1.1.4 -39 silly idealTree:prePrune ├── ws@1.1.0 -39 silly idealTree:prePrune ├── x-default-browser@0.3.1 -39 silly idealTree:prePrune ├── x-xss-protection@0.2.0 -39 silly idealTree:prePrune ├── xdg-basedir@2.0.0 -39 silly idealTree:prePrune ├─┬ xmlbuilder@4.0.0 -39 silly idealTree:prePrune │ └── lodash@3.10.1 -39 silly idealTree:prePrune ├── xmldom@0.1.22 -39 silly idealTree:prePrune ├── xmlhttprequest-ssl@1.5.1 -39 silly idealTree:prePrune ├── xtend@4.0.1 -39 silly idealTree:prePrune ├── xtraverse@0.1.0 -39 silly idealTree:prePrune ├── yallist@2.0.0 -39 silly idealTree:prePrune ├─┬ yargs@3.10.0 -39 silly idealTree:prePrune │ └── camelcase@1.2.1 -39 silly idealTree:prePrune ├── yauzl@2.4.1 -39 silly idealTree:prePrune └── yeast@0.1.2 -40 silly loadIdealTree Finishing -41 silly currentTree TellForm@1.2.1 -41 silly currentTree ├── MD5@1.3.0 -41 silly currentTree ├── abbrev@1.0.7 -41 silly currentTree ├── accepts@1.3.2 -41 silly currentTree ├─┬ acorn-globals@1.0.9 -41 silly currentTree │ └── acorn@2.7.0 -41 silly currentTree ├── acorn@1.2.2 -41 silly currentTree ├── addressparser@0.3.2 -41 silly currentTree ├── after@0.8.1 -41 silly currentTree ├── align-text@0.1.4 -41 silly currentTree ├── alter@0.2.0 -41 silly currentTree ├── amdefine@1.0.0 -41 silly currentTree ├── ansi-regex@2.0.0 -41 silly currentTree ├── ansi-styles@2.2.1 -41 silly currentTree ├── ansi@0.3.1 -41 silly currentTree ├── anymatch@1.3.0 -41 silly currentTree ├── append-field@0.1.0 -41 silly currentTree ├─┬ are-we-there-yet@1.1.2 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ └── readable-stream@2.1.0 -41 silly currentTree ├─┬ argparse@0.1.16 -41 silly currentTree │ └── underscore.string@2.4.0 -41 silly currentTree ├── arr-diff@2.0.0 -41 silly currentTree ├── arr-flatten@1.0.1 -41 silly currentTree ├── array-differ@1.0.0 -41 silly currentTree ├── array-find-index@1.0.1 -41 silly currentTree ├── array-flatten@1.1.1 -41 silly currentTree ├── array-slice@0.2.3 -41 silly currentTree ├── array-union@1.0.1 -41 silly currentTree ├── array-uniq@1.0.2 -41 silly currentTree ├── array-unique@0.2.1 -41 silly currentTree ├── arraybuffer.slice@0.0.6 -41 silly currentTree ├── arrify@1.0.1 -41 silly currentTree ├── asap@1.0.0 -41 silly currentTree ├── asn1@0.2.3 -41 silly currentTree ├── assert-plus@0.2.0 -41 silly currentTree ├── ast-types@0.8.16 -41 silly currentTree ├── async-each@1.0.0 -41 silly currentTree ├── async@1.5.2 -41 silly currentTree ├── aws-sign2@0.6.0 -41 silly currentTree ├─┬ aws4@1.3.2 -41 silly currentTree │ └── lru-cache@4.0.1 -41 silly currentTree ├── backo2@1.0.2 -41 silly currentTree ├── balanced-match@0.3.0 -41 silly currentTree ├── base64-arraybuffer@0.1.2 -41 silly currentTree ├── base64-js@0.0.8 -41 silly currentTree ├── base64-url@1.2.1 -41 silly currentTree ├── base64id@0.1.0 -41 silly currentTree ├── basic-auth@1.0.3 -41 silly currentTree ├── batch@0.5.3 -41 silly currentTree ├─┬ bcrypt@0.8.6 -41 silly currentTree │ └── nan@2.2.1 -41 silly currentTree ├── benchmark@1.0.0 -41 silly currentTree ├── better-assert@1.0.2 -41 silly currentTree ├─┬ biased-opener@0.2.8 -41 silly currentTree │ └── minimist@1.2.0 -41 silly currentTree ├── big-integer@1.6.15 -41 silly currentTree ├── binary-extensions@1.4.0 -41 silly currentTree ├── bindings@1.2.1 -41 silly currentTree ├─┬ bl@1.1.2 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ └── readable-stream@2.0.6 -41 silly currentTree ├── blob@0.0.4 -41 silly currentTree ├── block-stream@0.0.8 -41 silly currentTree ├── bluebird@2.10.2 -41 silly currentTree ├── body-parser@1.14.2 -41 silly currentTree ├── boom@2.10.1 -41 silly currentTree ├─┬ bower@1.6.9 -41 silly currentTree │ ├── abbrev@1.0.7 -41 silly currentTree │ ├── archy@1.0.0 -41 silly currentTree │ ├─┬ bower-config@1.2.3 -41 silly currentTree │ │ ├── graceful-fs@4.1.2 -41 silly currentTree │ │ ├─┬ optimist@0.6.1 -41 silly currentTree │ │ │ ├── minimist@0.0.10 -41 silly currentTree │ │ │ └── wordwrap@0.0.3 -41 silly currentTree │ │ └─┬ osenv@0.1.3 -41 silly currentTree │ │ ├── os-homedir@1.0.1 -41 silly currentTree │ │ └── os-tmpdir@1.0.1 -41 silly currentTree │ ├── bower-endpoint-parser@0.2.2 -41 silly currentTree │ ├─┬ bower-json@0.4.0 -41 silly currentTree │ │ ├── deep-extend@0.2.11 -41 silly currentTree │ │ ├── graceful-fs@2.0.3 -41 silly currentTree │ │ └── intersect@0.0.3 -41 silly currentTree │ ├── bower-logger@0.2.2 -41 silly currentTree │ ├─┬ bower-registry-client@1.0.0 -41 silly currentTree │ │ ├── async@0.2.10 -41 silly currentTree │ │ ├── graceful-fs@4.1.2 -41 silly currentTree │ │ ├── mkdirp@0.3.5 -41 silly currentTree │ │ └── request-replay@0.2.0 -41 silly currentTree │ ├─┬ cardinal@0.4.4 -41 silly currentTree │ │ ├── ansicolors@0.2.1 -41 silly currentTree │ │ └─┬ redeyed@0.4.4 -41 silly currentTree │ │ └── esprima@1.0.4 -41 silly currentTree │ ├─┬ chalk@1.1.1 -41 silly currentTree │ │ ├── ansi-styles@2.1.0 -41 silly currentTree │ │ ├── escape-string-regexp@1.0.3 -41 silly currentTree │ │ ├─┬ has-ansi@2.0.0 -41 silly currentTree │ │ │ └── ansi-regex@2.0.0 -41 silly currentTree │ │ ├─┬ strip-ansi@3.0.0 -41 silly currentTree │ │ │ └── ansi-regex@2.0.0 -41 silly currentTree │ │ └── supports-color@2.0.0 -41 silly currentTree │ ├── chmodr@1.0.2 -41 silly currentTree │ ├─┬ configstore@0.3.2 -41 silly currentTree │ │ ├─┬ js-yaml@3.4.6 -41 silly currentTree │ │ │ ├─┬ argparse@1.0.3 -41 silly currentTree │ │ │ │ ├── lodash@3.10.1 -41 silly currentTree │ │ │ │ └── sprintf-js@1.0.3 -41 silly currentTree │ │ │ ├── esprima@2.7.0 -41 silly currentTree │ │ │ └── inherit@2.2.2 -41 silly currentTree │ │ ├── object-assign@2.1.1 -41 silly currentTree │ │ ├─┬ osenv@0.1.3 -41 silly currentTree │ │ │ ├── os-homedir@1.0.1 -41 silly currentTree │ │ │ └── os-tmpdir@1.0.1 -41 silly currentTree │ │ ├── uuid@2.0.1 -41 silly currentTree │ │ └── xdg-basedir@1.0.1 -41 silly currentTree │ ├─┬ decompress-zip@0.1.0 -41 silly currentTree │ │ ├─┬ binary@0.3.0 -41 silly currentTree │ │ │ ├── buffers@0.1.1 -41 silly currentTree │ │ │ └─┬ chainsaw@0.1.0 -41 silly currentTree │ │ │ └── traverse@0.3.9 -41 silly currentTree │ │ ├── mkpath@0.1.0 -41 silly currentTree │ │ ├─┬ readable-stream@1.1.13 -41 silly currentTree │ │ │ ├── core-util-is@1.0.2 -41 silly currentTree │ │ │ ├── inherits@2.0.1 -41 silly currentTree │ │ │ ├── isarray@0.0.1 -41 silly currentTree │ │ │ └── string_decoder@0.10.31 -41 silly currentTree │ │ └─┬ touch@0.0.3 -41 silly currentTree │ │ └── nopt@1.0.10 -41 silly currentTree │ ├── destroy@1.0.3 -41 silly currentTree │ ├─┬ fs-write-stream-atomic@1.0.5 -41 silly currentTree │ │ ├── graceful-fs@4.1.2 -41 silly currentTree │ │ └── imurmurhash@0.1.4 -41 silly currentTree │ ├─┬ fstream-ignore@1.0.3 -41 silly currentTree │ │ ├── inherits@2.0.1 -41 silly currentTree │ │ └─┬ minimatch@3.0.0 -41 silly currentTree │ │ └─┬ brace-expansion@1.1.2 -41 silly currentTree │ │ ├── balanced-match@0.3.0 -41 silly currentTree │ │ └── concat-map@0.0.1 -41 silly currentTree │ ├─┬ fstream@1.0.8 -41 silly currentTree │ │ ├── graceful-fs@4.1.2 -41 silly currentTree │ │ └── inherits@2.0.1 -41 silly currentTree │ ├─┬ github@0.2.4 -41 silly currentTree │ │ └── mime@1.3.4 -41 silly currentTree │ ├─┬ glob@4.5.3 -41 silly currentTree │ │ ├─┬ inflight@1.0.4 -41 silly currentTree │ │ │ └── wrappy@1.0.1 -41 silly currentTree │ │ ├── inherits@2.0.1 -41 silly currentTree │ │ ├─┬ minimatch@2.0.10 -41 silly currentTree │ │ │ └─┬ brace-expansion@1.1.2 -41 silly currentTree │ │ │ ├── balanced-match@0.3.0 -41 silly currentTree │ │ │ └── concat-map@0.0.1 -41 silly currentTree │ │ └─┬ once@1.3.3 -41 silly currentTree │ │ └── wrappy@1.0.1 -41 silly currentTree │ ├── graceful-fs@3.0.8 -41 silly currentTree │ ├─┬ handlebars@2.0.0 -41 silly currentTree │ │ ├─┬ optimist@0.3.7 -41 silly currentTree │ │ │ └── wordwrap@0.0.3 -41 silly currentTree │ │ └─┬ uglify-js@2.3.6 -41 silly currentTree │ │ ├── async@0.2.10 -41 silly currentTree │ │ └─┬ source-map@0.1.43 -41 silly currentTree │ │ └── amdefine@1.0.0 -41 silly currentTree │ ├─┬ inquirer@0.10.0 -41 silly currentTree │ │ ├── ansi-escapes@1.1.0 -41 silly currentTree │ │ ├── ansi-regex@2.0.0 -41 silly currentTree │ │ ├─┬ cli-cursor@1.0.2 -41 silly currentTree │ │ │ └─┬ restore-cursor@1.0.1 -41 silly currentTree │ │ │ ├── exit-hook@1.1.1 -41 silly currentTree │ │ │ └── onetime@1.0.0 -41 silly currentTree │ │ ├── cli-width@1.1.0 -41 silly currentTree │ │ ├── figures@1.4.0 -41 silly currentTree │ │ ├── lodash@3.10.1 -41 silly currentTree │ │ ├─┬ readline2@1.0.1 -41 silly currentTree │ │ │ ├─┬ code-point-at@1.0.0 -41 silly currentTree │ │ │ │ └── number-is-nan@1.0.0 -41 silly currentTree │ │ │ ├─┬ is-fullwidth-code-point@1.0.0 -41 silly currentTree │ │ │ │ └── number-is-nan@1.0.0 -41 silly currentTree │ │ │ └── mute-stream@0.0.5 -41 silly currentTree │ │ ├─┬ run-async@0.1.0 -41 silly currentTree │ │ │ └─┬ once@1.3.3 -41 silly currentTree │ │ │ └── wrappy@1.0.1 -41 silly currentTree │ │ ├── rx-lite@3.1.2 -41 silly currentTree │ │ ├── strip-ansi@3.0.0 -41 silly currentTree │ │ └── through@2.3.8 -41 silly currentTree │ ├─┬ insight@0.7.0 -41 silly currentTree │ │ ├── async@1.5.0 -41 silly currentTree │ │ ├─┬ configstore@1.3.0 -41 silly currentTree │ │ │ ├── graceful-fs@4.1.2 -41 silly currentTree │ │ │ ├── os-tmpdir@1.0.1 -41 silly currentTree │ │ │ ├─┬ osenv@0.1.3 -41 silly currentTree │ │ │ │ └── os-homedir@1.0.1 -41 silly currentTree │ │ │ ├── uuid@2.0.1 -41 silly currentTree │ │ │ ├─┬ write-file-atomic@1.1.4 -41 silly currentTree │ │ │ │ ├── imurmurhash@0.1.4 -41 silly currentTree │ │ │ │ └── slide@1.1.6 -41 silly currentTree │ │ │ └─┬ xdg-basedir@2.0.0 -41 silly currentTree │ │ │ └── os-homedir@1.0.1 -41 silly currentTree │ │ ├─┬ lodash.debounce@3.1.1 -41 silly currentTree │ │ │ └── lodash._getnative@3.9.1 -41 silly currentTree │ │ ├── object-assign@4.0.1 -41 silly currentTree │ │ ├─┬ os-name@1.0.3 -41 silly currentTree │ │ │ ├─┬ osx-release@1.1.0 -41 silly currentTree │ │ │ │ └── minimist@1.2.0 -41 silly currentTree │ │ │ └─┬ win-release@1.1.1 -41 silly currentTree │ │ │ └── semver@5.1.0 -41 silly currentTree │ │ └── tough-cookie@2.2.1 -41 silly currentTree │ ├── is-root@1.0.0 -41 silly currentTree │ ├── junk@1.0.2 -41 silly currentTree │ ├── lockfile@1.0.1 -41 silly currentTree │ ├── lru-cache@2.7.3 -41 silly currentTree │ ├─┬ md5-hex@1.1.0 -41 silly currentTree │ │ └── md5-o-matic@0.1.1 -41 silly currentTree │ ├─┬ mkdirp@0.5.0 -41 silly currentTree │ │ └── minimist@0.0.8 -41 silly currentTree │ ├── mout@0.11.1 -41 silly currentTree │ ├── nopt@3.0.6 -41 silly currentTree │ ├── opn@1.0.2 -41 silly currentTree │ ├─┬ p-throttler@0.1.1 -41 silly currentTree │ │ └── q@0.9.7 -41 silly currentTree │ ├─┬ promptly@0.2.0 -41 silly currentTree │ │ └─┬ read@1.0.7 -41 silly currentTree │ │ └── mute-stream@0.0.5 -41 silly currentTree │ ├── q@1.4.1 -41 silly currentTree │ ├─┬ request-progress@0.3.1 -41 silly currentTree │ │ └── throttleit@0.0.2 -41 silly currentTree │ ├─┬ request@2.53.0 -41 silly currentTree │ │ ├── aws-sign2@0.5.0 -41 silly currentTree │ │ ├─┬ bl@0.9.4 -41 silly currentTree │ │ │ └─┬ readable-stream@1.0.33 -41 silly currentTree │ │ │ ├── core-util-is@1.0.2 -41 silly currentTree │ │ │ ├── inherits@2.0.1 -41 silly currentTree │ │ │ ├── isarray@0.0.1 -41 silly currentTree │ │ │ └── string_decoder@0.10.31 -41 silly currentTree │ │ ├── caseless@0.9.0 -41 silly currentTree │ │ ├─┬ combined-stream@0.0.7 -41 silly currentTree │ │ │ └── delayed-stream@0.0.5 -41 silly currentTree │ │ ├── forever-agent@0.5.2 -41 silly currentTree │ │ ├─┬ form-data@0.2.0 -41 silly currentTree │ │ │ └── async@0.9.2 -41 silly currentTree │ │ ├─┬ hawk@2.3.1 -41 silly currentTree │ │ │ ├── boom@2.10.1 -41 silly currentTree │ │ │ ├── cryptiles@2.0.5 -41 silly currentTree │ │ │ ├── hoek@2.16.3 -41 silly currentTree │ │ │ └── sntp@1.0.9 -41 silly currentTree │ │ ├─┬ http-signature@0.10.1 -41 silly currentTree │ │ │ ├── asn1@0.1.11 -41 silly currentTree │ │ │ ├── assert-plus@0.1.5 -41 silly currentTree │ │ │ └── ctype@0.5.3 -41 silly currentTree │ │ ├── isstream@0.1.2 -41 silly currentTree │ │ ├── json-stringify-safe@5.0.1 -41 silly currentTree │ │ ├─┬ mime-types@2.0.14 -41 silly currentTree │ │ │ └── mime-db@1.12.0 -41 silly currentTree │ │ ├── node-uuid@1.4.7 -41 silly currentTree │ │ ├── oauth-sign@0.6.0 -41 silly currentTree │ │ ├── qs@2.3.3 -41 silly currentTree │ │ ├── stringstream@0.0.5 -41 silly currentTree │ │ ├── tough-cookie@2.2.1 -41 silly currentTree │ │ └── tunnel-agent@0.4.1 -41 silly currentTree │ ├── retry@0.6.1 -41 silly currentTree │ ├─┬ rimraf@2.4.4 -41 silly currentTree │ │ └─┬ glob@5.0.15 -41 silly currentTree │ │ ├─┬ inflight@1.0.4 -41 silly currentTree │ │ │ └── wrappy@1.0.1 -41 silly currentTree │ │ ├── inherits@2.0.1 -41 silly currentTree │ │ ├─┬ minimatch@3.0.0 -41 silly currentTree │ │ │ └─┬ brace-expansion@1.1.2 -41 silly currentTree │ │ │ ├── balanced-match@0.3.0 -41 silly currentTree │ │ │ └── concat-map@0.0.1 -41 silly currentTree │ │ ├─┬ once@1.3.3 -41 silly currentTree │ │ │ └── wrappy@1.0.1 -41 silly currentTree │ │ └── path-is-absolute@1.0.0 -41 silly currentTree │ ├── semver@2.3.2 -41 silly currentTree │ ├─┬ shell-quote@1.4.3 -41 silly currentTree │ │ ├── array-filter@0.0.1 -41 silly currentTree │ │ ├── array-map@0.0.0 -41 silly currentTree │ │ ├── array-reduce@0.0.0 -41 silly currentTree │ │ └── jsonify@0.0.0 -41 silly currentTree │ ├── stringify-object@1.0.1 -41 silly currentTree │ ├─┬ tar-fs@1.8.1 -41 silly currentTree │ │ ├─┬ pump@1.0.1 -41 silly currentTree │ │ │ ├── end-of-stream@1.1.0 -41 silly currentTree │ │ │ └─┬ once@1.3.3 -41 silly currentTree │ │ │ └── wrappy@1.0.1 -41 silly currentTree │ │ └─┬ tar-stream@1.3.1 -41 silly currentTree │ │ ├── bl@1.0.0 -41 silly currentTree │ │ ├─┬ end-of-stream@1.1.0 -41 silly currentTree │ │ │ └─┬ once@1.3.3 -41 silly currentTree │ │ │ └── wrappy@1.0.1 -41 silly currentTree │ │ ├─┬ readable-stream@2.0.4 -41 silly currentTree │ │ │ ├── core-util-is@1.0.2 -41 silly currentTree │ │ │ ├── inherits@2.0.1 -41 silly currentTree │ │ │ ├── isarray@0.0.1 -41 silly currentTree │ │ │ ├── process-nextick-args@1.0.6 -41 silly currentTree │ │ │ ├── string_decoder@0.10.31 -41 silly currentTree │ │ │ └── util-deprecate@1.0.2 -41 silly currentTree │ │ └── xtend@4.0.1 -41 silly currentTree │ ├── tmp@0.0.24 -41 silly currentTree │ ├─┬ update-notifier@0.3.2 -41 silly currentTree │ │ ├── is-npm@1.0.0 -41 silly currentTree │ │ ├─┬ latest-version@1.0.1 -41 silly currentTree │ │ │ └─┬ package-json@1.2.0 -41 silly currentTree │ │ │ ├─┬ got@3.3.1 -41 silly currentTree │ │ │ │ ├─┬ duplexify@3.4.2 -41 silly currentTree │ │ │ │ │ ├─┬ end-of-stream@1.0.0 -41 silly currentTree │ │ │ │ │ │ └─┬ once@1.3.3 -41 silly currentTree │ │ │ │ │ │ └── wrappy@1.0.1 -41 silly currentTree │ │ │ │ │ └─┬ readable-stream@2.0.4 -41 silly currentTree │ │ │ │ │ ├── core-util-is@1.0.2 -41 silly currentTree │ │ │ │ │ ├── inherits@2.0.1 -41 silly currentTree │ │ │ │ │ ├── isarray@0.0.1 -41 silly currentTree │ │ │ │ │ ├── process-nextick-args@1.0.6 -41 silly currentTree │ │ │ │ │ ├── string_decoder@0.10.31 -41 silly currentTree │ │ │ │ │ └── util-deprecate@1.0.2 -41 silly currentTree │ │ │ │ ├── infinity-agent@2.0.3 -41 silly currentTree │ │ │ │ ├── is-redirect@1.0.0 -41 silly currentTree │ │ │ │ ├── is-stream@1.0.1 -41 silly currentTree │ │ │ │ ├── lowercase-keys@1.0.0 -41 silly currentTree │ │ │ │ ├─┬ nested-error-stacks@1.0.2 -41 silly currentTree │ │ │ │ │ └── inherits@2.0.1 -41 silly currentTree │ │ │ │ ├── object-assign@3.0.0 -41 silly currentTree │ │ │ │ ├── prepend-http@1.0.3 -41 silly currentTree │ │ │ │ ├─┬ read-all-stream@3.0.1 -41 silly currentTree │ │ │ │ │ ├─┬ pinkie-promise@1.0.0 -41 silly currentTree │ │ │ │ │ │ └── pinkie@1.0.0 -41 silly currentTree │ │ │ │ │ └─┬ readable-stream@2.0.4 -41 silly currentTree │ │ │ │ │ ├── core-util-is@1.0.2 -41 silly currentTree │ │ │ │ │ ├── inherits@2.0.1 -41 silly currentTree │ │ │ │ │ ├── isarray@0.0.1 -41 silly currentTree │ │ │ │ │ ├── process-nextick-args@1.0.6 -41 silly currentTree │ │ │ │ │ ├── string_decoder@0.10.31 -41 silly currentTree │ │ │ │ │ └── util-deprecate@1.0.2 -41 silly currentTree │ │ │ │ └── timed-out@2.0.0 -41 silly currentTree │ │ │ └─┬ registry-url@3.0.3 -41 silly currentTree │ │ │ └─┬ rc@1.1.5 -41 silly currentTree │ │ │ ├── deep-extend@0.4.0 -41 silly currentTree │ │ │ ├── ini@1.3.4 -41 silly currentTree │ │ │ ├── minimist@1.2.0 -41 silly currentTree │ │ │ └── strip-json-comments@1.0.4 -41 silly currentTree │ │ ├─┬ semver-diff@2.1.0 -41 silly currentTree │ │ │ └── semver@5.1.0 -41 silly currentTree │ │ └─┬ string-length@1.0.1 -41 silly currentTree │ │ └─┬ strip-ansi@3.0.0 -41 silly currentTree │ │ └── ansi-regex@2.0.0 -41 silly currentTree │ ├── user-home@1.1.1 -41 silly currentTree │ └─┬ which@1.2.0 -41 silly currentTree │ └─┬ is-absolute@0.1.7 -41 silly currentTree │ └── is-relative@0.1.3 -41 silly currentTree ├── bplist-parser@0.1.1 -41 silly currentTree ├── brace-expansion@1.1.3 -41 silly currentTree ├── braces@1.8.4 -41 silly currentTree ├─┬ broadway@0.3.6 -41 silly currentTree │ ├── async@0.2.10 -41 silly currentTree │ ├── cliff@0.1.9 -41 silly currentTree │ └── winston@0.8.0 -41 silly currentTree ├─┬ browser-launcher2@0.4.6 -41 silly currentTree │ └── rimraf@2.2.8 -41 silly currentTree ├── browserify-zlib@0.1.4 -41 silly currentTree ├── bson@0.4.23 -41 silly currentTree ├─┬ buildmail@2.0.0 -41 silly currentTree │ └── needle@0.10.0 -41 silly currentTree ├── builtin-modules@1.1.1 -41 silly currentTree ├─┬ busboy@0.2.13 -41 silly currentTree │ └── readable-stream@1.1.14 -41 silly currentTree ├── bytes@2.2.0 -41 silly currentTree ├── caller@0.0.1 -41 silly currentTree ├── callsite@1.0.0 -41 silly currentTree ├── camel-case@1.2.2 -41 silly currentTree ├── camelcase-keys@2.1.0 -41 silly currentTree ├── camelcase@2.1.1 -41 silly currentTree ├── camelize@1.0.0 -41 silly currentTree ├── caseless@0.11.0 -41 silly currentTree ├── center-align@0.1.3 -41 silly currentTree ├── chalk@1.1.3 -41 silly currentTree ├── change-case@2.1.6 -41 silly currentTree ├── character-parser@1.2.1 -41 silly currentTree ├── charenc@0.0.1 -41 silly currentTree ├── chokidar@1.4.3 -41 silly currentTree ├─┬ clean-css@3.4.12 -41 silly currentTree │ └── source-map@0.4.4 -41 silly currentTree ├─┬ cli@0.6.6 -41 silly currentTree │ ├── glob@3.2.11 -41 silly currentTree │ └── minimatch@0.3.0 -41 silly currentTree ├─┬ cliff@0.1.10 -41 silly currentTree │ └── colors@1.0.3 -41 silly currentTree ├─┬ cliui@2.1.0 -41 silly currentTree │ └── wordwrap@0.0.2 -41 silly currentTree ├── clone-stats@0.0.1 -41 silly currentTree ├── clone@1.0.2 -41 silly currentTree ├── coffee-script@1.3.3 -41 silly currentTree ├── colors@0.6.2 -41 silly currentTree ├── combined-stream@1.0.5 -41 silly currentTree ├── commander@2.8.1 -41 silly currentTree ├── component-bind@1.0.0 -41 silly currentTree ├── component-emitter@1.1.2 -41 silly currentTree ├── component-inherit@0.0.3 -41 silly currentTree ├── compressible@2.0.7 -41 silly currentTree ├── compression@1.6.1 -41 silly currentTree ├── concat-map@0.0.1 -41 silly currentTree ├─┬ concat-stream@1.5.1 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ └── readable-stream@2.0.6 -41 silly currentTree ├─┬ configstore@1.4.0 -41 silly currentTree │ └── object-assign@4.0.1 -41 silly currentTree ├── connect-flash@0.1.1 -41 silly currentTree ├── connect-mongo@0.8.2 -41 silly currentTree ├─┬ connect@3.4.0 -41 silly currentTree │ ├── escape-html@1.0.2 -41 silly currentTree │ └── finalhandler@0.4.0 -41 silly currentTree ├── console-browserify@1.1.0 -41 silly currentTree ├── consolidate@0.13.1 -41 silly currentTree ├── constant-case@1.1.2 -41 silly currentTree ├─┬ constantinople@3.0.2 -41 silly currentTree │ └── acorn@2.7.0 -41 silly currentTree ├── content-disposition@0.5.1 -41 silly currentTree ├── content-security-policy-builder@0.2.0 -41 silly currentTree ├── content-type@1.0.1 -41 silly currentTree ├── convert-source-map@1.1.3 -41 silly currentTree ├── cookie-parser@1.4.1 -41 silly currentTree ├── cookie-signature@1.0.6 -41 silly currentTree ├── cookie@0.2.3 -41 silly currentTree ├── cookiejar@2.0.6 -41 silly currentTree ├── core-js@2.2.2 -41 silly currentTree ├── core-util-is@1.0.2 -41 silly currentTree ├─┬ coveralls@2.11.9 -41 silly currentTree │ ├── bl@1.0.3 -41 silly currentTree │ ├── esprima@1.0.4 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ ├── js-yaml@3.0.1 -41 silly currentTree │ ├── minimist@1.2.0 -41 silly currentTree │ ├── readable-stream@2.0.6 -41 silly currentTree │ └── request@2.67.0 -41 silly currentTree ├── crc@3.3.0 -41 silly currentTree ├── crypt@0.0.1 -41 silly currentTree ├── cryptiles@2.0.5 -41 silly currentTree ├── css-parse@1.0.4 -41 silly currentTree ├── css-stringify@1.0.5 -41 silly currentTree ├── css@1.0.8 -41 silly currentTree ├── csslint@0.10.0 -41 silly currentTree ├── ctype@0.5.3 -41 silly currentTree ├── custom-event@1.0.0 -41 silly currentTree ├── cycle@1.0.3 -41 silly currentTree ├─┬ dashdash@1.13.0 -41 silly currentTree │ └── assert-plus@1.0.0 -41 silly currentTree ├── dashify@0.1.0 -41 silly currentTree ├── date-now@0.1.4 -41 silly currentTree ├── dateformat@1.0.2-1.2.3 -41 silly currentTree ├── debug@2.2.0 -41 silly currentTree ├── decamelize@1.2.0 -41 silly currentTree ├── deep-equal@1.0.1 -41 silly currentTree ├── deep-extend@0.4.1 -41 silly currentTree ├── deep-is@0.1.3 -41 silly currentTree ├── default-browser-id@1.0.4 -41 silly currentTree ├── defined@0.0.0 -41 silly currentTree ├── delayed-stream@1.0.0 -41 silly currentTree ├── delegates@1.0.0 -41 silly currentTree ├── depd@1.1.0 -41 silly currentTree ├── destroy@1.0.4 -41 silly currentTree ├── device@0.3.6 -41 silly currentTree ├── di@0.0.1 -41 silly currentTree ├─┬ dicer@0.2.5 -41 silly currentTree │ └── readable-stream@1.1.14 -41 silly currentTree ├── diff@1.4.0 -41 silly currentTree ├── director@1.2.7 -41 silly currentTree ├── dom-serialize@2.2.1 -41 silly currentTree ├─┬ dom-serializer@0.1.0 -41 silly currentTree │ ├── domelementtype@1.1.3 -41 silly currentTree │ └── entities@1.1.1 -41 silly currentTree ├── domelementtype@1.3.0 -41 silly currentTree ├── domhandler@2.3.0 -41 silly currentTree ├── domutils@1.5.1 -41 silly currentTree ├── dont-sniff-mimetype@0.1.0 -41 silly currentTree ├── dot-case@1.1.2 -41 silly currentTree ├── double-ended-queue@2.1.0-0 -41 silly currentTree ├── duplexer@0.1.1 -41 silly currentTree ├─┬ duplexify@3.4.3 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ └── readable-stream@2.1.0 -41 silly currentTree ├── ecc-jsbn@0.1.1 -41 silly currentTree ├── ee-first@1.1.1 -41 silly currentTree ├── email-addresses@2.0.2 -41 silly currentTree ├── email-verification@0.1.9 -41 silly currentTree ├── end-of-stream@1.0.0 -41 silly currentTree ├─┬ engine.io-client@1.6.8 -41 silly currentTree │ └── ws@1.0.1 -41 silly currentTree ├─┬ engine.io-parser@1.2.4 -41 silly currentTree │ └── has-binary@0.1.6 -41 silly currentTree ├─┬ engine.io@1.6.8 -41 silly currentTree │ ├── accepts@1.1.4 -41 silly currentTree │ ├── mime-db@1.12.0 -41 silly currentTree │ ├── mime-types@2.0.14 -41 silly currentTree │ ├── negotiator@0.4.9 -41 silly currentTree │ └── ws@1.0.1 -41 silly currentTree ├── ent@2.2.0 -41 silly currentTree ├── entities@1.0.0 -41 silly currentTree ├── error-ex@1.3.0 -41 silly currentTree ├── es6-promise@2.1.1 -41 silly currentTree ├── escape-html@1.0.3 -41 silly currentTree ├── escape-string-regexp@1.0.5 -41 silly currentTree ├─┬ escodegen@1.8.0 -41 silly currentTree │ └── source-map@0.2.0 -41 silly currentTree ├── esmangle-evaluator@1.0.0 -41 silly currentTree ├── esprima@2.7.2 -41 silly currentTree ├── estraverse@1.9.3 -41 silly currentTree ├── esutils@2.0.2 -41 silly currentTree ├── etag@1.7.0 -41 silly currentTree ├─┬ event-stream@0.5.3 -41 silly currentTree │ └── optimist@0.2.8 -41 silly currentTree ├── eventemitter2@0.4.14 -41 silly currentTree ├── eventemitter3@1.2.0 -41 silly currentTree ├── exit@0.1.2 -41 silly currentTree ├─┬ expand-braces@0.1.2 -41 silly currentTree │ ├── braces@0.1.5 -41 silly currentTree │ ├── expand-range@0.1.1 -41 silly currentTree │ ├── is-number@0.1.1 -41 silly currentTree │ └── repeat-string@0.2.2 -41 silly currentTree ├── expand-brackets@0.1.5 -41 silly currentTree ├── expand-range@1.8.1 -41 silly currentTree ├── express-device@0.4.2 -41 silly currentTree ├── express-partials@0.3.0 -41 silly currentTree ├── express-session@1.12.1 -41 silly currentTree ├─┬ express@4.13.4 -41 silly currentTree │ ├── accepts@1.2.13 -41 silly currentTree │ ├── cookie@0.1.5 -41 silly currentTree │ ├── negotiator@0.5.3 -41 silly currentTree │ ├── qs@4.0.0 -41 silly currentTree │ └── vary@1.0.1 -41 silly currentTree ├── extend@3.0.0 -41 silly currentTree ├── extglob@0.3.2 -41 silly currentTree ├─┬ extract-zip@1.5.0 -41 silly currentTree │ ├── concat-stream@1.5.0 -41 silly currentTree │ ├── debug@0.7.4 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ ├── minimist@0.0.8 -41 silly currentTree │ ├── mkdirp@0.5.0 -41 silly currentTree │ └── readable-stream@2.0.6 -41 silly currentTree ├── extsprintf@1.0.2 -41 silly currentTree ├── eyes@0.1.8 -41 silly currentTree ├── falafel@1.2.0 -41 silly currentTree ├── fast-levenshtein@1.1.3 -41 silly currentTree ├── faye-websocket@0.4.4 -41 silly currentTree ├── fd-slicer@1.0.1 -41 silly currentTree ├── fdf@0.0.0 -41 silly currentTree ├── figures@1.5.0 -41 silly currentTree ├── filename-regex@2.0.0 -41 silly currentTree ├─┬ fileset@0.2.1 -41 silly currentTree │ ├── glob@5.0.15 -41 silly currentTree │ └── minimatch@2.0.10 -41 silly currentTree ├── fill-range@2.2.3 -41 silly currentTree ├── finalhandler@0.4.1 -41 silly currentTree ├── find-index@0.1.1 -41 silly currentTree ├── find-up@1.1.2 -41 silly currentTree ├─┬ findup-sync@0.1.3 -41 silly currentTree │ ├── glob@3.2.11 -41 silly currentTree │ └── minimatch@0.3.0 -41 silly currentTree ├── first-chunk-stream@1.0.0 -41 silly currentTree ├─┬ flatiron@0.4.3 -41 silly currentTree │ └── optimist@0.6.0 -41 silly currentTree ├── for-in@0.1.5 -41 silly currentTree ├── for-own@0.1.4 -41 silly currentTree ├── foreach@2.0.5 -41 silly currentTree ├── forever-agent@0.6.1 -41 silly currentTree ├─┬ forever-monitor@1.6.0 -41 silly currentTree │ └── minimatch@2.0.10 -41 silly currentTree ├── forever@0.15.1 -41 silly currentTree ├── form-data@1.0.0-rc4 -41 silly currentTree ├── formidable@1.0.17 -41 silly currentTree ├── forwarded@0.1.0 -41 silly currentTree ├── frameguard@0.2.2 -41 silly currentTree ├── fresh@0.3.0 -41 silly currentTree ├── from@0.1.3 -41 silly currentTree ├── fs-access@1.0.0 -41 silly currentTree ├── fs-extra@0.26.7 -41 silly currentTree ├── fstream-ignore@1.0.3 -41 silly currentTree ├── fstream@1.0.8 -41 silly currentTree ├── gauge@1.2.7 -41 silly currentTree ├── gaze@0.5.2 -41 silly currentTree ├── generate-function@2.0.0 -41 silly currentTree ├── generate-object-property@1.2.0 -41 silly currentTree ├── get-stdin@4.0.1 -41 silly currentTree ├── getobject@0.1.0 -41 silly currentTree ├── glob-base@0.3.0 -41 silly currentTree ├── glob-parent@2.0.0 -41 silly currentTree ├─┬ glob-stream@4.1.1 -41 silly currentTree │ ├── glob@4.5.3 -41 silly currentTree │ └── minimatch@2.0.10 -41 silly currentTree ├── glob-watcher@0.0.8 -41 silly currentTree ├── glob2base@0.0.12 -41 silly currentTree ├── glob@7.0.3 -41 silly currentTree ├─┬ globby@2.1.0 -41 silly currentTree │ └── glob@5.0.15 -41 silly currentTree ├─┬ globule@0.1.0 -41 silly currentTree │ ├── glob@3.1.21 -41 silly currentTree │ ├── graceful-fs@1.2.3 -41 silly currentTree │ ├── inherits@1.0.2 -41 silly currentTree │ ├── lodash@1.0.2 -41 silly currentTree │ └── minimatch@0.2.14 -41 silly currentTree ├── got@3.3.1 -41 silly currentTree ├── graceful-fs@4.1.3 -41 silly currentTree ├── graceful-readlink@1.0.1 -41 silly currentTree ├── growl@1.8.1 -41 silly currentTree ├── grunt-cli@0.1.13 -41 silly currentTree ├── grunt-concurrent@2.3.0 -41 silly currentTree ├─┬ grunt-contrib-csslint@0.5.0 -41 silly currentTree │ ├── lodash@3.10.1 -41 silly currentTree │ └── strip-json-comments@1.0.4 -41 silly currentTree ├── grunt-contrib-cssmin@0.14.0 -41 silly currentTree ├── grunt-contrib-jshint@0.11.3 -41 silly currentTree ├─┬ grunt-contrib-uglify@0.11.1 -41 silly currentTree │ ├── gzip-size@3.0.0 -41 silly currentTree │ ├── lodash@4.11.1 -41 silly currentTree │ ├── maxmin@2.1.0 -41 silly currentTree │ └── pretty-bytes@3.0.1 -41 silly currentTree ├─┬ grunt-contrib-watch@0.6.1 -41 silly currentTree │ └── async@0.2.10 -41 silly currentTree ├── grunt-env@0.4.4 -41 silly currentTree ├── grunt-html2js@0.3.6 -41 silly currentTree ├─┬ grunt-karma@0.12.2 -41 silly currentTree │ └── lodash@3.10.1 -41 silly currentTree ├─┬ grunt-legacy-log-utils@0.1.1 -41 silly currentTree │ └── underscore.string@2.3.3 -41 silly currentTree ├─┬ grunt-legacy-log@0.1.3 -41 silly currentTree │ └── underscore.string@2.3.3 -41 silly currentTree ├─┬ grunt-legacy-util@0.2.0 -41 silly currentTree │ ├── async@0.1.22 -41 silly currentTree │ └── lodash@0.9.2 -41 silly currentTree ├── grunt-mocha-istanbul@3.0.1 -41 silly currentTree ├── grunt-mocha-test@0.12.7 -41 silly currentTree ├─┬ grunt-newer@1.1.2 -41 silly currentTree │ ├── async@0.9.0 -41 silly currentTree │ └── rimraf@2.2.8 -41 silly currentTree ├── grunt-ng-annotate@1.0.1 -41 silly currentTree ├── grunt-node-inspector@0.4.1 -41 silly currentTree ├── grunt-nodemon@0.4.2 -41 silly currentTree ├─┬ grunt@0.4.5 -41 silly currentTree │ ├── async@0.1.22 -41 silly currentTree │ ├── glob@3.1.21 -41 silly currentTree │ ├── graceful-fs@1.2.3 -41 silly currentTree │ ├── iconv-lite@0.2.11 -41 silly currentTree │ ├── inherits@1.0.2 -41 silly currentTree │ ├── lodash@0.9.2 -41 silly currentTree │ ├── minimatch@0.2.14 -41 silly currentTree │ └── rimraf@2.2.8 -41 silly currentTree ├── gzip-size@1.0.0 -41 silly currentTree ├─┬ handlebars@4.0.5 -41 silly currentTree │ └── source-map@0.4.4 -41 silly currentTree ├─┬ har-validator@2.0.6 -41 silly currentTree │ └── commander@2.9.0 -41 silly currentTree ├── has-ansi@2.0.0 -41 silly currentTree ├── has-binary@0.1.7 -41 silly currentTree ├── has-cors@1.1.0 -41 silly currentTree ├── has-flag@1.0.0 -41 silly currentTree ├── has-unicode@2.0.0 -41 silly currentTree ├── hasha@2.2.0 -41 silly currentTree ├── hawk@3.1.3 -41 silly currentTree ├── headless@0.1.7 -41 silly currentTree ├── helmet-crossdomain@0.1.0 -41 silly currentTree ├── helmet-csp@0.3.0 -41 silly currentTree ├── helmet@0.14.0 -41 silly currentTree ├── hide-powered-by@0.1.0 -41 silly currentTree ├── hoek@2.16.3 -41 silly currentTree ├── hooker@0.2.3 -41 silly currentTree ├── hooks@0.2.1 -41 silly currentTree ├── hosted-git-info@2.1.4 -41 silly currentTree ├── hpkp@0.2.0 -41 silly currentTree ├─┬ hsts@0.2.0 -41 silly currentTree │ └── core-util-is@1.0.1 -41 silly currentTree ├─┬ html-minifier@0.6.9 -41 silly currentTree │ ├── async@0.2.10 -41 silly currentTree │ ├── camelcase@1.2.1 -41 silly currentTree │ ├── clean-css@2.2.23 -41 silly currentTree │ ├── commander@2.2.0 -41 silly currentTree │ ├── source-map@0.1.34 -41 silly currentTree │ ├── uglify-js@2.4.24 -41 silly currentTree │ ├── wordwrap@0.0.2 -41 silly currentTree │ └── yargs@3.5.4 -41 silly currentTree ├─┬ htmlparser2@3.8.3 -41 silly currentTree │ └── readable-stream@1.1.14 -41 silly currentTree ├── http-errors@1.3.1 -41 silly currentTree ├── http-proxy@1.13.2 -41 silly currentTree ├── http-signature@1.1.1 -41 silly currentTree ├── i@0.3.4 -41 silly currentTree ├── iconv-lite@0.4.13 -41 silly currentTree ├── ienoopen@0.1.0 -41 silly currentTree ├── ignore-by-default@1.0.1 -41 silly currentTree ├── imurmurhash@0.1.4 -41 silly currentTree ├── indent-string@2.1.0 -41 silly currentTree ├── indexof@0.0.1 -41 silly currentTree ├── infinity-agent@2.0.3 -41 silly currentTree ├── inflight@1.0.4 -41 silly currentTree ├── inherits@2.0.1 -41 silly currentTree ├── ini@1.3.4 -41 silly currentTree ├── inline-process-browser@2.0.1 -41 silly currentTree ├── ipaddr.js@1.0.5 -41 silly currentTree ├── is-absolute@0.1.7 -41 silly currentTree ├── is-arrayish@0.2.1 -41 silly currentTree ├── is-binary-path@1.0.1 -41 silly currentTree ├── is-buffer@1.1.3 -41 silly currentTree ├── is-builtin-module@1.0.0 -41 silly currentTree ├── is-dotfile@1.0.2 -41 silly currentTree ├── is-equal-shallow@0.1.3 -41 silly currentTree ├── is-extendable@0.1.1 -41 silly currentTree ├── is-extglob@1.0.0 -41 silly currentTree ├── is-finite@1.0.1 -41 silly currentTree ├── is-glob@2.0.1 -41 silly currentTree ├── is-lower-case@1.1.3 -41 silly currentTree ├── is-my-json-valid@2.13.1 -41 silly currentTree ├── is-npm@1.0.0 -41 silly currentTree ├── is-number@2.1.0 -41 silly currentTree ├── is-posix-bracket@0.1.1 -41 silly currentTree ├── is-primitive@2.0.0 -41 silly currentTree ├── is-promise@2.1.0 -41 silly currentTree ├── is-property@1.0.2 -41 silly currentTree ├── is-redirect@1.0.0 -41 silly currentTree ├── is-relative@0.1.3 -41 silly currentTree ├── is-stream@1.1.0 -41 silly currentTree ├── is-typedarray@1.0.0 -41 silly currentTree ├── is-upper-case@1.1.2 -41 silly currentTree ├── is-utf8@0.2.1 -41 silly currentTree ├── isarray@0.0.1 -41 silly currentTree ├── isbinaryfile@3.0.0 -41 silly currentTree ├── isexe@1.1.2 -41 silly currentTree ├── isobject@2.0.0 -41 silly currentTree ├── isstream@0.1.2 -41 silly currentTree ├─┬ istanbul@0.4.3 -41 silly currentTree │ ├── argparse@1.0.7 -41 silly currentTree │ ├── js-yaml@3.6.0 -41 silly currentTree │ ├── nopt@3.0.6 -41 silly currentTree │ ├── resolve@1.1.7 -41 silly currentTree │ ├── supports-color@3.1.2 -41 silly currentTree │ ├── which@1.2.4 -41 silly currentTree │ └── wordwrap@1.0.0 -41 silly currentTree ├─┬ jade@1.11.0 -41 silly currentTree │ └── commander@2.6.0 -41 silly currentTree ├── jasmine-core@2.4.1 -41 silly currentTree ├── jit-grunt@0.9.1 -41 silly currentTree ├── jodid25519@1.0.2 -41 silly currentTree ├─┬ js-yaml@2.0.5 -41 silly currentTree │ └── esprima@1.0.4 -41 silly currentTree ├── jsbn@0.1.0 -41 silly currentTree ├─┬ jshint@2.8.0 -41 silly currentTree │ ├── lodash@3.7.0 -41 silly currentTree │ ├── minimatch@2.0.10 -41 silly currentTree │ └── strip-json-comments@1.0.4 -41 silly currentTree ├── json-schema@0.2.2 -41 silly currentTree ├── json-stable-stringify@1.0.1 -41 silly currentTree ├── json-stringify-safe@5.0.1 -41 silly currentTree ├── json3@3.2.6 -41 silly currentTree ├── jsonfile@2.3.0 -41 silly currentTree ├── jsonify@0.0.0 -41 silly currentTree ├── jsonpointer@2.0.0 -41 silly currentTree ├── jsprim@1.2.2 -41 silly currentTree ├── jstransformer@0.0.2 -41 silly currentTree ├─┬ karma-chrome-launcher@0.2.3 -41 silly currentTree │ └── which@1.2.4 -41 silly currentTree ├─┬ karma-coverage@0.5.5 -41 silly currentTree │ └── dateformat@1.0.12 -41 silly currentTree ├── karma-firefox-launcher@0.1.7 -41 silly currentTree ├─┬ karma-jasmine-html-reporter@0.1.8 -41 silly currentTree │ └── karma-jasmine@0.2.3 -41 silly currentTree ├── karma-jasmine@0.3.8 -41 silly currentTree ├─┬ karma-mocha-reporter@1.3.0 -41 silly currentTree │ └── chalk@1.1.1 -41 silly currentTree ├── karma-ng-html2js-preprocessor@0.2.2 -41 silly currentTree ├─┬ karma-phantomjs-launcher@0.2.3 -41 silly currentTree │ └── lodash@3.10.1 -41 silly currentTree ├─┬ karma@0.13.22 -41 silly currentTree │ ├── colors@1.1.2 -41 silly currentTree │ └── lodash@3.10.1 -41 silly currentTree ├── kerberos@0.0.11 -41 silly currentTree ├── kew@0.7.0 -41 silly currentTree ├── kind-of@3.0.2 -41 silly currentTree ├── klaw@1.2.0 -41 silly currentTree ├── latest-version@1.0.1 -41 silly currentTree ├── lazy-cache@1.0.3 -41 silly currentTree ├── lazy@1.0.11 -41 silly currentTree ├── lcov-parse@0.0.6 -41 silly currentTree ├── levn@0.3.0 -41 silly currentTree ├── libbase64@0.1.0 -41 silly currentTree ├── libmime@1.2.0 -41 silly currentTree ├── libqp@1.1.0 -41 silly currentTree ├── load-json-file@1.1.0 -41 silly currentTree ├── lodash._arraycopy@3.0.0 -41 silly currentTree ├── lodash._arrayeach@3.0.0 -41 silly currentTree ├── lodash._baseassign@3.2.0 -41 silly currentTree ├── lodash._baseclone@3.3.0 -41 silly currentTree ├── lodash._basecopy@3.0.1 -41 silly currentTree ├── lodash._baseflatten@3.1.4 -41 silly currentTree ├── lodash._basefor@3.0.3 -41 silly currentTree ├── lodash._baseslice@4.0.0 -41 silly currentTree ├── lodash._bindcallback@3.0.1 -41 silly currentTree ├── lodash._createassigner@3.1.1 -41 silly currentTree ├── lodash._getnative@3.9.1 -41 silly currentTree ├── lodash._isiterateecall@3.0.9 -41 silly currentTree ├── lodash._pickbyarray@3.0.2 -41 silly currentTree ├── lodash._pickbycallback@3.0.0 -41 silly currentTree ├── lodash.assign@3.2.0 -41 silly currentTree ├── lodash.clonedeep@3.0.2 -41 silly currentTree ├── lodash.defaults@3.1.2 -41 silly currentTree ├── lodash.isarguments@3.0.8 -41 silly currentTree ├── lodash.isarray@3.0.4 -41 silly currentTree ├── lodash.isstring@3.0.1 -41 silly currentTree ├── lodash.keys@3.1.2 -41 silly currentTree ├── lodash.keysin@3.0.8 -41 silly currentTree ├── lodash.pad@4.3.0 -41 silly currentTree ├── lodash.padend@4.4.0 -41 silly currentTree ├── lodash.padstart@4.4.0 -41 silly currentTree ├── lodash.pick@3.1.0 -41 silly currentTree ├── lodash.restparam@3.6.1 -41 silly currentTree ├── lodash.tostring@4.1.2 -41 silly currentTree ├── lodash@2.4.2 -41 silly currentTree ├── log-driver@1.2.4 -41 silly currentTree ├─┬ log4js@0.6.35 -41 silly currentTree │ └── semver@4.3.6 -41 silly currentTree ├── longest@1.0.1 -41 silly currentTree ├── loud-rejection@1.3.0 -41 silly currentTree ├── lower-case@1.1.3 -41 silly currentTree ├── lowercase-keys@1.0.0 -41 silly currentTree ├── lru-cache@2.2.4 -41 silly currentTree ├── lsmod@0.0.3 -41 silly currentTree ├── mailcomposer@2.1.0 -41 silly currentTree ├─┬ mailosaur@1.0.1 -41 silly currentTree │ ├── asn1@0.1.11 -41 silly currentTree │ ├── assert-plus@0.1.5 -41 silly currentTree │ ├── async@0.9.2 -41 silly currentTree │ ├── aws-sign2@0.5.0 -41 silly currentTree │ ├── boom@0.4.2 -41 silly currentTree │ ├── combined-stream@0.0.7 -41 silly currentTree │ ├── cryptiles@0.2.2 -41 silly currentTree │ ├── delayed-stream@0.0.5 -41 silly currentTree │ ├── forever-agent@0.5.2 -41 silly currentTree │ ├── form-data@0.1.4 -41 silly currentTree │ ├── hawk@1.0.0 -41 silly currentTree │ ├── hoek@0.9.1 -41 silly currentTree │ ├── http-signature@0.10.1 -41 silly currentTree │ ├── mime@1.2.11 -41 silly currentTree │ ├── oauth-sign@0.3.0 -41 silly currentTree │ ├── qs@0.6.6 -41 silly currentTree │ ├── request@2.36.0 -41 silly currentTree │ └── sntp@0.2.4 -41 silly currentTree ├─┬ main-bower-files@2.9.0 -41 silly currentTree │ ├── extend@2.0.1 -41 silly currentTree │ ├── path-exists@1.0.0 -41 silly currentTree │ └── strip-json-comments@1.0.4 -41 silly currentTree ├── mandrill-api@1.0.45 -41 silly currentTree ├── map-obj@1.0.1 -41 silly currentTree ├── map-stream@0.1.0 -41 silly currentTree ├── math@0.0.3 -41 silly currentTree ├── maxmin@1.1.0 -41 silly currentTree ├── media-typer@0.3.0 -41 silly currentTree ├─┬ meow@3.7.0 -41 silly currentTree │ ├── minimist@1.2.0 -41 silly currentTree │ └── object-assign@4.0.1 -41 silly currentTree ├── merge-descriptors@1.0.1 -41 silly currentTree ├── merge-stream@0.1.8 -41 silly currentTree ├─┬ method-override@2.3.5 -41 silly currentTree │ └── vary@1.0.1 -41 silly currentTree ├── methods@1.1.2 -41 silly currentTree ├── micromatch@2.3.7 -41 silly currentTree ├── mime-db@1.22.0 -41 silly currentTree ├── mime-types@2.1.10 -41 silly currentTree ├── mime@1.3.4 -41 silly currentTree ├── minimatch@3.0.0 -41 silly currentTree ├── minimist@0.0.10 -41 silly currentTree ├─┬ mkdirp@0.5.1 -41 silly currentTree │ └── minimist@0.0.8 -41 silly currentTree ├── mocha-lcov-reporter@1.2.0 -41 silly currentTree ├─┬ mocha@2.4.5 -41 silly currentTree │ ├── commander@2.3.0 -41 silly currentTree │ ├── escape-string-regexp@1.0.2 -41 silly currentTree │ ├── glob@3.2.3 -41 silly currentTree │ ├── graceful-fs@2.0.3 -41 silly currentTree │ ├─┬ jade@0.26.3 -41 silly currentTree │ │ ├── commander@0.6.1 -41 silly currentTree │ │ └── mkdirp@0.3.0 -41 silly currentTree │ ├── minimatch@0.2.14 -41 silly currentTree │ └── supports-color@1.2.0 -41 silly currentTree ├── mongodb-core@1.2.31 -41 silly currentTree ├── mongodb@2.0.55 -41 silly currentTree ├─┬ mongoose-utilities@0.1.1 -41 silly currentTree │ ├── bson@0.2.2 -41 silly currentTree │ ├── kerberos@0.0.3 -41 silly currentTree │ ├── mongodb@1.3.19 -41 silly currentTree │ ├── mongoose@3.6.20 -41 silly currentTree │ ├─┬ mpromise@0.2.1 -41 silly currentTree │ │ └── sliced@0.0.4 -41 silly currentTree │ ├── ms@0.1.0 -41 silly currentTree │ └── muri@0.3.1 -41 silly currentTree ├─┬ mongoose@3.8.39 -41 silly currentTree │ ├── bson@0.2.22 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ ├── mongodb@1.4.38 -41 silly currentTree │ ├── ms@0.1.0 -41 silly currentTree │ └── readable-stream@2.1.0 -41 silly currentTree ├─┬ morgan@1.6.1 -41 silly currentTree │ └── depd@1.0.1 -41 silly currentTree ├── mpath@0.1.1 -41 silly currentTree ├── mpromise@0.4.3 -41 silly currentTree ├─┬ mquery@1.6.1 -41 silly currentTree │ └── bluebird@2.9.26 -41 silly currentTree ├── ms@0.7.1 -41 silly currentTree ├── multer@1.1.0 -41 silly currentTree ├── multimatch@2.1.0 -41 silly currentTree ├── muri@1.1.0 -41 silly currentTree ├── mute-stream@0.0.6 -41 silly currentTree ├── nan@1.8.4 -41 silly currentTree ├─┬ nconf@0.6.9 -41 silly currentTree │ ├── async@0.2.9 -41 silly currentTree │ └── optimist@0.6.0 -41 silly currentTree ├── ncp@0.4.2 -41 silly currentTree ├── needle@0.11.0 -41 silly currentTree ├── negotiator@0.6.0 -41 silly currentTree ├── nested-error-stacks@1.0.2 -41 silly currentTree ├─┬ ng-annotate@1.2.1 -41 silly currentTree │ └── acorn@2.6.4 -41 silly currentTree ├── nocache@0.4.0 -41 silly currentTree ├── node-freegeoip@0.0.1 -41 silly currentTree ├─┬ node-inspector@0.12.8 -41 silly currentTree │ ├── async@0.9.2 -41 silly currentTree │ ├── glob@5.0.15 -41 silly currentTree │ ├── semver@4.3.6 -41 silly currentTree │ └── which@1.2.4 -41 silly currentTree ├── node-mandrill@1.0.1 -41 silly currentTree ├─┬ node-pre-gyp@0.6.26 -41 silly currentTree │ └── nopt@3.0.6 -41 silly currentTree ├── node-uuid@1.4.7 -41 silly currentTree ├── nodemailer-direct-transport@1.1.0 -41 silly currentTree ├── nodemailer-mandrill-transport@0.3.0 -41 silly currentTree ├── nodemailer-smtp-transport@1.1.0 -41 silly currentTree ├── nodemailer-wellknown@0.1.9 -41 silly currentTree ├── nodemailer@1.10.0 -41 silly currentTree ├─┬ nodemon@1.9.1 -41 silly currentTree │ ├── es6-promise@3.1.2 -41 silly currentTree │ ├── event-stream@3.3.2 -41 silly currentTree │ └── ps-tree@1.0.1 -41 silly currentTree ├── nopt@1.0.10 -41 silly currentTree ├─┬ noptify@0.0.3 -41 silly currentTree │ └── nopt@2.0.0 -41 silly currentTree ├── normalize-package-data@2.3.5 -41 silly currentTree ├── normalize-path@2.0.1 -41 silly currentTree ├── npmlog@2.0.3 -41 silly currentTree ├── nssocket@0.5.3 -41 silly currentTree ├── null-check@1.0.0 -41 silly currentTree ├── number-is-nan@1.0.0 -41 silly currentTree ├── oauth-sign@0.8.1 -41 silly currentTree ├── oauth@0.9.14 -41 silly currentTree ├── object-assign@3.0.0 -41 silly currentTree ├── object-component@0.0.3 -41 silly currentTree ├── object-keys@1.0.9 -41 silly currentTree ├── object.omit@2.0.0 -41 silly currentTree ├── on-finished@2.3.0 -41 silly currentTree ├── on-headers@1.0.1 -41 silly currentTree ├── once@1.3.3 -41 silly currentTree ├── optimist@0.6.1 -41 silly currentTree ├─┬ optionator@0.8.1 -41 silly currentTree │ └── wordwrap@1.0.0 -41 silly currentTree ├── options@0.0.6 -41 silly currentTree ├── ordered-ast-traverse@1.1.1 -41 silly currentTree ├── ordered-esprima-props@1.1.0 -41 silly currentTree ├── ordered-read-streams@0.1.0 -41 silly currentTree ├── os-homedir@1.0.1 -41 silly currentTree ├── os-tmpdir@1.0.1 -41 silly currentTree ├── osenv@0.1.3 -41 silly currentTree ├── package-json@1.2.0 -41 silly currentTree ├─┬ pad-stream@1.2.0 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ ├── readable-stream@2.0.6 -41 silly currentTree │ └── through2@2.0.1 -41 silly currentTree ├── pako@0.2.8 -41 silly currentTree ├── param-case@1.1.2 -41 silly currentTree ├── parse-glob@3.0.4 -41 silly currentTree ├── parse-json@2.2.0 -41 silly currentTree ├── parsejson@0.0.1 -41 silly currentTree ├── parseqs@0.0.2 -41 silly currentTree ├── parserlib@0.2.5 -41 silly currentTree ├── parseuri@0.0.4 -41 silly currentTree ├── parseurl@1.3.1 -41 silly currentTree ├── pascal-case@1.1.2 -41 silly currentTree ├── passport-facebook@2.0.0 -41 silly currentTree ├── passport-github@1.0.0 -41 silly currentTree ├── passport-google-oauth@0.2.0 -41 silly currentTree ├── passport-linkedin@1.0.0 -41 silly currentTree ├── passport-local@1.0.0 -41 silly currentTree ├── passport-oauth1@1.1.0 -41 silly currentTree ├── passport-oauth2@1.3.0 -41 silly currentTree ├── passport-oauth@1.0.0 -41 silly currentTree ├── passport-strategy@1.0.0 -41 silly currentTree ├── passport-twitter@1.0.4 -41 silly currentTree ├── passport@0.3.2 -41 silly currentTree ├── path-case@1.1.2 -41 silly currentTree ├── path-exists@2.1.0 -41 silly currentTree ├── path-is-absolute@1.0.0 -41 silly currentTree ├── path-to-regexp@0.1.7 -41 silly currentTree ├── path-type@1.1.0 -41 silly currentTree ├── pause-stream@0.0.11 -41 silly currentTree ├── pause@0.0.1 -41 silly currentTree ├─┬ pdffiller@0.1.2 -41 silly currentTree │ ├── lodash@3.8.0 -41 silly currentTree │ ├── should-equal@0.3.1 -41 silly currentTree │ ├── should-format@0.0.7 -41 silly currentTree │ ├── should-type@0.0.4 -41 silly currentTree │ └── should@6.0.1 -41 silly currentTree ├── pend@1.2.0 -41 silly currentTree ├─┬ phantomjs@1.9.20 -41 silly currentTree │ ├── bl@1.0.3 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ ├── readable-stream@2.0.6 -41 silly currentTree │ ├── request@2.67.0 -41 silly currentTree │ └── which@1.2.4 -41 silly currentTree ├── pify@2.3.0 -41 silly currentTree ├── pinkie-promise@2.0.1 -41 silly currentTree ├── pinkie@2.0.4 -41 silly currentTree ├── pkginfo@0.3.1 -41 silly currentTree ├── platform@1.3.0 -41 silly currentTree ├── plist@1.2.0 -41 silly currentTree ├── prelude-ls@1.1.2 -41 silly currentTree ├── prepend-http@1.0.3 -41 silly currentTree ├── prerender-node@2.2.1 -41 silly currentTree ├── preserve@0.2.0 -41 silly currentTree ├── pretty-bytes@1.0.4 -41 silly currentTree ├─┬ prettyjson@1.1.3 -41 silly currentTree │ ├── colors@1.1.2 -41 silly currentTree │ └── minimist@1.2.0 -41 silly currentTree ├── private@0.1.6 -41 silly currentTree ├── process-nextick-args@1.0.6 -41 silly currentTree ├── progress@1.1.8 -41 silly currentTree ├── promise@6.1.0 -41 silly currentTree ├── prompt@0.2.14 -41 silly currentTree ├── proxy-addr@1.0.10 -41 silly currentTree ├── ps-tree@0.0.3 -41 silly currentTree ├── pseudomap@1.0.2 -41 silly currentTree ├─┬ pump@1.0.1 -41 silly currentTree │ └── end-of-stream@1.1.0 -41 silly currentTree ├── pumpify@1.3.4 -41 silly currentTree ├── qs@5.2.0 -41 silly currentTree ├── rand-token@0.2.1 -41 silly currentTree ├── randomatic@1.1.5 -41 silly currentTree ├── range-parser@1.0.3 -41 silly currentTree ├─┬ raven@0.9.0 -41 silly currentTree │ ├── cookie@0.1.0 -41 silly currentTree │ └── stack-trace@0.0.7 -41 silly currentTree ├─┬ raw-body@2.1.6 -41 silly currentTree │ └── bytes@2.3.0 -41 silly currentTree ├─┬ rc@1.1.6 -41 silly currentTree │ ├── minimist@1.2.0 -41 silly currentTree │ └── strip-json-comments@1.0.4 -41 silly currentTree ├─┬ read-all-stream@3.1.0 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ └── readable-stream@2.1.0 -41 silly currentTree ├── read-pkg-up@1.0.1 -41 silly currentTree ├── read-pkg@1.1.0 -41 silly currentTree ├── read@1.0.7 -41 silly currentTree ├── readable-stream@1.0.31 -41 silly currentTree ├─┬ readdirp@2.0.0 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ ├── minimatch@2.0.10 -41 silly currentTree │ └── readable-stream@2.1.0 -41 silly currentTree ├── recast@0.11.5 -41 silly currentTree ├── redent@1.0.0 -41 silly currentTree ├── redis-commands@1.2.0 -41 silly currentTree ├── redis-parser@1.3.0 -41 silly currentTree ├── redis@2.5.3 -41 silly currentTree ├── reduce-component@1.0.1 -41 silly currentTree ├── regex-cache@0.4.3 -41 silly currentTree ├── regexp-clone@0.0.1 -41 silly currentTree ├── registry-url@3.1.0 -41 silly currentTree ├── relateurl@0.2.6 -41 silly currentTree ├── repeat-element@1.1.2 -41 silly currentTree ├── repeat-string@1.5.4 -41 silly currentTree ├── repeating@2.0.1 -41 silly currentTree ├── request-progress@2.0.1 -41 silly currentTree ├─┬ request@2.72.0 -41 silly currentTree │ └── qs@6.1.0 -41 silly currentTree ├── requires-port@1.0.0 -41 silly currentTree ├── resolve@0.3.1 -41 silly currentTree ├── resumer@0.0.0 -41 silly currentTree ├── revalidator@0.1.8 -41 silly currentTree ├── right-align@0.1.3 -41 silly currentTree ├── rimraf@2.5.2 -41 silly currentTree ├── sax@1.2.1 -41 silly currentTree ├── selectn@0.9.6 -41 silly currentTree ├── semver-diff@2.1.0 -41 silly currentTree ├── semver@5.1.0 -41 silly currentTree ├── send@0.13.1 -41 silly currentTree ├── sentence-case@1.1.3 -41 silly currentTree ├── serve-favicon@2.3.0 -41 silly currentTree ├── serve-static@1.10.2 -41 silly currentTree ├── shelljs@0.3.0 -41 silly currentTree ├── should-equal@0.5.0 -41 silly currentTree ├── should-format@0.3.1 -41 silly currentTree ├── should-type@0.2.0 -41 silly currentTree ├── should@7.1.1 -41 silly currentTree ├── shush@1.0.0 -41 silly currentTree ├── sigmund@1.0.1 -41 silly currentTree ├── signal-exit@2.1.2 -41 silly currentTree ├── simple-fmt@0.1.0 -41 silly currentTree ├── simple-is@0.2.0 -41 silly currentTree ├── sliced@0.0.5 -41 silly currentTree ├── slide@1.1.6 -41 silly currentTree ├── smtp-connection@1.3.8 -41 silly currentTree ├── snake-case@1.1.2 -41 silly currentTree ├── sntp@1.0.9 -41 silly currentTree ├─┬ soap@0.11.4 -41 silly currentTree │ ├── debug@0.7.4 -41 silly currentTree │ ├── first-chunk-stream@0.1.0 -41 silly currentTree │ └── strip-bom@0.3.1 -41 silly currentTree ├─┬ socket.io-adapter@0.4.0 -41 silly currentTree │ └─┬ socket.io-parser@2.2.2 -41 silly currentTree │ └── debug@0.7.4 -41 silly currentTree ├─┬ socket.io-client@1.4.5 -41 silly currentTree │ └── component-emitter@1.2.0 -41 silly currentTree ├─┬ socket.io-parser@2.2.6 -41 silly currentTree │ └── json3@3.3.2 -41 silly currentTree ├── socket.io@1.4.5 -41 silly currentTree ├── source-map@0.5.3 -41 silly currentTree ├── spdx-correct@1.0.2 -41 silly currentTree ├── spdx-exceptions@1.0.4 -41 silly currentTree ├── spdx-expression-parse@1.0.2 -41 silly currentTree ├── spdx-license-ids@1.2.1 -41 silly currentTree ├─┬ split2@1.1.1 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ ├── readable-stream@2.0.6 -41 silly currentTree │ └── through2@2.0.1 -41 silly currentTree ├── split@0.3.3 -41 silly currentTree ├── sprintf-js@1.0.3 -41 silly currentTree ├── sshpk@1.7.4 -41 silly currentTree ├── stable@0.1.5 -41 silly currentTree ├── stack-trace@0.0.9 -41 silly currentTree ├── statuses@1.2.1 -41 silly currentTree ├── stream-combiner@0.0.4 -41 silly currentTree ├── streamsearch@0.1.2 -41 silly currentTree ├── string-length@1.0.1 -41 silly currentTree ├── string_decoder@0.10.31 -41 silly currentTree ├── stringmap@0.2.2 -41 silly currentTree ├── stringset@0.2.1 -41 silly currentTree ├── stringstream@0.0.5 -41 silly currentTree ├── strip-ansi@3.0.1 -41 silly currentTree ├── strip-bom@2.0.0 -41 silly currentTree ├── strip-indent@1.0.1 -41 silly currentTree ├── strip-json-comments@0.1.3 -41 silly currentTree ├── strong-data-uri@1.0.3 -41 silly currentTree ├─┬ superagent@1.8.3 -41 silly currentTree │ ├── component-emitter@1.2.1 -41 silly currentTree │ ├── form-data@1.0.0-rc3 -41 silly currentTree │ ├── qs@2.3.3 -41 silly currentTree │ └── readable-stream@1.0.27-1 -41 silly currentTree ├─┬ supertest-session@2.0.1 -41 silly currentTree │ └── object-assign@4.0.1 -41 silly currentTree ├── supertest@1.2.0 -41 silly currentTree ├── supports-color@2.0.0 -41 silly currentTree ├── swap-case@1.1.2 -41 silly currentTree ├─┬ swig@1.4.2 -41 silly currentTree │ ├── async@0.2.10 -41 silly currentTree │ ├── camelcase@1.2.1 -41 silly currentTree │ ├── source-map@0.1.34 -41 silly currentTree │ ├── uglify-js@2.4.24 -41 silly currentTree │ ├── wordwrap@0.0.2 -41 silly currentTree │ └── yargs@3.5.4 -41 silly currentTree ├─┬ tape@2.3.3 -41 silly currentTree │ └── deep-equal@0.1.2 -41 silly currentTree ├─┬ tar-pack@3.1.3 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ └── readable-stream@2.0.6 -41 silly currentTree ├── tar@2.2.1 -41 silly currentTree ├── throttleit@1.0.0 -41 silly currentTree ├─┬ through2-filter@2.0.0 -41 silly currentTree │ ├── isarray@1.0.0 -41 silly currentTree │ ├── readable-stream@2.0.6 -41 silly currentTree │ └── through2@2.0.1 -41 silly currentTree ├─┬ through2@0.6.5 -41 silly currentTree │ └── readable-stream@1.0.34 -41 silly currentTree ├── through@2.3.8 -41 silly currentTree ├── timed-out@2.0.0 -41 silly currentTree ├── timespan@2.3.0 -41 silly currentTree ├─┬ tiny-lr-fork@0.0.5 -41 silly currentTree │ ├── debug@0.7.4 -41 silly currentTree │ └── qs@0.5.6 -41 silly currentTree ├── title-case@1.1.2 -41 silly currentTree ├── to-array@0.1.4 -41 silly currentTree ├── touch@1.0.0 -41 silly currentTree ├── tough-cookie@2.2.2 -41 silly currentTree ├─┬ transformers@2.1.0 -41 silly currentTree │ ├── is-promise@1.0.1 -41 silly currentTree │ ├── optimist@0.3.7 -41 silly currentTree │ ├── promise@2.0.0 -41 silly currentTree │ ├── source-map@0.1.43 -41 silly currentTree │ └── uglify-js@2.2.5 -41 silly currentTree ├── trim-newlines@1.0.0 -41 silly currentTree ├── truncate@1.0.5 -41 silly currentTree ├── tryor@0.1.2 -41 silly currentTree ├── tunnel-agent@0.4.2 -41 silly currentTree ├── tweetnacl@0.14.3 -41 silly currentTree ├── type-check@0.3.2 -41 silly currentTree ├── type-is@1.6.12 -41 silly currentTree ├── typedarray@0.0.6 -41 silly currentTree ├─┬ uglify-js@2.6.2 -41 silly currentTree │ └── async@0.2.10 -41 silly currentTree ├── uglify-to-browserify@1.0.2 -41 silly currentTree ├── uid-number@0.0.6 -41 silly currentTree ├── uid-safe@2.0.0 -41 silly currentTree ├── uid2@0.0.3 -41 silly currentTree ├── uid@0.0.2 -41 silly currentTree ├── ultron@1.0.2 -41 silly currentTree ├── undefsafe@0.0.3 -41 silly currentTree ├── underscore.string@2.2.1 -41 silly currentTree ├── underscore@1.7.0 -41 silly currentTree ├── unique-stream@2.2.1 -41 silly currentTree ├── unpipe@1.0.0 -41 silly currentTree ├── unreachable-branch-transform@0.5.1 -41 silly currentTree ├── untildify@2.1.0 -41 silly currentTree ├─┬ update-notifier@0.5.0 -41 silly currentTree │ └── repeating@1.1.3 -41 silly currentTree ├── upper-case-first@1.1.2 -41 silly currentTree ├── upper-case@1.1.3 -41 silly currentTree ├── uri-path@1.0.0 -41 silly currentTree ├── useragent@2.1.9 -41 silly currentTree ├── utf8@2.1.0 -41 silly currentTree ├── util-deprecate@1.0.2 -41 silly currentTree ├─┬ utile@0.2.1 -41 silly currentTree │ └── async@0.2.10 -41 silly currentTree ├── utils-merge@1.0.0 -41 silly currentTree ├── uuid@2.0.2 -41 silly currentTree ├─┬ v8-debug@0.7.1 -41 silly currentTree │ └── nan@2.2.1 -41 silly currentTree ├─┬ v8-profiler@5.6.0 -41 silly currentTree │ └── nan@2.0.9 -41 silly currentTree ├── validate-npm-package-license@3.0.1 -41 silly currentTree ├── vary@1.1.0 -41 silly currentTree ├── verror@1.3.6 -41 silly currentTree ├─┬ vinyl-fs@1.0.0 -41 silly currentTree │ ├── graceful-fs@3.0.8 -41 silly currentTree │ ├── object-assign@2.1.1 -41 silly currentTree │ └── strip-bom@1.0.0 -41 silly currentTree ├─┬ vinyl@0.4.6 -41 silly currentTree │ └── clone@0.2.0 -41 silly currentTree ├── void-elements@2.0.1 -41 silly currentTree ├── which@1.0.9 -41 silly currentTree ├─┬ win-detect-browsers@1.0.2 -41 silly currentTree │ └── yargs@1.3.3 -41 silly currentTree ├── window-size@0.1.0 -41 silly currentTree ├─┬ winston@0.8.3 -41 silly currentTree │ └── async@0.2.10 -41 silly currentTree ├── with@4.0.3 -41 silly currentTree ├── wordwrap@0.0.3 -41 silly currentTree ├── wrappy@1.0.1 -41 silly currentTree ├── write-file-atomic@1.1.4 -41 silly currentTree ├── ws@1.1.0 -41 silly currentTree ├── x-default-browser@0.3.1 -41 silly currentTree ├── x-xss-protection@0.2.0 -41 silly currentTree ├── xdg-basedir@2.0.0 -41 silly currentTree ├─┬ xmlbuilder@4.0.0 -41 silly currentTree │ └── lodash@3.10.1 -41 silly currentTree ├── xmldom@0.1.22 -41 silly currentTree ├── xmlhttprequest-ssl@1.5.1 -41 silly currentTree ├── xtend@4.0.1 -41 silly currentTree ├── xtraverse@0.1.0 -41 silly currentTree ├── yallist@2.0.0 -41 silly currentTree ├─┬ yargs@3.10.0 -41 silly currentTree │ └── camelcase@1.2.1 -41 silly currentTree ├── yauzl@2.4.1 -41 silly currentTree └── yeast@0.1.2 -42 silly idealTree TellForm@1.2.1 -42 silly idealTree ├── MD5@1.3.0 -42 silly idealTree ├── abbrev@1.0.7 -42 silly idealTree ├── accepts@1.3.2 -42 silly idealTree ├─┬ acorn-globals@1.0.9 -42 silly idealTree │ └── acorn@2.7.0 -42 silly idealTree ├── acorn@1.2.2 -42 silly idealTree ├── addressparser@0.3.2 -42 silly idealTree ├── after@0.8.1 -42 silly idealTree ├── align-text@0.1.4 -42 silly idealTree ├── alter@0.2.0 -42 silly idealTree ├── amdefine@1.0.0 -42 silly idealTree ├── ansi-regex@2.0.0 -42 silly idealTree ├── ansi-styles@2.2.1 -42 silly idealTree ├── ansi@0.3.1 -42 silly idealTree ├── anymatch@1.3.0 -42 silly idealTree ├── append-field@0.1.0 -42 silly idealTree ├─┬ are-we-there-yet@1.1.2 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ └── readable-stream@2.1.0 -42 silly idealTree ├─┬ argparse@0.1.16 -42 silly idealTree │ └── underscore.string@2.4.0 -42 silly idealTree ├── arr-diff@2.0.0 -42 silly idealTree ├── arr-flatten@1.0.1 -42 silly idealTree ├── array-differ@1.0.0 -42 silly idealTree ├── array-find-index@1.0.1 -42 silly idealTree ├── array-flatten@1.1.1 -42 silly idealTree ├── array-slice@0.2.3 -42 silly idealTree ├── array-union@1.0.1 -42 silly idealTree ├── array-uniq@1.0.2 -42 silly idealTree ├── array-unique@0.2.1 -42 silly idealTree ├── arraybuffer.slice@0.0.6 -42 silly idealTree ├── arrify@1.0.1 -42 silly idealTree ├── asap@1.0.0 -42 silly idealTree ├── asn1@0.2.3 -42 silly idealTree ├── assert-plus@0.2.0 -42 silly idealTree ├── ast-types@0.8.16 -42 silly idealTree ├── async-each@1.0.0 -42 silly idealTree ├── async@1.5.2 -42 silly idealTree ├── aws-sign2@0.6.0 -42 silly idealTree ├─┬ aws4@1.3.2 -42 silly idealTree │ └── lru-cache@4.0.1 -42 silly idealTree ├── backo2@1.0.2 -42 silly idealTree ├── balanced-match@0.3.0 -42 silly idealTree ├── base64-arraybuffer@0.1.2 -42 silly idealTree ├── base64-js@0.0.8 -42 silly idealTree ├── base64-url@1.2.1 -42 silly idealTree ├── base64id@0.1.0 -42 silly idealTree ├── basic-auth@1.0.3 -42 silly idealTree ├── batch@0.5.3 -42 silly idealTree ├─┬ bcrypt@0.8.6 -42 silly idealTree │ └── nan@2.2.1 -42 silly idealTree ├── benchmark@1.0.0 -42 silly idealTree ├── better-assert@1.0.2 -42 silly idealTree ├─┬ biased-opener@0.2.8 -42 silly idealTree │ └── minimist@1.2.0 -42 silly idealTree ├── big-integer@1.6.15 -42 silly idealTree ├── binary-extensions@1.4.0 -42 silly idealTree ├── bindings@1.2.1 -42 silly idealTree ├─┬ bl@1.1.2 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ └── readable-stream@2.0.6 -42 silly idealTree ├── blob@0.0.4 -42 silly idealTree ├── block-stream@0.0.8 -42 silly idealTree ├── bluebird@2.10.2 -42 silly idealTree ├── body-parser@1.14.2 -42 silly idealTree ├── boom@2.10.1 -42 silly idealTree ├─┬ bower@1.6.9 -42 silly idealTree │ ├── abbrev@1.0.7 -42 silly idealTree │ ├── archy@1.0.0 -42 silly idealTree │ ├─┬ bower-config@1.2.3 -42 silly idealTree │ │ ├── graceful-fs@4.1.2 -42 silly idealTree │ │ ├─┬ optimist@0.6.1 -42 silly idealTree │ │ │ ├── minimist@0.0.10 -42 silly idealTree │ │ │ └── wordwrap@0.0.3 -42 silly idealTree │ │ └─┬ osenv@0.1.3 -42 silly idealTree │ │ ├── os-homedir@1.0.1 -42 silly idealTree │ │ └── os-tmpdir@1.0.1 -42 silly idealTree │ ├── bower-endpoint-parser@0.2.2 -42 silly idealTree │ ├─┬ bower-json@0.4.0 -42 silly idealTree │ │ ├── deep-extend@0.2.11 -42 silly idealTree │ │ ├── graceful-fs@2.0.3 -42 silly idealTree │ │ └── intersect@0.0.3 -42 silly idealTree │ ├── bower-logger@0.2.2 -42 silly idealTree │ ├─┬ bower-registry-client@1.0.0 -42 silly idealTree │ │ ├── async@0.2.10 -42 silly idealTree │ │ ├── graceful-fs@4.1.2 -42 silly idealTree │ │ ├── mkdirp@0.3.5 -42 silly idealTree │ │ └── request-replay@0.2.0 -42 silly idealTree │ ├─┬ cardinal@0.4.4 -42 silly idealTree │ │ ├── ansicolors@0.2.1 -42 silly idealTree │ │ └─┬ redeyed@0.4.4 -42 silly idealTree │ │ └── esprima@1.0.4 -42 silly idealTree │ ├─┬ chalk@1.1.1 -42 silly idealTree │ │ ├── ansi-styles@2.1.0 -42 silly idealTree │ │ ├── escape-string-regexp@1.0.3 -42 silly idealTree │ │ ├─┬ has-ansi@2.0.0 -42 silly idealTree │ │ │ └── ansi-regex@2.0.0 -42 silly idealTree │ │ ├─┬ strip-ansi@3.0.0 -42 silly idealTree │ │ │ └── ansi-regex@2.0.0 -42 silly idealTree │ │ └── supports-color@2.0.0 -42 silly idealTree │ ├── chmodr@1.0.2 -42 silly idealTree │ ├─┬ configstore@0.3.2 -42 silly idealTree │ │ ├─┬ js-yaml@3.4.6 -42 silly idealTree │ │ │ ├─┬ argparse@1.0.3 -42 silly idealTree │ │ │ │ ├── lodash@3.10.1 -42 silly idealTree │ │ │ │ └── sprintf-js@1.0.3 -42 silly idealTree │ │ │ ├── esprima@2.7.0 -42 silly idealTree │ │ │ └── inherit@2.2.2 -42 silly idealTree │ │ ├── object-assign@2.1.1 -42 silly idealTree │ │ ├─┬ osenv@0.1.3 -42 silly idealTree │ │ │ ├── os-homedir@1.0.1 -42 silly idealTree │ │ │ └── os-tmpdir@1.0.1 -42 silly idealTree │ │ ├── uuid@2.0.1 -42 silly idealTree │ │ └── xdg-basedir@1.0.1 -42 silly idealTree │ ├─┬ decompress-zip@0.1.0 -42 silly idealTree │ │ ├─┬ binary@0.3.0 -42 silly idealTree │ │ │ ├── buffers@0.1.1 -42 silly idealTree │ │ │ └─┬ chainsaw@0.1.0 -42 silly idealTree │ │ │ └── traverse@0.3.9 -42 silly idealTree │ │ ├── mkpath@0.1.0 -42 silly idealTree │ │ ├─┬ readable-stream@1.1.13 -42 silly idealTree │ │ │ ├── core-util-is@1.0.2 -42 silly idealTree │ │ │ ├── inherits@2.0.1 -42 silly idealTree │ │ │ ├── isarray@0.0.1 -42 silly idealTree │ │ │ └── string_decoder@0.10.31 -42 silly idealTree │ │ └─┬ touch@0.0.3 -42 silly idealTree │ │ └── nopt@1.0.10 -42 silly idealTree │ ├── destroy@1.0.3 -42 silly idealTree │ ├─┬ fs-write-stream-atomic@1.0.5 -42 silly idealTree │ │ ├── graceful-fs@4.1.2 -42 silly idealTree │ │ └── imurmurhash@0.1.4 -42 silly idealTree │ ├─┬ fstream-ignore@1.0.3 -42 silly idealTree │ │ ├── inherits@2.0.1 -42 silly idealTree │ │ └─┬ minimatch@3.0.0 -42 silly idealTree │ │ └─┬ brace-expansion@1.1.2 -42 silly idealTree │ │ ├── balanced-match@0.3.0 -42 silly idealTree │ │ └── concat-map@0.0.1 -42 silly idealTree │ ├─┬ fstream@1.0.8 -42 silly idealTree │ │ ├── graceful-fs@4.1.2 -42 silly idealTree │ │ └── inherits@2.0.1 -42 silly idealTree │ ├─┬ github@0.2.4 -42 silly idealTree │ │ └── mime@1.3.4 -42 silly idealTree │ ├─┬ glob@4.5.3 -42 silly idealTree │ │ ├─┬ inflight@1.0.4 -42 silly idealTree │ │ │ └── wrappy@1.0.1 -42 silly idealTree │ │ ├── inherits@2.0.1 -42 silly idealTree │ │ ├─┬ minimatch@2.0.10 -42 silly idealTree │ │ │ └─┬ brace-expansion@1.1.2 -42 silly idealTree │ │ │ ├── balanced-match@0.3.0 -42 silly idealTree │ │ │ └── concat-map@0.0.1 -42 silly idealTree │ │ └─┬ once@1.3.3 -42 silly idealTree │ │ └── wrappy@1.0.1 -42 silly idealTree │ ├── graceful-fs@3.0.8 -42 silly idealTree │ ├─┬ handlebars@2.0.0 -42 silly idealTree │ │ ├─┬ optimist@0.3.7 -42 silly idealTree │ │ │ └── wordwrap@0.0.3 -42 silly idealTree │ │ └─┬ uglify-js@2.3.6 -42 silly idealTree │ │ ├── async@0.2.10 -42 silly idealTree │ │ └─┬ source-map@0.1.43 -42 silly idealTree │ │ └── amdefine@1.0.0 -42 silly idealTree │ ├─┬ inquirer@0.10.0 -42 silly idealTree │ │ ├── ansi-escapes@1.1.0 -42 silly idealTree │ │ ├── ansi-regex@2.0.0 -42 silly idealTree │ │ ├─┬ cli-cursor@1.0.2 -42 silly idealTree │ │ │ └─┬ restore-cursor@1.0.1 -42 silly idealTree │ │ │ ├── exit-hook@1.1.1 -42 silly idealTree │ │ │ └── onetime@1.0.0 -42 silly idealTree │ │ ├── cli-width@1.1.0 -42 silly idealTree │ │ ├── figures@1.4.0 -42 silly idealTree │ │ ├── lodash@3.10.1 -42 silly idealTree │ │ ├─┬ readline2@1.0.1 -42 silly idealTree │ │ │ ├─┬ code-point-at@1.0.0 -42 silly idealTree │ │ │ │ └── number-is-nan@1.0.0 -42 silly idealTree │ │ │ ├─┬ is-fullwidth-code-point@1.0.0 -42 silly idealTree │ │ │ │ └── number-is-nan@1.0.0 -42 silly idealTree │ │ │ └── mute-stream@0.0.5 -42 silly idealTree │ │ ├─┬ run-async@0.1.0 -42 silly idealTree │ │ │ └─┬ once@1.3.3 -42 silly idealTree │ │ │ └── wrappy@1.0.1 -42 silly idealTree │ │ ├── rx-lite@3.1.2 -42 silly idealTree │ │ ├── strip-ansi@3.0.0 -42 silly idealTree │ │ └── through@2.3.8 -42 silly idealTree │ ├─┬ insight@0.7.0 -42 silly idealTree │ │ ├── async@1.5.0 -42 silly idealTree │ │ ├─┬ configstore@1.3.0 -42 silly idealTree │ │ │ ├── graceful-fs@4.1.2 -42 silly idealTree │ │ │ ├── os-tmpdir@1.0.1 -42 silly idealTree │ │ │ ├─┬ osenv@0.1.3 -42 silly idealTree │ │ │ │ └── os-homedir@1.0.1 -42 silly idealTree │ │ │ ├── uuid@2.0.1 -42 silly idealTree │ │ │ ├─┬ write-file-atomic@1.1.4 -42 silly idealTree │ │ │ │ ├── imurmurhash@0.1.4 -42 silly idealTree │ │ │ │ └── slide@1.1.6 -42 silly idealTree │ │ │ └─┬ xdg-basedir@2.0.0 -42 silly idealTree │ │ │ └── os-homedir@1.0.1 -42 silly idealTree │ │ ├─┬ lodash.debounce@3.1.1 -42 silly idealTree │ │ │ └── lodash._getnative@3.9.1 -42 silly idealTree │ │ ├── object-assign@4.0.1 -42 silly idealTree │ │ ├─┬ os-name@1.0.3 -42 silly idealTree │ │ │ ├─┬ osx-release@1.1.0 -42 silly idealTree │ │ │ │ └── minimist@1.2.0 -42 silly idealTree │ │ │ └─┬ win-release@1.1.1 -42 silly idealTree │ │ │ └── semver@5.1.0 -42 silly idealTree │ │ └── tough-cookie@2.2.1 -42 silly idealTree │ ├── is-root@1.0.0 -42 silly idealTree │ ├── junk@1.0.2 -42 silly idealTree │ ├── lockfile@1.0.1 -42 silly idealTree │ ├── lru-cache@2.7.3 -42 silly idealTree │ ├─┬ md5-hex@1.1.0 -42 silly idealTree │ │ └── md5-o-matic@0.1.1 -42 silly idealTree │ ├─┬ mkdirp@0.5.0 -42 silly idealTree │ │ └── minimist@0.0.8 -42 silly idealTree │ ├── mout@0.11.1 -42 silly idealTree │ ├── nopt@3.0.6 -42 silly idealTree │ ├── opn@1.0.2 -42 silly idealTree │ ├─┬ p-throttler@0.1.1 -42 silly idealTree │ │ └── q@0.9.7 -42 silly idealTree │ ├─┬ promptly@0.2.0 -42 silly idealTree │ │ └─┬ read@1.0.7 -42 silly idealTree │ │ └── mute-stream@0.0.5 -42 silly idealTree │ ├── q@1.4.1 -42 silly idealTree │ ├─┬ request-progress@0.3.1 -42 silly idealTree │ │ └── throttleit@0.0.2 -42 silly idealTree │ ├─┬ request@2.53.0 -42 silly idealTree │ │ ├── aws-sign2@0.5.0 -42 silly idealTree │ │ ├─┬ bl@0.9.4 -42 silly idealTree │ │ │ └─┬ readable-stream@1.0.33 -42 silly idealTree │ │ │ ├── core-util-is@1.0.2 -42 silly idealTree │ │ │ ├── inherits@2.0.1 -42 silly idealTree │ │ │ ├── isarray@0.0.1 -42 silly idealTree │ │ │ └── string_decoder@0.10.31 -42 silly idealTree │ │ ├── caseless@0.9.0 -42 silly idealTree │ │ ├─┬ combined-stream@0.0.7 -42 silly idealTree │ │ │ └── delayed-stream@0.0.5 -42 silly idealTree │ │ ├── forever-agent@0.5.2 -42 silly idealTree │ │ ├─┬ form-data@0.2.0 -42 silly idealTree │ │ │ └── async@0.9.2 -42 silly idealTree │ │ ├─┬ hawk@2.3.1 -42 silly idealTree │ │ │ ├── boom@2.10.1 -42 silly idealTree │ │ │ ├── cryptiles@2.0.5 -42 silly idealTree │ │ │ ├── hoek@2.16.3 -42 silly idealTree │ │ │ └── sntp@1.0.9 -42 silly idealTree │ │ ├─┬ http-signature@0.10.1 -42 silly idealTree │ │ │ ├── asn1@0.1.11 -42 silly idealTree │ │ │ ├── assert-plus@0.1.5 -42 silly idealTree │ │ │ └── ctype@0.5.3 -42 silly idealTree │ │ ├── isstream@0.1.2 -42 silly idealTree │ │ ├── json-stringify-safe@5.0.1 -42 silly idealTree │ │ ├─┬ mime-types@2.0.14 -42 silly idealTree │ │ │ └── mime-db@1.12.0 -42 silly idealTree │ │ ├── node-uuid@1.4.7 -42 silly idealTree │ │ ├── oauth-sign@0.6.0 -42 silly idealTree │ │ ├── qs@2.3.3 -42 silly idealTree │ │ ├── stringstream@0.0.5 -42 silly idealTree │ │ ├── tough-cookie@2.2.1 -42 silly idealTree │ │ └── tunnel-agent@0.4.1 -42 silly idealTree │ ├── retry@0.6.1 -42 silly idealTree │ ├─┬ rimraf@2.4.4 -42 silly idealTree │ │ └─┬ glob@5.0.15 -42 silly idealTree │ │ ├─┬ inflight@1.0.4 -42 silly idealTree │ │ │ └── wrappy@1.0.1 -42 silly idealTree │ │ ├── inherits@2.0.1 -42 silly idealTree │ │ ├─┬ minimatch@3.0.0 -42 silly idealTree │ │ │ └─┬ brace-expansion@1.1.2 -42 silly idealTree │ │ │ ├── balanced-match@0.3.0 -42 silly idealTree │ │ │ └── concat-map@0.0.1 -42 silly idealTree │ │ ├─┬ once@1.3.3 -42 silly idealTree │ │ │ └── wrappy@1.0.1 -42 silly idealTree │ │ └── path-is-absolute@1.0.0 -42 silly idealTree │ ├── semver@2.3.2 -42 silly idealTree │ ├─┬ shell-quote@1.4.3 -42 silly idealTree │ │ ├── array-filter@0.0.1 -42 silly idealTree │ │ ├── array-map@0.0.0 -42 silly idealTree │ │ ├── array-reduce@0.0.0 -42 silly idealTree │ │ └── jsonify@0.0.0 -42 silly idealTree │ ├── stringify-object@1.0.1 -42 silly idealTree │ ├─┬ tar-fs@1.8.1 -42 silly idealTree │ │ ├─┬ pump@1.0.1 -42 silly idealTree │ │ │ ├── end-of-stream@1.1.0 -42 silly idealTree │ │ │ └─┬ once@1.3.3 -42 silly idealTree │ │ │ └── wrappy@1.0.1 -42 silly idealTree │ │ └─┬ tar-stream@1.3.1 -42 silly idealTree │ │ ├── bl@1.0.0 -42 silly idealTree │ │ ├─┬ end-of-stream@1.1.0 -42 silly idealTree │ │ │ └─┬ once@1.3.3 -42 silly idealTree │ │ │ └── wrappy@1.0.1 -42 silly idealTree │ │ ├─┬ readable-stream@2.0.4 -42 silly idealTree │ │ │ ├── core-util-is@1.0.2 -42 silly idealTree │ │ │ ├── inherits@2.0.1 -42 silly idealTree │ │ │ ├── isarray@0.0.1 -42 silly idealTree │ │ │ ├── process-nextick-args@1.0.6 -42 silly idealTree │ │ │ ├── string_decoder@0.10.31 -42 silly idealTree │ │ │ └── util-deprecate@1.0.2 -42 silly idealTree │ │ └── xtend@4.0.1 -42 silly idealTree │ ├── tmp@0.0.24 -42 silly idealTree │ ├─┬ update-notifier@0.3.2 -42 silly idealTree │ │ ├── is-npm@1.0.0 -42 silly idealTree │ │ ├─┬ latest-version@1.0.1 -42 silly idealTree │ │ │ └─┬ package-json@1.2.0 -42 silly idealTree │ │ │ ├─┬ got@3.3.1 -42 silly idealTree │ │ │ │ ├─┬ duplexify@3.4.2 -42 silly idealTree │ │ │ │ │ ├─┬ end-of-stream@1.0.0 -42 silly idealTree │ │ │ │ │ │ └─┬ once@1.3.3 -42 silly idealTree │ │ │ │ │ │ └── wrappy@1.0.1 -42 silly idealTree │ │ │ │ │ └─┬ readable-stream@2.0.4 -42 silly idealTree │ │ │ │ │ ├── core-util-is@1.0.2 -42 silly idealTree │ │ │ │ │ ├── inherits@2.0.1 -42 silly idealTree │ │ │ │ │ ├── isarray@0.0.1 -42 silly idealTree │ │ │ │ │ ├── process-nextick-args@1.0.6 -42 silly idealTree │ │ │ │ │ ├── string_decoder@0.10.31 -42 silly idealTree │ │ │ │ │ └── util-deprecate@1.0.2 -42 silly idealTree │ │ │ │ ├── infinity-agent@2.0.3 -42 silly idealTree │ │ │ │ ├── is-redirect@1.0.0 -42 silly idealTree │ │ │ │ ├── is-stream@1.0.1 -42 silly idealTree │ │ │ │ ├── lowercase-keys@1.0.0 -42 silly idealTree │ │ │ │ ├─┬ nested-error-stacks@1.0.2 -42 silly idealTree │ │ │ │ │ └── inherits@2.0.1 -42 silly idealTree │ │ │ │ ├── object-assign@3.0.0 -42 silly idealTree │ │ │ │ ├── prepend-http@1.0.3 -42 silly idealTree │ │ │ │ ├─┬ read-all-stream@3.0.1 -42 silly idealTree │ │ │ │ │ ├─┬ pinkie-promise@1.0.0 -42 silly idealTree │ │ │ │ │ │ └── pinkie@1.0.0 -42 silly idealTree │ │ │ │ │ └─┬ readable-stream@2.0.4 -42 silly idealTree │ │ │ │ │ ├── core-util-is@1.0.2 -42 silly idealTree │ │ │ │ │ ├── inherits@2.0.1 -42 silly idealTree │ │ │ │ │ ├── isarray@0.0.1 -42 silly idealTree │ │ │ │ │ ├── process-nextick-args@1.0.6 -42 silly idealTree │ │ │ │ │ ├── string_decoder@0.10.31 -42 silly idealTree │ │ │ │ │ └── util-deprecate@1.0.2 -42 silly idealTree │ │ │ │ └── timed-out@2.0.0 -42 silly idealTree │ │ │ └─┬ registry-url@3.0.3 -42 silly idealTree │ │ │ └─┬ rc@1.1.5 -42 silly idealTree │ │ │ ├── deep-extend@0.4.0 -42 silly idealTree │ │ │ ├── ini@1.3.4 -42 silly idealTree │ │ │ ├── minimist@1.2.0 -42 silly idealTree │ │ │ └── strip-json-comments@1.0.4 -42 silly idealTree │ │ ├─┬ semver-diff@2.1.0 -42 silly idealTree │ │ │ └── semver@5.1.0 -42 silly idealTree │ │ └─┬ string-length@1.0.1 -42 silly idealTree │ │ └─┬ strip-ansi@3.0.0 -42 silly idealTree │ │ └── ansi-regex@2.0.0 -42 silly idealTree │ ├── user-home@1.1.1 -42 silly idealTree │ └─┬ which@1.2.0 -42 silly idealTree │ └─┬ is-absolute@0.1.7 -42 silly idealTree │ └── is-relative@0.1.3 -42 silly idealTree ├── bplist-parser@0.1.1 -42 silly idealTree ├── brace-expansion@1.1.3 -42 silly idealTree ├── braces@1.8.4 -42 silly idealTree ├─┬ broadway@0.3.6 -42 silly idealTree │ ├── async@0.2.10 -42 silly idealTree │ ├── cliff@0.1.9 -42 silly idealTree │ └── winston@0.8.0 -42 silly idealTree ├─┬ browser-launcher2@0.4.6 -42 silly idealTree │ └── rimraf@2.2.8 -42 silly idealTree ├── browserify-zlib@0.1.4 -42 silly idealTree ├── bson@0.4.23 -42 silly idealTree ├─┬ buildmail@2.0.0 -42 silly idealTree │ └── needle@0.10.0 -42 silly idealTree ├── builtin-modules@1.1.1 -42 silly idealTree ├─┬ busboy@0.2.13 -42 silly idealTree │ └── readable-stream@1.1.14 -42 silly idealTree ├── bytes@2.2.0 -42 silly idealTree ├── caller@0.0.1 -42 silly idealTree ├── callsite@1.0.0 -42 silly idealTree ├── camel-case@1.2.2 -42 silly idealTree ├── camelcase-keys@2.1.0 -42 silly idealTree ├── camelcase@2.1.1 -42 silly idealTree ├── camelize@1.0.0 -42 silly idealTree ├── caseless@0.11.0 -42 silly idealTree ├── center-align@0.1.3 -42 silly idealTree ├── chalk@1.1.3 -42 silly idealTree ├── change-case@2.1.6 -42 silly idealTree ├── character-parser@1.2.1 -42 silly idealTree ├── charenc@0.0.1 -42 silly idealTree ├── chokidar@1.4.3 -42 silly idealTree ├─┬ clean-css@3.4.12 -42 silly idealTree │ └── source-map@0.4.4 -42 silly idealTree ├─┬ cli@0.6.6 -42 silly idealTree │ ├── glob@3.2.11 -42 silly idealTree │ └── minimatch@0.3.0 -42 silly idealTree ├─┬ cliff@0.1.10 -42 silly idealTree │ └── colors@1.0.3 -42 silly idealTree ├─┬ cliui@2.1.0 -42 silly idealTree │ └── wordwrap@0.0.2 -42 silly idealTree ├── clone-stats@0.0.1 -42 silly idealTree ├── clone@1.0.2 -42 silly idealTree ├── coffee-script@1.3.3 -42 silly idealTree ├── colors@0.6.2 -42 silly idealTree ├── combined-stream@1.0.5 -42 silly idealTree ├── commander@2.8.1 -42 silly idealTree ├── component-bind@1.0.0 -42 silly idealTree ├── component-emitter@1.1.2 -42 silly idealTree ├── component-inherit@0.0.3 -42 silly idealTree ├── compressible@2.0.7 -42 silly idealTree ├── compression@1.6.1 -42 silly idealTree ├── concat-map@0.0.1 -42 silly idealTree ├─┬ concat-stream@1.5.1 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ └── readable-stream@2.0.6 -42 silly idealTree ├─┬ configstore@1.4.0 -42 silly idealTree │ └── object-assign@4.0.1 -42 silly idealTree ├── connect-flash@0.1.1 -42 silly idealTree ├── connect-mongo@0.8.2 -42 silly idealTree ├─┬ connect@3.4.0 -42 silly idealTree │ ├── escape-html@1.0.2 -42 silly idealTree │ └── finalhandler@0.4.0 -42 silly idealTree ├── console-browserify@1.1.0 -42 silly idealTree ├── consolidate@0.13.1 -42 silly idealTree ├── constant-case@1.1.2 -42 silly idealTree ├─┬ constantinople@3.0.2 -42 silly idealTree │ └── acorn@2.7.0 -42 silly idealTree ├── content-disposition@0.5.1 -42 silly idealTree ├── content-security-policy-builder@0.2.0 -42 silly idealTree ├── content-type@1.0.1 -42 silly idealTree ├── convert-source-map@1.1.3 -42 silly idealTree ├── cookie-parser@1.4.1 -42 silly idealTree ├── cookie-signature@1.0.6 -42 silly idealTree ├── cookie@0.2.3 -42 silly idealTree ├── cookiejar@2.0.6 -42 silly idealTree ├── core-js@2.2.2 -42 silly idealTree ├── core-util-is@1.0.2 -42 silly idealTree ├─┬ coveralls@2.11.9 -42 silly idealTree │ ├── bl@1.0.3 -42 silly idealTree │ ├── esprima@1.0.4 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ ├── js-yaml@3.0.1 -42 silly idealTree │ ├── minimist@1.2.0 -42 silly idealTree │ ├── readable-stream@2.0.6 -42 silly idealTree │ └── request@2.67.0 -42 silly idealTree ├── crc@3.3.0 -42 silly idealTree ├── crypt@0.0.1 -42 silly idealTree ├── cryptiles@2.0.5 -42 silly idealTree ├── css-parse@1.0.4 -42 silly idealTree ├── css-stringify@1.0.5 -42 silly idealTree ├── css@1.0.8 -42 silly idealTree ├── csslint@0.10.0 -42 silly idealTree ├── ctype@0.5.3 -42 silly idealTree ├── custom-event@1.0.0 -42 silly idealTree ├── cycle@1.0.3 -42 silly idealTree ├─┬ dashdash@1.13.0 -42 silly idealTree │ └── assert-plus@1.0.0 -42 silly idealTree ├── dashify@0.1.0 -42 silly idealTree ├── date-now@0.1.4 -42 silly idealTree ├── dateformat@1.0.2-1.2.3 -42 silly idealTree ├── debug@2.2.0 -42 silly idealTree ├── decamelize@1.2.0 -42 silly idealTree ├── deep-equal@1.0.1 -42 silly idealTree ├── deep-extend@0.4.1 -42 silly idealTree ├── deep-is@0.1.3 -42 silly idealTree ├── default-browser-id@1.0.4 -42 silly idealTree ├── defined@0.0.0 -42 silly idealTree ├── delayed-stream@1.0.0 -42 silly idealTree ├── delegates@1.0.0 -42 silly idealTree ├── depd@1.1.0 -42 silly idealTree ├── destroy@1.0.4 -42 silly idealTree ├── device@0.3.6 -42 silly idealTree ├── di@0.0.1 -42 silly idealTree ├─┬ dicer@0.2.5 -42 silly idealTree │ └── readable-stream@1.1.14 -42 silly idealTree ├── diff@1.4.0 -42 silly idealTree ├── director@1.2.7 -42 silly idealTree ├── dom-serialize@2.2.1 -42 silly idealTree ├─┬ dom-serializer@0.1.0 -42 silly idealTree │ ├── domelementtype@1.1.3 -42 silly idealTree │ └── entities@1.1.1 -42 silly idealTree ├── domelementtype@1.3.0 -42 silly idealTree ├── domhandler@2.3.0 -42 silly idealTree ├── domutils@1.5.1 -42 silly idealTree ├── dont-sniff-mimetype@0.1.0 -42 silly idealTree ├── dot-case@1.1.2 -42 silly idealTree ├── double-ended-queue@2.1.0-0 -42 silly idealTree ├── duplexer@0.1.1 -42 silly idealTree ├─┬ duplexify@3.4.3 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ └── readable-stream@2.1.0 -42 silly idealTree ├── ecc-jsbn@0.1.1 -42 silly idealTree ├── ee-first@1.1.1 -42 silly idealTree ├── email-addresses@2.0.2 -42 silly idealTree ├── email-verification@0.1.9 -42 silly idealTree ├── end-of-stream@1.0.0 -42 silly idealTree ├─┬ engine.io-client@1.6.8 -42 silly idealTree │ └── ws@1.0.1 -42 silly idealTree ├─┬ engine.io-parser@1.2.4 -42 silly idealTree │ └── has-binary@0.1.6 -42 silly idealTree ├─┬ engine.io@1.6.8 -42 silly idealTree │ ├── accepts@1.1.4 -42 silly idealTree │ ├── mime-db@1.12.0 -42 silly idealTree │ ├── mime-types@2.0.14 -42 silly idealTree │ ├── negotiator@0.4.9 -42 silly idealTree │ └── ws@1.0.1 -42 silly idealTree ├── ent@2.2.0 -42 silly idealTree ├── entities@1.0.0 -42 silly idealTree ├── error-ex@1.3.0 -42 silly idealTree ├── es6-promise@2.1.1 -42 silly idealTree ├── escape-html@1.0.3 -42 silly idealTree ├── escape-string-regexp@1.0.5 -42 silly idealTree ├─┬ escodegen@1.8.0 -42 silly idealTree │ └── source-map@0.2.0 -42 silly idealTree ├── esmangle-evaluator@1.0.0 -42 silly idealTree ├── esprima@2.7.2 -42 silly idealTree ├── estraverse@1.9.3 -42 silly idealTree ├── esutils@2.0.2 -42 silly idealTree ├── etag@1.7.0 -42 silly idealTree ├─┬ event-stream@0.5.3 -42 silly idealTree │ └── optimist@0.2.8 -42 silly idealTree ├── eventemitter2@0.4.14 -42 silly idealTree ├── eventemitter3@1.2.0 -42 silly idealTree ├── exit@0.1.2 -42 silly idealTree ├─┬ expand-braces@0.1.2 -42 silly idealTree │ ├── braces@0.1.5 -42 silly idealTree │ ├── expand-range@0.1.1 -42 silly idealTree │ ├── is-number@0.1.1 -42 silly idealTree │ └── repeat-string@0.2.2 -42 silly idealTree ├── expand-brackets@0.1.5 -42 silly idealTree ├── expand-range@1.8.1 -42 silly idealTree ├── express-device@0.4.2 -42 silly idealTree ├── express-partials@0.3.0 -42 silly idealTree ├── express-session@1.12.1 -42 silly idealTree ├─┬ express@4.13.4 -42 silly idealTree │ ├── accepts@1.2.13 -42 silly idealTree │ ├── cookie@0.1.5 -42 silly idealTree │ ├── negotiator@0.5.3 -42 silly idealTree │ ├── qs@4.0.0 -42 silly idealTree │ └── vary@1.0.1 -42 silly idealTree ├── extend@3.0.0 -42 silly idealTree ├── extglob@0.3.2 -42 silly idealTree ├─┬ extract-zip@1.5.0 -42 silly idealTree │ ├── concat-stream@1.5.0 -42 silly idealTree │ ├── debug@0.7.4 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ ├── minimist@0.0.8 -42 silly idealTree │ ├── mkdirp@0.5.0 -42 silly idealTree │ └── readable-stream@2.0.6 -42 silly idealTree ├── extsprintf@1.0.2 -42 silly idealTree ├── eyes@0.1.8 -42 silly idealTree ├── falafel@1.2.0 -42 silly idealTree ├── fast-levenshtein@1.1.3 -42 silly idealTree ├── faye-websocket@0.4.4 -42 silly idealTree ├── fd-slicer@1.0.1 -42 silly idealTree ├── fdf@0.0.0 -42 silly idealTree ├── figures@1.5.0 -42 silly idealTree ├── filename-regex@2.0.0 -42 silly idealTree ├─┬ fileset@0.2.1 -42 silly idealTree │ ├── glob@5.0.15 -42 silly idealTree │ └── minimatch@2.0.10 -42 silly idealTree ├── fill-range@2.2.3 -42 silly idealTree ├── finalhandler@0.4.1 -42 silly idealTree ├── find-index@0.1.1 -42 silly idealTree ├── find-up@1.1.2 -42 silly idealTree ├─┬ findup-sync@0.1.3 -42 silly idealTree │ ├── glob@3.2.11 -42 silly idealTree │ └── minimatch@0.3.0 -42 silly idealTree ├── first-chunk-stream@1.0.0 -42 silly idealTree ├─┬ flatiron@0.4.3 -42 silly idealTree │ └── optimist@0.6.0 -42 silly idealTree ├── for-in@0.1.5 -42 silly idealTree ├── for-own@0.1.4 -42 silly idealTree ├── foreach@2.0.5 -42 silly idealTree ├── forever-agent@0.6.1 -42 silly idealTree ├─┬ forever-monitor@1.6.0 -42 silly idealTree │ └── minimatch@2.0.10 -42 silly idealTree ├── forever@0.15.1 -42 silly idealTree ├── form-data@1.0.0-rc4 -42 silly idealTree ├── formidable@1.0.17 -42 silly idealTree ├── forwarded@0.1.0 -42 silly idealTree ├── frameguard@0.2.2 -42 silly idealTree ├── fresh@0.3.0 -42 silly idealTree ├── from@0.1.3 -42 silly idealTree ├── fs-access@1.0.0 -42 silly idealTree ├── fs-extra@0.26.7 -42 silly idealTree ├── fstream-ignore@1.0.3 -42 silly idealTree ├── fstream@1.0.8 -42 silly idealTree ├── gauge@1.2.7 -42 silly idealTree ├── gaze@0.5.2 -42 silly idealTree ├── generate-function@2.0.0 -42 silly idealTree ├── generate-object-property@1.2.0 -42 silly idealTree ├── get-stdin@4.0.1 -42 silly idealTree ├── getobject@0.1.0 -42 silly idealTree ├── glob-base@0.3.0 -42 silly idealTree ├── glob-parent@2.0.0 -42 silly idealTree ├─┬ glob-stream@4.1.1 -42 silly idealTree │ ├── glob@4.5.3 -42 silly idealTree │ └── minimatch@2.0.10 -42 silly idealTree ├── glob-watcher@0.0.8 -42 silly idealTree ├── glob2base@0.0.12 -42 silly idealTree ├── glob@7.0.3 -42 silly idealTree ├─┬ globby@2.1.0 -42 silly idealTree │ └── glob@5.0.15 -42 silly idealTree ├─┬ globule@0.1.0 -42 silly idealTree │ ├── glob@3.1.21 -42 silly idealTree │ ├── graceful-fs@1.2.3 -42 silly idealTree │ ├── inherits@1.0.2 -42 silly idealTree │ ├── lodash@1.0.2 -42 silly idealTree │ └── minimatch@0.2.14 -42 silly idealTree ├── got@3.3.1 -42 silly idealTree ├── graceful-fs@4.1.3 -42 silly idealTree ├── graceful-readlink@1.0.1 -42 silly idealTree ├── growl@1.8.1 -42 silly idealTree ├── grunt-cli@0.1.13 -42 silly idealTree ├── grunt-concurrent@2.3.0 -42 silly idealTree ├─┬ grunt-contrib-csslint@0.5.0 -42 silly idealTree │ ├── lodash@3.10.1 -42 silly idealTree │ └── strip-json-comments@1.0.4 -42 silly idealTree ├── grunt-contrib-cssmin@0.14.0 -42 silly idealTree ├── grunt-contrib-jshint@0.11.3 -42 silly idealTree ├─┬ grunt-contrib-uglify@0.11.1 -42 silly idealTree │ ├── gzip-size@3.0.0 -42 silly idealTree │ ├── lodash@4.11.1 -42 silly idealTree │ ├── maxmin@2.1.0 -42 silly idealTree │ └── pretty-bytes@3.0.1 -42 silly idealTree ├─┬ grunt-contrib-watch@0.6.1 -42 silly idealTree │ └── async@0.2.10 -42 silly idealTree ├── grunt-env@0.4.4 -42 silly idealTree ├── grunt-html2js@0.3.6 -42 silly idealTree ├─┬ grunt-karma@0.12.2 -42 silly idealTree │ └── lodash@3.10.1 -42 silly idealTree ├─┬ grunt-legacy-log-utils@0.1.1 -42 silly idealTree │ └── underscore.string@2.3.3 -42 silly idealTree ├─┬ grunt-legacy-log@0.1.3 -42 silly idealTree │ └── underscore.string@2.3.3 -42 silly idealTree ├─┬ grunt-legacy-util@0.2.0 -42 silly idealTree │ ├── async@0.1.22 -42 silly idealTree │ └── lodash@0.9.2 -42 silly idealTree ├── grunt-mocha-istanbul@3.0.1 -42 silly idealTree ├── grunt-mocha-test@0.12.7 -42 silly idealTree ├─┬ grunt-newer@1.1.2 -42 silly idealTree │ ├── async@0.9.0 -42 silly idealTree │ └── rimraf@2.2.8 -42 silly idealTree ├── grunt-ng-annotate@1.0.1 -42 silly idealTree ├── grunt-node-inspector@0.4.1 -42 silly idealTree ├── grunt-nodemon@0.4.2 -42 silly idealTree ├─┬ grunt@0.4.5 -42 silly idealTree │ ├── async@0.1.22 -42 silly idealTree │ ├── glob@3.1.21 -42 silly idealTree │ ├── graceful-fs@1.2.3 -42 silly idealTree │ ├── iconv-lite@0.2.11 -42 silly idealTree │ ├── inherits@1.0.2 -42 silly idealTree │ ├── lodash@0.9.2 -42 silly idealTree │ ├── minimatch@0.2.14 -42 silly idealTree │ └── rimraf@2.2.8 -42 silly idealTree ├── gzip-size@1.0.0 -42 silly idealTree ├─┬ handlebars@4.0.5 -42 silly idealTree │ └── source-map@0.4.4 -42 silly idealTree ├─┬ har-validator@2.0.6 -42 silly idealTree │ └── commander@2.9.0 -42 silly idealTree ├── has-ansi@2.0.0 -42 silly idealTree ├── has-binary@0.1.7 -42 silly idealTree ├── has-cors@1.1.0 -42 silly idealTree ├── has-flag@1.0.0 -42 silly idealTree ├── has-unicode@2.0.0 -42 silly idealTree ├── hasha@2.2.0 -42 silly idealTree ├── hawk@3.1.3 -42 silly idealTree ├── headless@0.1.7 -42 silly idealTree ├── helmet-crossdomain@0.1.0 -42 silly idealTree ├── helmet-csp@0.3.0 -42 silly idealTree ├── helmet@0.14.0 -42 silly idealTree ├── hide-powered-by@0.1.0 -42 silly idealTree ├── hoek@2.16.3 -42 silly idealTree ├── hooker@0.2.3 -42 silly idealTree ├── hooks@0.2.1 -42 silly idealTree ├── hosted-git-info@2.1.4 -42 silly idealTree ├── hpkp@0.2.0 -42 silly idealTree ├─┬ hsts@0.2.0 -42 silly idealTree │ └── core-util-is@1.0.1 -42 silly idealTree ├─┬ html-minifier@0.6.9 -42 silly idealTree │ ├── async@0.2.10 -42 silly idealTree │ ├── camelcase@1.2.1 -42 silly idealTree │ ├── clean-css@2.2.23 -42 silly idealTree │ ├── commander@2.2.0 -42 silly idealTree │ ├── source-map@0.1.34 -42 silly idealTree │ ├── uglify-js@2.4.24 -42 silly idealTree │ ├── wordwrap@0.0.2 -42 silly idealTree │ └── yargs@3.5.4 -42 silly idealTree ├─┬ htmlparser2@3.8.3 -42 silly idealTree │ └── readable-stream@1.1.14 -42 silly idealTree ├── http-errors@1.3.1 -42 silly idealTree ├── http-proxy@1.13.2 -42 silly idealTree ├── http-signature@1.1.1 -42 silly idealTree ├── i@0.3.4 -42 silly idealTree ├── iconv-lite@0.4.13 -42 silly idealTree ├── ienoopen@0.1.0 -42 silly idealTree ├── ignore-by-default@1.0.1 -42 silly idealTree ├── imurmurhash@0.1.4 -42 silly idealTree ├── indent-string@2.1.0 -42 silly idealTree ├── indexof@0.0.1 -42 silly idealTree ├── infinity-agent@2.0.3 -42 silly idealTree ├── inflight@1.0.4 -42 silly idealTree ├── inherits@2.0.1 -42 silly idealTree ├── ini@1.3.4 -42 silly idealTree ├── inline-process-browser@2.0.1 -42 silly idealTree ├── ipaddr.js@1.0.5 -42 silly idealTree ├── is-absolute@0.1.7 -42 silly idealTree ├── is-arrayish@0.2.1 -42 silly idealTree ├── is-binary-path@1.0.1 -42 silly idealTree ├── is-buffer@1.1.3 -42 silly idealTree ├── is-builtin-module@1.0.0 -42 silly idealTree ├── is-dotfile@1.0.2 -42 silly idealTree ├── is-equal-shallow@0.1.3 -42 silly idealTree ├── is-extendable@0.1.1 -42 silly idealTree ├── is-extglob@1.0.0 -42 silly idealTree ├── is-finite@1.0.1 -42 silly idealTree ├── is-glob@2.0.1 -42 silly idealTree ├── is-lower-case@1.1.3 -42 silly idealTree ├── is-my-json-valid@2.13.1 -42 silly idealTree ├── is-npm@1.0.0 -42 silly idealTree ├── is-number@2.1.0 -42 silly idealTree ├── is-posix-bracket@0.1.1 -42 silly idealTree ├── is-primitive@2.0.0 -42 silly idealTree ├── is-promise@2.1.0 -42 silly idealTree ├── is-property@1.0.2 -42 silly idealTree ├── is-redirect@1.0.0 -42 silly idealTree ├── is-relative@0.1.3 -42 silly idealTree ├── is-stream@1.1.0 -42 silly idealTree ├── is-typedarray@1.0.0 -42 silly idealTree ├── is-upper-case@1.1.2 -42 silly idealTree ├── is-utf8@0.2.1 -42 silly idealTree ├── isarray@0.0.1 -42 silly idealTree ├── isbinaryfile@3.0.0 -42 silly idealTree ├── isexe@1.1.2 -42 silly idealTree ├── isobject@2.0.0 -42 silly idealTree ├── isstream@0.1.2 -42 silly idealTree ├─┬ istanbul@0.4.3 -42 silly idealTree │ ├── argparse@1.0.7 -42 silly idealTree │ ├── js-yaml@3.6.0 -42 silly idealTree │ ├── nopt@3.0.6 -42 silly idealTree │ ├── resolve@1.1.7 -42 silly idealTree │ ├── supports-color@3.1.2 -42 silly idealTree │ ├── which@1.2.4 -42 silly idealTree │ └── wordwrap@1.0.0 -42 silly idealTree ├─┬ jade@1.11.0 -42 silly idealTree │ └── commander@2.6.0 -42 silly idealTree ├── jasmine-core@2.4.1 -42 silly idealTree ├── jit-grunt@0.9.1 -42 silly idealTree ├── jodid25519@1.0.2 -42 silly idealTree ├─┬ js-yaml@2.0.5 -42 silly idealTree │ └── esprima@1.0.4 -42 silly idealTree ├── jsbn@0.1.0 -42 silly idealTree ├─┬ jshint@2.8.0 -42 silly idealTree │ ├── lodash@3.7.0 -42 silly idealTree │ ├── minimatch@2.0.10 -42 silly idealTree │ └── strip-json-comments@1.0.4 -42 silly idealTree ├── json-schema@0.2.2 -42 silly idealTree ├── json-stable-stringify@1.0.1 -42 silly idealTree ├── json-stringify-safe@5.0.1 -42 silly idealTree ├── json3@3.2.6 -42 silly idealTree ├── jsonfile@2.3.0 -42 silly idealTree ├── jsonify@0.0.0 -42 silly idealTree ├── jsonpointer@2.0.0 -42 silly idealTree ├── jsprim@1.2.2 -42 silly idealTree ├── jstransformer@0.0.2 -42 silly idealTree ├─┬ karma-chrome-launcher@0.2.3 -42 silly idealTree │ └── which@1.2.4 -42 silly idealTree ├─┬ karma-coverage@0.5.5 -42 silly idealTree │ └── dateformat@1.0.12 -42 silly idealTree ├── karma-firefox-launcher@0.1.7 -42 silly idealTree ├─┬ karma-jasmine-html-reporter@0.1.8 -42 silly idealTree │ └── karma-jasmine@0.2.3 -42 silly idealTree ├── karma-jasmine@0.3.8 -42 silly idealTree ├─┬ karma-mocha-reporter@1.3.0 -42 silly idealTree │ └── chalk@1.1.1 -42 silly idealTree ├── karma-ng-html2js-preprocessor@0.2.2 -42 silly idealTree ├─┬ karma-phantomjs-launcher@0.2.3 -42 silly idealTree │ └── lodash@3.10.1 -42 silly idealTree ├─┬ karma@0.13.22 -42 silly idealTree │ ├── colors@1.1.2 -42 silly idealTree │ └── lodash@3.10.1 -42 silly idealTree ├── kerberos@0.0.11 -42 silly idealTree ├── kew@0.7.0 -42 silly idealTree ├── kind-of@3.0.2 -42 silly idealTree ├── klaw@1.2.0 -42 silly idealTree ├── latest-version@1.0.1 -42 silly idealTree ├── lazy-cache@1.0.3 -42 silly idealTree ├── lazy@1.0.11 -42 silly idealTree ├── lcov-parse@0.0.6 -42 silly idealTree ├── levn@0.3.0 -42 silly idealTree ├── libbase64@0.1.0 -42 silly idealTree ├── libmime@1.2.0 -42 silly idealTree ├── libqp@1.1.0 -42 silly idealTree ├── load-json-file@1.1.0 -42 silly idealTree ├── lodash._arraycopy@3.0.0 -42 silly idealTree ├── lodash._arrayeach@3.0.0 -42 silly idealTree ├── lodash._baseassign@3.2.0 -42 silly idealTree ├── lodash._baseclone@3.3.0 -42 silly idealTree ├── lodash._basecopy@3.0.1 -42 silly idealTree ├── lodash._baseflatten@3.1.4 -42 silly idealTree ├── lodash._basefor@3.0.3 -42 silly idealTree ├── lodash._baseslice@4.0.0 -42 silly idealTree ├── lodash._bindcallback@3.0.1 -42 silly idealTree ├── lodash._createassigner@3.1.1 -42 silly idealTree ├── lodash._getnative@3.9.1 -42 silly idealTree ├── lodash._isiterateecall@3.0.9 -42 silly idealTree ├── lodash._pickbyarray@3.0.2 -42 silly idealTree ├── lodash._pickbycallback@3.0.0 -42 silly idealTree ├── lodash.assign@3.2.0 -42 silly idealTree ├── lodash.clonedeep@3.0.2 -42 silly idealTree ├── lodash.defaults@3.1.2 -42 silly idealTree ├── lodash.isarguments@3.0.8 -42 silly idealTree ├── lodash.isarray@3.0.4 -42 silly idealTree ├── lodash.isstring@3.0.1 -42 silly idealTree ├── lodash.keys@3.1.2 -42 silly idealTree ├── lodash.keysin@3.0.8 -42 silly idealTree ├── lodash.pad@4.3.0 -42 silly idealTree ├── lodash.padend@4.4.0 -42 silly idealTree ├── lodash.padstart@4.4.0 -42 silly idealTree ├── lodash.pick@3.1.0 -42 silly idealTree ├── lodash.restparam@3.6.1 -42 silly idealTree ├── lodash.tostring@4.1.2 -42 silly idealTree ├── lodash@2.4.2 -42 silly idealTree ├── log-driver@1.2.4 -42 silly idealTree ├─┬ log4js@0.6.35 -42 silly idealTree │ └── semver@4.3.6 -42 silly idealTree ├── longest@1.0.1 -42 silly idealTree ├── loud-rejection@1.3.0 -42 silly idealTree ├── lower-case@1.1.3 -42 silly idealTree ├── lowercase-keys@1.0.0 -42 silly idealTree ├── lru-cache@2.2.4 -42 silly idealTree ├── lsmod@0.0.3 -42 silly idealTree ├── mailcomposer@2.1.0 -42 silly idealTree ├─┬ mailosaur@1.0.1 -42 silly idealTree │ ├── asn1@0.1.11 -42 silly idealTree │ ├── assert-plus@0.1.5 -42 silly idealTree │ ├── async@0.9.2 -42 silly idealTree │ ├── aws-sign2@0.5.0 -42 silly idealTree │ ├── boom@0.4.2 -42 silly idealTree │ ├── combined-stream@0.0.7 -42 silly idealTree │ ├── cryptiles@0.2.2 -42 silly idealTree │ ├── delayed-stream@0.0.5 -42 silly idealTree │ ├── forever-agent@0.5.2 -42 silly idealTree │ ├── form-data@0.1.4 -42 silly idealTree │ ├── hawk@1.0.0 -42 silly idealTree │ ├── hoek@0.9.1 -42 silly idealTree │ ├── http-signature@0.10.1 -42 silly idealTree │ ├── mime@1.2.11 -42 silly idealTree │ ├── oauth-sign@0.3.0 -42 silly idealTree │ ├── qs@0.6.6 -42 silly idealTree │ ├── request@2.36.0 -42 silly idealTree │ └── sntp@0.2.4 -42 silly idealTree ├─┬ main-bower-files@2.9.0 -42 silly idealTree │ ├── extend@2.0.1 -42 silly idealTree │ ├── path-exists@1.0.0 -42 silly idealTree │ └── strip-json-comments@1.0.4 -42 silly idealTree ├── mandrill-api@1.0.45 -42 silly idealTree ├── map-obj@1.0.1 -42 silly idealTree ├── map-stream@0.1.0 -42 silly idealTree ├── math@0.0.3 -42 silly idealTree ├── maxmin@1.1.0 -42 silly idealTree ├── media-typer@0.3.0 -42 silly idealTree ├─┬ meow@3.7.0 -42 silly idealTree │ ├── minimist@1.2.0 -42 silly idealTree │ └── object-assign@4.0.1 -42 silly idealTree ├── merge-descriptors@1.0.1 -42 silly idealTree ├── merge-stream@0.1.8 -42 silly idealTree ├─┬ method-override@2.3.5 -42 silly idealTree │ └── vary@1.0.1 -42 silly idealTree ├── methods@1.1.2 -42 silly idealTree ├── micromatch@2.3.7 -42 silly idealTree ├── mime-db@1.22.0 -42 silly idealTree ├── mime-types@2.1.10 -42 silly idealTree ├── mime@1.3.4 -42 silly idealTree ├── minimatch@3.0.0 -42 silly idealTree ├── minimist@0.0.10 -42 silly idealTree ├─┬ mkdirp@0.5.1 -42 silly idealTree │ └── minimist@0.0.8 -42 silly idealTree ├── mocha-lcov-reporter@1.2.0 -42 silly idealTree ├─┬ mocha@2.4.5 -42 silly idealTree │ ├── commander@2.3.0 -42 silly idealTree │ ├── escape-string-regexp@1.0.2 -42 silly idealTree │ ├── glob@3.2.3 -42 silly idealTree │ ├── graceful-fs@2.0.3 -42 silly idealTree │ ├─┬ jade@0.26.3 -42 silly idealTree │ │ ├── commander@0.6.1 -42 silly idealTree │ │ └── mkdirp@0.3.0 -42 silly idealTree │ ├── minimatch@0.2.14 -42 silly idealTree │ └── supports-color@1.2.0 -42 silly idealTree ├── mongodb-core@1.2.31 -42 silly idealTree ├── mongodb@2.0.55 -42 silly idealTree ├─┬ mongoose-utilities@0.1.1 -42 silly idealTree │ ├── bson@0.2.2 -42 silly idealTree │ ├── kerberos@0.0.3 -42 silly idealTree │ ├── mongodb@1.3.19 -42 silly idealTree │ ├── mongoose@3.6.20 -42 silly idealTree │ ├─┬ mpromise@0.2.1 -42 silly idealTree │ │ └── sliced@0.0.4 -42 silly idealTree │ ├── ms@0.1.0 -42 silly idealTree │ └── muri@0.3.1 -42 silly idealTree ├─┬ mongoose@3.8.39 -42 silly idealTree │ ├── bson@0.2.22 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ ├── mongodb@1.4.38 -42 silly idealTree │ ├── ms@0.1.0 -42 silly idealTree │ └── readable-stream@2.1.0 -42 silly idealTree ├─┬ morgan@1.6.1 -42 silly idealTree │ └── depd@1.0.1 -42 silly idealTree ├── mpath@0.1.1 -42 silly idealTree ├── mpromise@0.4.3 -42 silly idealTree ├─┬ mquery@1.6.1 -42 silly idealTree │ └── bluebird@2.9.26 -42 silly idealTree ├── ms@0.7.1 -42 silly idealTree ├── multer@1.1.0 -42 silly idealTree ├── multimatch@2.1.0 -42 silly idealTree ├── muri@1.1.0 -42 silly idealTree ├── mute-stream@0.0.6 -42 silly idealTree ├── nan@1.8.4 -42 silly idealTree ├─┬ nconf@0.6.9 -42 silly idealTree │ ├── async@0.2.9 -42 silly idealTree │ └── optimist@0.6.0 -42 silly idealTree ├── ncp@0.4.2 -42 silly idealTree ├── needle@0.11.0 -42 silly idealTree ├── negotiator@0.6.0 -42 silly idealTree ├── nested-error-stacks@1.0.2 -42 silly idealTree ├─┬ ng-annotate@1.2.1 -42 silly idealTree │ └── acorn@2.6.4 -42 silly idealTree ├── nocache@0.4.0 -42 silly idealTree ├── node-freegeoip@0.0.1 -42 silly idealTree ├─┬ node-inspector@0.12.8 -42 silly idealTree │ ├── async@0.9.2 -42 silly idealTree │ ├── glob@5.0.15 -42 silly idealTree │ ├── semver@4.3.6 -42 silly idealTree │ └── which@1.2.4 -42 silly idealTree ├── node-mandrill@1.0.1 -42 silly idealTree ├─┬ node-pre-gyp@0.6.26 -42 silly idealTree │ └── nopt@3.0.6 -42 silly idealTree ├── node-uuid@1.4.7 -42 silly idealTree ├── nodemailer-direct-transport@1.1.0 -42 silly idealTree ├── nodemailer-mandrill-transport@0.3.0 -42 silly idealTree ├── nodemailer-smtp-transport@1.1.0 -42 silly idealTree ├── nodemailer-wellknown@0.1.9 -42 silly idealTree ├── nodemailer@1.10.0 -42 silly idealTree ├─┬ nodemon@1.9.1 -42 silly idealTree │ ├── es6-promise@3.1.2 -42 silly idealTree │ ├── event-stream@3.3.2 -42 silly idealTree │ └── ps-tree@1.0.1 -42 silly idealTree ├── nopt@1.0.10 -42 silly idealTree ├─┬ noptify@0.0.3 -42 silly idealTree │ └── nopt@2.0.0 -42 silly idealTree ├── normalize-package-data@2.3.5 -42 silly idealTree ├── normalize-path@2.0.1 -42 silly idealTree ├── npmlog@2.0.3 -42 silly idealTree ├── nssocket@0.5.3 -42 silly idealTree ├── null-check@1.0.0 -42 silly idealTree ├── number-is-nan@1.0.0 -42 silly idealTree ├── oauth-sign@0.8.1 -42 silly idealTree ├── oauth@0.9.14 -42 silly idealTree ├── object-assign@3.0.0 -42 silly idealTree ├── object-component@0.0.3 -42 silly idealTree ├── object-keys@1.0.9 -42 silly idealTree ├── object.omit@2.0.0 -42 silly idealTree ├── on-finished@2.3.0 -42 silly idealTree ├── on-headers@1.0.1 -42 silly idealTree ├── once@1.3.3 -42 silly idealTree ├── optimist@0.6.1 -42 silly idealTree ├─┬ optionator@0.8.1 -42 silly idealTree │ └── wordwrap@1.0.0 -42 silly idealTree ├── options@0.0.6 -42 silly idealTree ├── ordered-ast-traverse@1.1.1 -42 silly idealTree ├── ordered-esprima-props@1.1.0 -42 silly idealTree ├── ordered-read-streams@0.1.0 -42 silly idealTree ├── os-homedir@1.0.1 -42 silly idealTree ├── os-tmpdir@1.0.1 -42 silly idealTree ├── osenv@0.1.3 -42 silly idealTree ├── package-json@1.2.0 -42 silly idealTree ├─┬ pad-stream@1.2.0 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ ├── readable-stream@2.0.6 -42 silly idealTree │ └── through2@2.0.1 -42 silly idealTree ├── pako@0.2.8 -42 silly idealTree ├── param-case@1.1.2 -42 silly idealTree ├── parse-glob@3.0.4 -42 silly idealTree ├── parse-json@2.2.0 -42 silly idealTree ├── parsejson@0.0.1 -42 silly idealTree ├── parseqs@0.0.2 -42 silly idealTree ├── parserlib@0.2.5 -42 silly idealTree ├── parseuri@0.0.4 -42 silly idealTree ├── parseurl@1.3.1 -42 silly idealTree ├── pascal-case@1.1.2 -42 silly idealTree ├── passport-facebook@2.0.0 -42 silly idealTree ├── passport-github@1.0.0 -42 silly idealTree ├── passport-google-oauth@0.2.0 -42 silly idealTree ├── passport-linkedin@1.0.0 -42 silly idealTree ├── passport-local@1.0.0 -42 silly idealTree ├── passport-oauth1@1.1.0 -42 silly idealTree ├── passport-oauth2@1.3.0 -42 silly idealTree ├── passport-oauth@1.0.0 -42 silly idealTree ├── passport-strategy@1.0.0 -42 silly idealTree ├── passport-twitter@1.0.4 -42 silly idealTree ├── passport@0.3.2 -42 silly idealTree ├── path-case@1.1.2 -42 silly idealTree ├── path-exists@2.1.0 -42 silly idealTree ├── path-is-absolute@1.0.0 -42 silly idealTree ├── path-to-regexp@0.1.7 -42 silly idealTree ├── path-type@1.1.0 -42 silly idealTree ├── pause-stream@0.0.11 -42 silly idealTree ├── pause@0.0.1 -42 silly idealTree ├─┬ pdffiller@0.1.2 -42 silly idealTree │ ├── lodash@3.8.0 -42 silly idealTree │ ├── should-equal@0.3.1 -42 silly idealTree │ ├── should-format@0.0.7 -42 silly idealTree │ ├── should-type@0.0.4 -42 silly idealTree │ └── should@6.0.1 -42 silly idealTree ├── pend@1.2.0 -42 silly idealTree ├─┬ phantomjs@1.9.20 -42 silly idealTree │ ├── bl@1.0.3 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ ├── readable-stream@2.0.6 -42 silly idealTree │ ├── request@2.67.0 -42 silly idealTree │ └── which@1.2.4 -42 silly idealTree ├── pify@2.3.0 -42 silly idealTree ├── pinkie-promise@2.0.1 -42 silly idealTree ├── pinkie@2.0.4 -42 silly idealTree ├── pkginfo@0.3.1 -42 silly idealTree ├── platform@1.3.0 -42 silly idealTree ├── plist@1.2.0 -42 silly idealTree ├── prelude-ls@1.1.2 -42 silly idealTree ├── prepend-http@1.0.3 -42 silly idealTree ├── prerender-node@2.2.1 -42 silly idealTree ├── preserve@0.2.0 -42 silly idealTree ├── pretty-bytes@1.0.4 -42 silly idealTree ├─┬ prettyjson@1.1.3 -42 silly idealTree │ ├── colors@1.1.2 -42 silly idealTree │ └── minimist@1.2.0 -42 silly idealTree ├── private@0.1.6 -42 silly idealTree ├── process-nextick-args@1.0.6 -42 silly idealTree ├── progress@1.1.8 -42 silly idealTree ├── promise@6.1.0 -42 silly idealTree ├── prompt@0.2.14 -42 silly idealTree ├── proxy-addr@1.0.10 -42 silly idealTree ├── ps-tree@0.0.3 -42 silly idealTree ├── pseudomap@1.0.2 -42 silly idealTree ├─┬ pump@1.0.1 -42 silly idealTree │ └── end-of-stream@1.1.0 -42 silly idealTree ├── pumpify@1.3.4 -42 silly idealTree ├── qs@5.2.0 -42 silly idealTree ├── rand-token@0.2.1 -42 silly idealTree ├── randomatic@1.1.5 -42 silly idealTree ├── range-parser@1.0.3 -42 silly idealTree ├─┬ raven@0.9.0 -42 silly idealTree │ ├── cookie@0.1.0 -42 silly idealTree │ └── stack-trace@0.0.7 -42 silly idealTree ├─┬ raw-body@2.1.6 -42 silly idealTree │ └── bytes@2.3.0 -42 silly idealTree ├─┬ rc@1.1.6 -42 silly idealTree │ ├── minimist@1.2.0 -42 silly idealTree │ └── strip-json-comments@1.0.4 -42 silly idealTree ├─┬ read-all-stream@3.1.0 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ └── readable-stream@2.1.0 -42 silly idealTree ├── read-pkg-up@1.0.1 -42 silly idealTree ├── read-pkg@1.1.0 -42 silly idealTree ├── read@1.0.7 -42 silly idealTree ├── readable-stream@1.0.31 -42 silly idealTree ├─┬ readdirp@2.0.0 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ ├── minimatch@2.0.10 -42 silly idealTree │ └── readable-stream@2.1.0 -42 silly idealTree ├── recast@0.11.5 -42 silly idealTree ├── redent@1.0.0 -42 silly idealTree ├── redis-commands@1.2.0 -42 silly idealTree ├── redis-parser@1.3.0 -42 silly idealTree ├── redis@2.5.3 -42 silly idealTree ├── reduce-component@1.0.1 -42 silly idealTree ├── regex-cache@0.4.3 -42 silly idealTree ├── regexp-clone@0.0.1 -42 silly idealTree ├── registry-url@3.1.0 -42 silly idealTree ├── relateurl@0.2.6 -42 silly idealTree ├── repeat-element@1.1.2 -42 silly idealTree ├── repeat-string@1.5.4 -42 silly idealTree ├── repeating@2.0.1 -42 silly idealTree ├── request-progress@2.0.1 -42 silly idealTree ├─┬ request@2.72.0 -42 silly idealTree │ └── qs@6.1.0 -42 silly idealTree ├── requires-port@1.0.0 -42 silly idealTree ├── resolve@0.3.1 -42 silly idealTree ├── resumer@0.0.0 -42 silly idealTree ├── revalidator@0.1.8 -42 silly idealTree ├── right-align@0.1.3 -42 silly idealTree ├── rimraf@2.5.2 -42 silly idealTree ├── sax@1.2.1 -42 silly idealTree ├── selectn@0.9.6 -42 silly idealTree ├── semver-diff@2.1.0 -42 silly idealTree ├── semver@5.1.0 -42 silly idealTree ├── send@0.13.1 -42 silly idealTree ├── sentence-case@1.1.3 -42 silly idealTree ├── serve-favicon@2.3.0 -42 silly idealTree ├── serve-static@1.10.2 -42 silly idealTree ├── shelljs@0.3.0 -42 silly idealTree ├── should-equal@0.5.0 -42 silly idealTree ├── should-format@0.3.1 -42 silly idealTree ├── should-type@0.2.0 -42 silly idealTree ├── should@7.1.1 -42 silly idealTree ├── shush@1.0.0 -42 silly idealTree ├── sigmund@1.0.1 -42 silly idealTree ├── signal-exit@2.1.2 -42 silly idealTree ├── simple-fmt@0.1.0 -42 silly idealTree ├── simple-is@0.2.0 -42 silly idealTree ├── sliced@0.0.5 -42 silly idealTree ├── slide@1.1.6 -42 silly idealTree ├── smtp-connection@1.3.8 -42 silly idealTree ├── snake-case@1.1.2 -42 silly idealTree ├── sntp@1.0.9 -42 silly idealTree ├─┬ soap@0.11.4 -42 silly idealTree │ ├── debug@0.7.4 -42 silly idealTree │ ├── first-chunk-stream@0.1.0 -42 silly idealTree │ └── strip-bom@0.3.1 -42 silly idealTree ├─┬ socket.io-adapter@0.4.0 -42 silly idealTree │ └─┬ socket.io-parser@2.2.2 -42 silly idealTree │ └── debug@0.7.4 -42 silly idealTree ├─┬ socket.io-client@1.4.5 -42 silly idealTree │ └── component-emitter@1.2.0 -42 silly idealTree ├─┬ socket.io-parser@2.2.6 -42 silly idealTree │ └── json3@3.3.2 -42 silly idealTree ├── socket.io@1.4.5 -42 silly idealTree ├── source-map@0.5.3 -42 silly idealTree ├── spdx-correct@1.0.2 -42 silly idealTree ├── spdx-exceptions@1.0.4 -42 silly idealTree ├── spdx-expression-parse@1.0.2 -42 silly idealTree ├── spdx-license-ids@1.2.1 -42 silly idealTree ├─┬ split2@1.1.1 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ ├── readable-stream@2.0.6 -42 silly idealTree │ └── through2@2.0.1 -42 silly idealTree ├── split@0.3.3 -42 silly idealTree ├── sprintf-js@1.0.3 -42 silly idealTree ├── sshpk@1.7.4 -42 silly idealTree ├── stable@0.1.5 -42 silly idealTree ├── stack-trace@0.0.9 -42 silly idealTree ├── statuses@1.2.1 -42 silly idealTree ├── stream-combiner@0.0.4 -42 silly idealTree ├── streamsearch@0.1.2 -42 silly idealTree ├── string-length@1.0.1 -42 silly idealTree ├── string_decoder@0.10.31 -42 silly idealTree ├── stringmap@0.2.2 -42 silly idealTree ├── stringset@0.2.1 -42 silly idealTree ├── stringstream@0.0.5 -42 silly idealTree ├── strip-ansi@3.0.1 -42 silly idealTree ├── strip-bom@2.0.0 -42 silly idealTree ├── strip-indent@1.0.1 -42 silly idealTree ├── strip-json-comments@0.1.3 -42 silly idealTree ├── strong-data-uri@1.0.3 -42 silly idealTree ├─┬ superagent@1.8.3 -42 silly idealTree │ ├── component-emitter@1.2.1 -42 silly idealTree │ ├── form-data@1.0.0-rc3 -42 silly idealTree │ ├── qs@2.3.3 -42 silly idealTree │ └── readable-stream@1.0.27-1 -42 silly idealTree ├─┬ supertest-session@2.0.1 -42 silly idealTree │ └── object-assign@4.0.1 -42 silly idealTree ├── supertest@1.2.0 -42 silly idealTree ├── supports-color@2.0.0 -42 silly idealTree ├── swap-case@1.1.2 -42 silly idealTree ├─┬ swig@1.4.2 -42 silly idealTree │ ├── async@0.2.10 -42 silly idealTree │ ├── camelcase@1.2.1 -42 silly idealTree │ ├── source-map@0.1.34 -42 silly idealTree │ ├── uglify-js@2.4.24 -42 silly idealTree │ ├── wordwrap@0.0.2 -42 silly idealTree │ └── yargs@3.5.4 -42 silly idealTree ├─┬ tape@2.3.3 -42 silly idealTree │ └── deep-equal@0.1.2 -42 silly idealTree ├─┬ tar-pack@3.1.3 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ └── readable-stream@2.0.6 -42 silly idealTree ├── tar@2.2.1 -42 silly idealTree ├── throttleit@1.0.0 -42 silly idealTree ├─┬ through2-filter@2.0.0 -42 silly idealTree │ ├── isarray@1.0.0 -42 silly idealTree │ ├── readable-stream@2.0.6 -42 silly idealTree │ └── through2@2.0.1 -42 silly idealTree ├─┬ through2@0.6.5 -42 silly idealTree │ └── readable-stream@1.0.34 -42 silly idealTree ├── through@2.3.8 -42 silly idealTree ├── timed-out@2.0.0 -42 silly idealTree ├── timespan@2.3.0 -42 silly idealTree ├─┬ tiny-lr-fork@0.0.5 -42 silly idealTree │ ├── debug@0.7.4 -42 silly idealTree │ └── qs@0.5.6 -42 silly idealTree ├── title-case@1.1.2 -42 silly idealTree ├── to-array@0.1.4 -42 silly idealTree ├── touch@1.0.0 -42 silly idealTree ├── tough-cookie@2.2.2 -42 silly idealTree ├─┬ transformers@2.1.0 -42 silly idealTree │ ├── is-promise@1.0.1 -42 silly idealTree │ ├── optimist@0.3.7 -42 silly idealTree │ ├── promise@2.0.0 -42 silly idealTree │ ├── source-map@0.1.43 -42 silly idealTree │ └── uglify-js@2.2.5 -42 silly idealTree ├── trim-newlines@1.0.0 -42 silly idealTree ├── truncate@1.0.5 -42 silly idealTree ├── tryor@0.1.2 -42 silly idealTree ├── tunnel-agent@0.4.2 -42 silly idealTree ├── tweetnacl@0.14.3 -42 silly idealTree ├── type-check@0.3.2 -42 silly idealTree ├── type-is@1.6.12 -42 silly idealTree ├── typedarray@0.0.6 -42 silly idealTree ├─┬ uglify-js@2.6.2 -42 silly idealTree │ └── async@0.2.10 -42 silly idealTree ├── uglify-to-browserify@1.0.2 -42 silly idealTree ├── uid-number@0.0.6 -42 silly idealTree ├── uid-safe@2.0.0 -42 silly idealTree ├── uid2@0.0.3 -42 silly idealTree ├── uid@0.0.2 -42 silly idealTree ├── ultron@1.0.2 -42 silly idealTree ├── undefsafe@0.0.3 -42 silly idealTree ├── underscore.string@2.2.1 -42 silly idealTree ├── underscore@1.7.0 -42 silly idealTree ├── unique-stream@2.2.1 -42 silly idealTree ├── unpipe@1.0.0 -42 silly idealTree ├── unreachable-branch-transform@0.5.1 -42 silly idealTree ├── untildify@2.1.0 -42 silly idealTree ├─┬ update-notifier@0.5.0 -42 silly idealTree │ └── repeating@1.1.3 -42 silly idealTree ├── upper-case-first@1.1.2 -42 silly idealTree ├── upper-case@1.1.3 -42 silly idealTree ├── uri-path@1.0.0 -42 silly idealTree ├── useragent@2.1.9 -42 silly idealTree ├── utf8@2.1.0 -42 silly idealTree ├── util-deprecate@1.0.2 -42 silly idealTree ├─┬ utile@0.2.1 -42 silly idealTree │ └── async@0.2.10 -42 silly idealTree ├── utils-merge@1.0.0 -42 silly idealTree ├── uuid@2.0.2 -42 silly idealTree ├─┬ v8-debug@0.7.1 -42 silly idealTree │ └── nan@2.2.1 -42 silly idealTree ├─┬ v8-profiler@5.6.0 -42 silly idealTree │ └── nan@2.0.9 -42 silly idealTree ├── validate-npm-package-license@3.0.1 -42 silly idealTree ├── vary@1.1.0 -42 silly idealTree ├── verror@1.3.6 -42 silly idealTree ├─┬ vinyl-fs@1.0.0 -42 silly idealTree │ ├── graceful-fs@3.0.8 -42 silly idealTree │ ├── object-assign@2.1.1 -42 silly idealTree │ └── strip-bom@1.0.0 -42 silly idealTree ├─┬ vinyl@0.4.6 -42 silly idealTree │ └── clone@0.2.0 -42 silly idealTree ├── void-elements@2.0.1 -42 silly idealTree ├── which@1.0.9 -42 silly idealTree ├─┬ win-detect-browsers@1.0.2 -42 silly idealTree │ └── yargs@1.3.3 -42 silly idealTree ├── window-size@0.1.0 -42 silly idealTree ├─┬ winston@0.8.3 -42 silly idealTree │ └── async@0.2.10 -42 silly idealTree ├── with@4.0.3 -42 silly idealTree ├── wordwrap@0.0.3 -42 silly idealTree ├── wrappy@1.0.1 -42 silly idealTree ├── write-file-atomic@1.1.4 -42 silly idealTree ├── ws@1.1.0 -42 silly idealTree ├── x-default-browser@0.3.1 -42 silly idealTree ├── x-xss-protection@0.2.0 -42 silly idealTree ├── xdg-basedir@2.0.0 -42 silly idealTree ├─┬ xmlbuilder@4.0.0 -42 silly idealTree │ └── lodash@3.10.1 -42 silly idealTree ├── xmldom@0.1.22 -42 silly idealTree ├── xmlhttprequest-ssl@1.5.1 -42 silly idealTree ├── xtend@4.0.1 -42 silly idealTree ├── xtraverse@0.1.0 -42 silly idealTree ├── yallist@2.0.0 -42 silly idealTree ├─┬ yargs@3.10.0 -42 silly idealTree │ └── camelcase@1.2.1 -42 silly idealTree ├── yauzl@2.4.1 -42 silly idealTree └── yeast@0.1.2 -43 silly generateActionsToTake Starting -44 silly install generateActionsToTake -45 silly generateActionsToTake Finishing -46 silly diffTrees action count 0 -47 silly decomposeActions action count 0 -48 silly executeActions Starting -49 silly install executeActions -50 silly doSerial global-install 0 -51 silly doParallel fetch 0 -52 verbose correctMkdir /home/polydaic/.npm/_locks correctMkdir not in flight; initializing -53 verbose lock using /home/polydaic/.npm/_locks/staging-31c9eab886c56a2a.lock for /opt/deploy/source/node_modules/.staging -54 silly doParallel extract 0 -55 silly doParallel preinstall 0 -56 silly doReverseSerial remove 0 -57 silly doSerial move 0 -58 silly doSerial finalize 0 -59 silly doSerial build 0 -60 silly doSerial global-link 0 -61 silly doParallel update-linked 0 -62 silly doSerial install 0 -63 silly doSerial postinstall 0 -64 verbose unlock done using /home/polydaic/.npm/_locks/staging-31c9eab886c56a2a.lock for /opt/deploy/source/node_modules/.staging -65 silly executeActions Finishing -66 silly rollbackFailedOptional Starting -67 silly rollbackFailedOptional Finishing -68 silly runTopLevelLifecycles Starting -69 silly install runTopLevelLifecycles -70 silly preinstall TellForm@1.2.1 /opt/deploy/source/TellForm-a29e6dcc -71 info lifecycle TellForm@1.2.1~preinstall: TellForm@1.2.1 -72 silly lifecycle TellForm@1.2.1~preinstall: no script for preinstall, continuing -73 silly build TellForm@1.2.1 -74 info linkStuff TellForm@1.2.1 -75 silly linkStuff TellForm@1.2.1 has /opt/deploy as its parent node_modules -76 verbose linkBins TellForm@1.2.1 -77 verbose linkMans TellForm@1.2.1 -78 silly install TellForm@1.2.1 /opt/deploy/source/TellForm-a29e6dcc -79 info lifecycle TellForm@1.2.1~install: TellForm@1.2.1 -80 silly lifecycle TellForm@1.2.1~install: no script for install, continuing -81 silly postinstall TellForm@1.2.1 /opt/deploy/source/TellForm-a29e6dcc -82 info lifecycle TellForm@1.2.1~postinstall: TellForm@1.2.1 -83 verbose lifecycle TellForm@1.2.1~postinstall: unsafe-perm in lifecycle true -84 verbose lifecycle TellForm@1.2.1~postinstall: PATH: /usr/local/lib/node_modules/npm/bin/node-gyp-bin:/opt/deploy/source/node_modules/.bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/polydaic/.rvm/rubies/ruby-2.1.4/bin -85 verbose lifecycle TellForm@1.2.1~postinstall: CWD: /opt/deploy/source -86 silly lifecycle TellForm@1.2.1~postinstall: Args: [ '-c', -86 silly lifecycle 'bower install --config.interactive=false; grunt build' ] -87 verbose stack Error: write EPIPE -87 verbose stack at exports._errnoException (util.js:746:11) -87 verbose stack at WriteWrap.afterWrite (net.js:775:14) -88 verbose cwd /opt/deploy/source -89 error Linux 3.13.0-57-generic -90 error argv "node" "/usr/local/bin/npm" "install" -91 error node v0.12.7 -92 error npm v3.8.6 -93 error code EPIPE -94 error errno EPIPE -95 error syscall write -96 error write EPIPE -97 error If you need help, you may report this error at: -97 error -98 verbose exit [ 1, true ] diff --git a/package.json b/package.json index ad7a0eed..7e0ee0c2 100644 --- a/package.json +++ b/package.json @@ -25,13 +25,14 @@ "async": "^1.4.2", "body-parser": "~1.14.1", "bower": "~1.6.5", - "chalk": "~1.1.1", + "chalk": "^1.1.3", "compression": "~1.6.0", "connect-flash": "~0.1.1", "connect-mongo": "~0.8.2", "consolidate": "~0.13.1", "cookie-parser": "~1.4.0", "email-verification": "whitef0x0/node-email-verification", + "envfile": "^2.0.1", "express": "~4.13.3", "express-device": "~0.4.2", "express-session": "~1.12.1", @@ -53,6 +54,7 @@ "grunt-node-inspector": "~0.4.1", "grunt-nodemon": "~0.4.0", "helmet": "~0.14.0", + "inquirer": "^1.0.2", "jit-grunt": "^0.9.1", "lodash": "^2.4.1", "main-bower-files": "~2.9.0", @@ -83,6 +85,7 @@ "devDependencies": { "coveralls": "^2.11.4", "glob": "^7.0.3", + "grunt-execute": "^0.2.2", "grunt-mocha-istanbul": "^3.0.1", "grunt-mocha-test": "~0.12.1", "istanbul": "^0.4.0", diff --git a/public/dist/application.js b/public/dist/application.js index 424a37f4..85651997 100644 --- a/public/dist/application.js +++ b/public/dist/application.js @@ -522,10 +522,10 @@ angular.module('core').service('Menus', [ // Define the menus object this.menus = {}; - // A private function for rendering decision + // A private function for rendering decision var shouldRender = function(user) { if (user) { - if (!!~this.roles.indexOf('*')) { + if (~this.roles.indexOf('*')) { return true; } else { for (var userRoleIndex in user.roles) { @@ -681,6 +681,7 @@ angular.module('core').service('Menus', [ this.addMenu('bottombar', false, ['*']); } ]); + 'use strict'; // Configuring the Forms drop-down menus @@ -797,15 +798,15 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope }, { heading: 'Design', - route: 'viewForm.design', + route: 'viewForm.design' }, { heading: 'Configure', - route: 'viewForm.configure', + route: 'viewForm.configure' }, { heading: 'Analyze', - route: 'viewForm.analyze', + route: 'viewForm.analyze' } ]; @@ -818,8 +819,8 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope }); }; - /* - ** DeleteModal Functions + /* + ** DeleteModal Functions */ $scope.openDeleteModal = function(){ $scope.deleteModal = $uibModal.open({ @@ -851,15 +852,15 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope if($scope.deleteModal && $scope.deleteModal.opened){ $scope.deleteModal.close(); - + var form_id = $scope.myform._id; if(!form_id) throw new Error('Error - removeCurrentForm(): $scope.myform._id does not exist'); - + $http.delete('/forms/'+form_id) .success(function(data, status, headers){ console.log('form deleted successfully'); - $state.go('listForms', {}, {reload: true}); + $state.go('listForms', {}, {reload: true}); }).error(function(error){ console.log('ERROR: Form could not be deleted.'); @@ -875,7 +876,7 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope if(!updateImmediately){ continueUpdate = !$rootScope.saveInProgress; } - + //Update form **if we are not currently updating** or if **shouldUpdateNow flag is set** if(continueUpdate){ var err = null; @@ -890,12 +891,12 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope console.log('Error occured during form UPDATE.\n'); // console.log(response.data); err = response.data; - }).finally(function() { + }).finally(function() { // console.log('finished updating'); if(!updateImmediately){$rootScope.saveInProgress = false; } if( (typeof cb) === 'function'){ - cb(err); + return cb(err); } }); } @@ -904,6 +905,7 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope } ]); + 'use strict'; // Forms controller @@ -1237,7 +1239,7 @@ angular.module('forms').directive('configureFormDirective', ['$rootScope', '$htt console.log('Error occured during upload.\n'); console.log(resp.status); }, function (evt) { - var progressPercentage = parseInt(100.0 * evt.loaded / evt.total); + var progressPercentage = parseInt(100.0 * evt.loaded / evt.total, 10); $scope.log = 'progress: ' + progressPercentage + '% ' + evt.config.data.file.name + '\n' + $scope.log; @@ -1261,7 +1263,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField templateUrl: 'modules/forms/views/directiveViews/form/edit-form.client.view.html', restrict: 'E', scope: { - myform:'=', + myform:'=' }, controller: ["$scope", function($scope){ var field_ids = _($scope.myform.form_fields).pluck('_id'); @@ -1300,7 +1302,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField if( $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id) ){ currentFields = _(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id]); - } + } //Get all oscarhostFields that haven't been mapped to a formfield return _(oscarhostFields).difference(currentFields).value(); @@ -1314,7 +1316,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField $scope.dropzone = { handle: ' .handle', containment: '.dropzoneContainer', - cursor: 'grabbing', + cursor: 'grabbing' }; /* @@ -1328,9 +1330,9 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField var fieldTitle; for(var i = 0; i < $scope.addField.types.length; i++){ - if($scope.addField.types[i].name === fieldType){ + if($scope.addField.types[i].name === fieldType){ $scope.addField.types[i].lastAddedID++; - fieldTitle = $scope.addField.types[i].value+$scope.addField.types[i].lastAddedID; + fieldTitle = $scope.addField.types[i].value+$scope.addField.types[i].lastAddedID; break; } } @@ -1345,12 +1347,12 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField // console.log('\n\n---------\nAdded field CLIENT'); // console.log(newField); // newField._id = _.uniqueId(); - + // put newField into fields array if(modifyForm){ $scope.myform.form_fields.push(newField); } - return newField; + return newField; }; // Delete particular field on button click @@ -1364,7 +1366,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField $scope.myform.form_fields.splice(field_index, 1); }; $scope.duplicateField = function (field_index){ - var currField = _.cloneDeep($scope.myform.form_fields[field_index]); + var currField = _.cloneDeep($scope.myform.form_fields[field_index]); currField._id = 'cloned'+_.uniqueId(); currField.title += ' copy'; @@ -1413,8 +1415,8 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField $scope.addOption = function(field_index){ var currField = $scope.myform.form_fields[field_index]; console.log(field_index); - console.log(currField); - + console.log(currField); + if(currField.fieldType === 'checkbox' || currField.fieldType === 'dropdown' || currField.fieldType === 'radio'){ if(!currField.fieldOptions) $scope.myform.form_fields[field_index].fieldOptions = []; @@ -1430,7 +1432,7 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField var newOption = { 'option_id' : Math.floor(100000*Math.random()), 'option_title' : 'Option '+lastOptionID, - 'option_value' : 'Option ' +lastOptionID, + 'option_value' : 'Option ' +lastOptionID }; // put new option into fieldOptions array @@ -1463,8 +1465,8 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField } }; - }], - + }] + }; } ]); @@ -1520,7 +1522,7 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', defaultFormFields = _.cloneDeep($scope.myform.form_fields); // console.log('before textField2: '+data[0].form_fields[1].fieldValue); - + //Iterate through form's submissions for(var i=0; i= 0) { templateUrl = templateUrl+type+'.html'; } - return $templateCache.get('../public/'+templateUrl); }; @@ -1828,28 +1829,30 @@ angular.module('forms').directive('submitFormDirective', ['$http', 'TimeCounter' $scope.fieldBottom = elemBox.bottom; //console.log($scope.forms.myForm); + var field_id; + var field_index; if(!$scope.noscroll){ //Focus on submit button if( $scope.selected.index === $scope.myform.form_fields.length-1 && $scope.fieldBottom < 200){ - var field_index = $scope.selected.index+1; - var field_id = 'submit_field'; + field_index = $scope.selected.index+1; + field_id = 'submit_field'; $scope.setActiveField(field_id, field_index, false); } //Focus on field above submit button else if($scope.selected.index === $scope.myform.form_fields.length){ if($scope.fieldTop > 200){ - var field_index = $scope.selected.index-1; - var field_id = $scope.myform.form_fields[field_index]._id; + field_index = $scope.selected.index-1; + field_id = $scope.myform.form_fields[field_index]._id; $scope.setActiveField(field_id, field_index, false); } }else if( $scope.fieldBottom < 0){ - var field_index = $scope.selected.index+1; - var field_id = $scope.myform.form_fields[field_index]._id; + field_index = $scope.selected.index+1; + field_id = $scope.myform.form_fields[field_index]._id; $scope.setActiveField(field_id, field_index, false); }else if ( $scope.selected.index !== 0 && $scope.fieldTop > 0) { - var field_index = $scope.selected.index-1; - var field_id = $scope.myform.form_fields[field_index]._id; + field_index = $scope.selected.index-1; + field_id = $scope.myform.form_fields[field_index]._id; $scope.setActiveField(field_id, field_index, false); } //console.log('$scope.selected.index: '+$scope.selected.index); @@ -2546,7 +2549,7 @@ angular.module('users').factory('Auth', ['$window', $window.user = null; userState.isLoggedIn = false; service._currentUser = null; - }, + } }; return service; @@ -2617,7 +2620,7 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', ' return deferred.promise; }, - logout: function() { + logout: function() { var deferred = $q.defer(); $http.get('/auth/signout').success(function(response) { @@ -2628,7 +2631,7 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', ' return deferred.promise; }, - signup: function(credentials) { + signup: function(credentials) { var deferred = $q.defer(); $http.post('/auth/signup', credentials).success(function(response) { @@ -2641,7 +2644,7 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', ' return deferred.promise; }, - resendVerifyEmail: function(_email) { + resendVerifyEmail: function(_email) { var deferred = $q.defer(); $http.post('/auth/verify', {email: _email}).success(function(response) { @@ -2653,7 +2656,7 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', ' return deferred.promise; }, - validateVerifyToken: function(token) { + validateVerifyToken: function(token) { //DAVID: TODO: The valid length of a token should somehow be linked to server config values //DAVID: TODO: SEMI-URGENT: Should we even be doing this? @@ -2695,12 +2698,12 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', ' }); return deferred.promise; - }, + } }; return userService; - + } ]); diff --git a/public/dist/application.min.js b/public/dist/application.min.js index 64cbd8c0..18990061 100644 --- a/public/dist/application.min.js +++ b/public/dist/application.min.js @@ -1,4 +1,4 @@ function removeDateFieldsFunc(o){function eachObject(v,k){"lastModified"!==k&&"created"!==k||delete clone[i][k]}for(var clone=_.clone(o),i=0;i'),$templateCache.put("../public/modules/core/views/home.client.view.html",'

Craft beautiful forms in seconds.

Create your next ______.

Tell a story with a form.

'),$templateCache.put("../public/modules/forms/views/admin-form.client.view.html",'
'),$templateCache.put("../public/modules/forms/views/list-forms.client.view.html",'

Create a new form
Name
Language

'),$templateCache.put("../public/modules/forms/views/submit-form.client.view.html","
"),$templateCache.put("../public/modules/forms/views/adminTabs/analyze.html",""),$templateCache.put("../public/modules/forms/views/adminTabs/configure.html",""),$templateCache.put("../public/modules/forms/views/adminTabs/create.html",""),$templateCache.put("../public/modules/forms/views/adminTabs/design.html",'
Background Color
Question Text Color
Answer Text Color
Button Background Color
Button Text Color
'),$templateCache.put("../public/modules/forms/views/directiveViews/cgBusy/update-form-message-TypeA.html",'
{{$message}}
'),$templateCache.put("../public/modules/forms/views/directiveViews/cgBusy/update-form-message-TypeB.html",'
{{$message}}
'),$templateCache.put("../public/modules/forms/views/directiveViews/entryPage/startPage.html",'

{{pageData.introTitle}}

{{pageData.introParagraph}}

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/date.html",'

{{field.title}} optional

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/dropdown.html",'
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/file.html",'
{{field.title}} (* required)
{{field.file.originalname}}
Upload your File
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/hidden.html",''),$templateCache.put("../public/modules/forms/views/directiveViews/field/legal.html",'
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/radio.html",'

{{field.title}} optional


'),$templateCache.put("../public/modules/forms/views/directiveViews/field/rating.html",'

{{field.title}} optional

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/statement.html",'

{{field.title}}

{{field.description}}


'),$templateCache.put("../public/modules/forms/views/directiveViews/field/textarea.html",'

{{field.title}} optional

press ENTER
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/textfield.html",'

{{field.title}} (optional)

press ENTER
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/yes_no.html",'

{{field.title}} *(required)

{{field.description}}


'),$templateCache.put("../public/modules/forms/views/directiveViews/form/configure-form.client.view.html",'
Save Submissions as PDFs?
Upload Your PDF Template
{{myform.pdf.name}}
Upload your PDF
Autogenerate Form?
Use Oscarhost API?
Oscarhost API Username
Oscarhost API Password
Oscarhost API URL
Oscarhost API Update Type
Form Name
Form Status
Language
* required
Display Form Footer?
Display Start Page?
'), $templateCache.put("../public/modules/forms/views/directiveViews/form/edit-form.client.view.html",'

Edit Start Page


Intro Title:
Intro Paragraph:
\n
\n\n

\n
\n
Options:
\n
\n
\n \n\n \n \n \n
\n
\n \n
\n
\n
\n\n

\n\n
\n
Required:
\n
\n \n\n \n
\n
\n\n
\n
Disabled:
\n
\n \n\n \n
\n
\n\n
\n \n\n
\n
\n

\n Click on Fields to add them here\n

\n
\n
\n\n
\n \n
\n\n \n \n\n \n
\n
\n\n'),$templateCache.put("../public/modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html",'
#{{value.title}}OscarEMR User ProfilePercentage CompleteTime ElapsedDeviceLocationIP AddressDate Submitted (UTC)Generated PDF
{{$index+1}}{{field.fieldValue}}User Profile #{{row.oscarDemoNum}}{{row.percentageComplete}}%{{row.timeElapsed}}{{row.device.name}}, {{row.device.type}}{{row.geoLocation.city}}, {{row.geoLocation.country}}{{row.ipAddr}}{{row.created | date:\'yyyy-MM-dd HH:mm:ss\'}}Generated PDF
'),$templateCache.put("../public/modules/forms/views/directiveViews/form/submit-form.client.view.html",'
press ENTER
'),$templateCache.put("../public/modules/users/views/authentication/access-denied.client.view.html",'

You need to be logged in to access this page

Login
'),$templateCache.put("../public/modules/users/views/authentication/signin.client.view.html",'

Sign into your account

'),$templateCache.put("../public/modules/users/views/authentication/signup-success.client.view.html",''),$templateCache.put("../public/modules/users/views/authentication/signup.client.view.html",''),$templateCache.put("../public/modules/users/views/password/forgot-password.client.view.html",'

Restore your password

Enter your account email.

'),$templateCache.put("../public/modules/users/views/password/reset-password-invalid.client.view.html",'

Password reset is invalid

Ask for a new password reset
'),$templateCache.put("../public/modules/users/views/password/reset-password-success.client.view.html",'

Password successfully reset

Continue to home page
'),$templateCache.put("../public/modules/users/views/password/reset-password.client.view.html",'

Reset your password

'),$templateCache.put("../public/modules/users/views/settings/change-password.client.view.html",'

Change your password

'),$templateCache.put("../public/modules/users/views/settings/edit-profile.client.view.html",'

Edit your profile

'), -$templateCache.put("../public/modules/users/views/settings/social-accounts.client.view.html",'

Connected social accounts:

Connect other social accounts:

'),$templateCache.put("../public/modules/users/views/verify/resend-verify-email.client.view.html",'

Resend your account verification email

Enter your account email.

{{error}}

Verification Email has been Sent

A verification email has been sent to {{username}}.
But your account is still not activated yet

Check your email and click on the activation link to activate your account. If you have any questions drop us a line at hi@TellForm.com

'),$templateCache.put("../public/modules/users/views/verify/verify-account.client.view.html",'

Account successfuly activated

Continue to login page

Verification link is invalid or has expired

Resend your verification email Signin to your account
')}]);var ApplicationConfiguration=function(){var applicationModuleName="NodeForm",applicationModuleVendorDependencies=["duScroll","ui.select","cgBusy","ngSanitize","vButton","ngResource","NodeForm.templates","ui.router","ui.bootstrap","ui.utils"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","$state","$stateParams",function($rootScope,Auth,$state,$stateParams){$rootScope.$state=$state,$rootScope.$stateParams=$stateParams,$rootScope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState){$state.previous=fromState,"home"===toState.name||"signin"===toState.name||"resendVerifyEmail"===toState.name||"verify"===toState.name||"signup"===toState.name||"signup-success"===toState.name?Auth.isAuthenticated()&&(event.preventDefault(),$state.go("listForms")):"access_denied"===toState.name||Auth.isAuthenticated()||"submitForm"===toState.name||(event.preventDefault(),$state.go("listForms"))})}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","User","Authorizer","$state","$stateParams",function($rootScope,Auth,User,Authorizer,$state,$stateParams){$rootScope.$on("$stateChangeStart",function(event,next){var authenticator,permissions,user;permissions=next&&next.data&&next.data.permissions?next.data.permissions:null,Auth.ensureHasCurrentUser(User),user=Auth.currentUser,user&&(authenticator=new Authorizer(user),null!=permissions&&(authenticator.canAccess(permissions)||(event.preventDefault(),$state.go("access_denied"))))})}]),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.router.tabs","colorpicker.module","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/forms")}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User",function($rootScope,$scope,Menus,$state,Auth,User){$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["english","french","spanish"],$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("listForms")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").controller("HomeController",["$rootScope","$scope","User","$state",function($rootScope,$scope,User,$state){$scope=$rootScope}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field&&"statement"!==field.fieldType&&"rating"!==field.fieldType?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",["$delegate",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate}])}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/views/list-forms.client.view.html"}).state("submitForm",{url:"/forms/:formId",templateUrl:"modules/forms/views/submit-form.client.view.html",data:{hideNav:!0},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"SubmitFormController",controllerAs:"ctrl"}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/views/admin-form.client.view.html",data:{permissions:["editForm"]},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"AdminFormController"}).state("viewForm.configure",{url:"/configure",templateUrl:"modules/forms/views/adminTabs/configure.html"}).state("viewForm.design",{url:"/design",templateUrl:"modules/forms/views/adminTabs/design.html"}).state("viewForm.analyze",{url:"/analyze",templateUrl:"modules/forms/views/adminTabs/analyze.html"}).state("viewForm.create",{url:"/create",templateUrl:"modules/forms/views/adminTabs/create.html"})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$uibModal","myForm",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$uibModal,myForm){$scope=$rootScope,$scope.animationsEnabled=!0,$scope.myform=myForm,$rootScope.saveInProgress=!1,CurrentForm.setForm($scope.myform),$scope.tabData=[{heading:"Create",route:"viewForm.create"},{heading:"Design",route:"viewForm.design"},{heading:"Configure",route:"viewForm.configure"},{heading:"Analyze",route:"viewForm.analyze"}],$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.openDeleteModal=function(){$scope.deleteModal=$uibModal.open({animation:$scope.animationsEnabled,templateUrl:"myModalContent.html",controller:"AdminFormController",resolve:{myForm:function(){return $scope.myform}}}),$scope.deleteModal.result.then(function(selectedItem){$scope.selected=selectedItem},function(){console.log("Modal dismissed at: "+new Date)})},$scope.cancelDeleteModal=function(){$scope.deleteModal&&$scope.deleteModal.dismiss("cancel")},$scope.removeCurrentForm=function(){if($scope.deleteModal&&$scope.deleteModal.opened){$scope.deleteModal.close();var form_id=$scope.myform._id;if(!form_id)throw new Error("Error - removeCurrentForm(): $scope.myform._id does not exist");$http["delete"]("/forms/"+form_id).success(function(data,status,headers){console.log("form deleted successfully"),$state.go("listForms",{},{reload:!0})}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}},$scope.update=$rootScope.update=function(updateImmediately,cb){var continueUpdate=!0;if(updateImmediately||(continueUpdate=!$rootScope.saveInProgress),continueUpdate){var err=null;updateImmediately||($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),err=response.data})["finally"](function(){updateImmediately||($rootScope.saveInProgress=!1),"function"==typeof cb&&cb(err)})}}}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$scope.forms={},$scope.showCreateModal=!1,$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$scope.showCreateModal||($scope.showCreateModal=!0)},$scope.closeCreateModal=function(){$scope.showCreateModal&&($scope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicateForm=function(form_index){var form=_.cloneDeep($scope.myforms[form_index]);delete form._id,$http.post("/forms",{form:form}).success(function(data,status,headers){$scope.myforms.splice(form_index+1,0,data)}).error(function(errorResponse){console.error(errorResponse),null===errorResponse&&($scope.error=errorResponse.data.message)})},$scope.createNewForm=function(){var form={};form.title=$scope.forms.createForm.title.$modelValue,form.language=$scope.forms.createForm.language.$modelValue,$scope.forms.createForm.$valid&&$scope.forms.createForm.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("new form created"),$scope.goToWithId("viewForm.create",data._id+"")}).error(function(errorResponse){console.error(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeForm=function(form_index){if(form_index>=$scope.myforms.length||0>form_index)throw new Error("Error: form_index in removeForm() must be between 0 and "+$scope.myforms.length-1);$http["delete"]("/forms/"+$scope.myforms[form_index]._id).success(function(data,status,headers){console.log("form deleted successfully"),$scope.myforms.splice(form_index,1)}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}}]),angular.module("forms").controller("SubmitFormController",["$scope","$rootScope","$state","myForm","Auth",function($scope,$rootScope,$state,myForm,Auth){$scope.authentication=Auth,$scope.myform=myForm,$scope.myform.isLive?$scope.hideNav=$rootScope.hideNav=!0:$scope.authentication.isAuthenticated()?$scope.hideNav=$rootScope.hideNav=!1:($scope.hideNav=$rootScope.hideNav=!0,$state.go("access_denied"))}]),_.mixin({removeDateFields:removeDateFieldsFunc}),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFields Started",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFields Finished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!0,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine(),$formCtrl.$setUntouched())})};$scope.$watch(function(newValue,oldValue){console.log("introParagraphStartPage.$dirty: "+$scope.editForm.introParagraphStartPage.$dirty),console.log("introParagraphStartPage.$touched: "+$scope.editForm.introParagraphStartPage.$touched),$rootScope.finishedRender&&$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&(console.log("Form saving started"),debounceSave(),console.log("introParagraphStartPage.$dirty AFTER: "+$scope.editForm.introParagraphStartPage.$dirty))}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){newValue=angular.copy(newValue),oldValue=angular.copy(oldValue),newValue.form_fields=_.removeDateFields(newValue.form_fields),oldValue.form_fields=_.removeDateFields(oldValue.form_fields);var changedFields=!_.isEqual(oldValue.form_fields,newValue.form_fields)||!_.isEqual(oldValue.startPage,newValue.startPage),changedFieldMap=!1;oldValue.hasOwnProperty("plugins.oscarhost.settings.fieldMap")&&(changedFieldMap=!!oldValue.plugins.oscarhost.settings.fieldMap&&!_.isEqual(oldValue.plugins.oscarhost.settings.fieldMap,newValue.plugins.oscarhost.settings.fieldMap)),(newValue||oldValue)&&oldValue&&(0===oldValue.form_fields.length&&($rootScope.finishedRender=!0),$rootScope.finishedRender&&(changedFields&&!$formCtrl.$dirty||changedFieldMap)&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","CurrentForm",function($rootScope,$http,Upload,CurrentForm){return{templateUrl:"modules/forms/views/directiveViews/form/configure-form.client.view.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:["$scope",function($scope){console.log($scope.myform),CurrentForm.getForm().plugins?CurrentForm.getForm().plugins.oscarhost.baseUrl&&($scope.oscarhostAPI=!0):$scope.oscarhostAPI=!1,$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages,this._current_upload=null,$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update,this._unbindedPdfFields=$scope.pdfFields,$scope.cancelUpload=function(){this._current_upload.abort(),$scope.pdfLoading=!1,$scope.removePDF()},$scope.removePDF=function(){$scope.myform.pdf=null,$scope.myform.isGenerated=!1,$scope.myform.autofillPDFs=!1,console.log("form.pdf: "+$scope.myform.pdf+" REMOVED")},$scope.uploadPDF=function(file){file&&(console.log(file),Upload.upload({url:"/upload/pdf",data:{user:$scope.user,file:file}}).then(function(resp){var data=resp.data;$scope.log="file "+data.originalname+" uploaded as "+data.filename+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()},function(resp){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(resp.status)},function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total);$scope.log="progress: "+progressPercentage+"% "+evt.config.data.file.name+"\n"+$scope.log,console.log($scope.log),$scope.pdfLoading=!0}))}}]}}]),angular.module("forms").directive("editFormDirective",["$rootScope","FormFields",function($rootScope,FormFields){return{templateUrl:"modules/forms/views/directiveViews/form/edit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:["$scope",function($scope){for(var field_ids=_($scope.myform.form_fields).pluck("_id"),i=0;i0){$scope.myform.plugins.oscarhost.settings.fieldMap||($scope.myform.plugins.oscarhost.settings.fieldMap={});var oscarhostFields=$scope.myform.plugins.oscarhost.settings.validFields,currentFields=_($scope.myform.plugins.oscarhost.settings.fieldMap).invert().keys().value();return $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id)&&(currentFields=_(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id])),_(oscarhostFields).difference(currentFields).value()}return[]},$scope.dropzone={handle:" .handle",containment:".dropzoneContainer",cursor:"grabbing"},$scope.addNewField=function(modifyForm,fieldType){$scope.addField.lastAddedID++;for(var fieldTitle,i=0;i<$scope.addField.types.length;i++)if($scope.addField.types[i].name===fieldType){$scope.addField.types[i].lastAddedID++,fieldTitle=$scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;break}var newField={title:fieldTitle,fieldType:fieldType,fieldValue:"",required:!0,disabled:!1,deletePreserved:!1};return modifyForm&&$scope.myform.form_fields.push(newField),newField},$scope.deleteField=function(field_index){var currFieldId=$scope.myform.form_fields[field_index]._id;$scope.myform.hasOwnProperty("plugins.oscarhost.baseUrl")&&delete $scope.myform.plugins.oscarhost.settings.fieldMap[currFieldId],$scope.myform.form_fields.splice(field_index,1)},$scope.duplicateField=function(field_index){var currField=_.cloneDeep($scope.myform.form_fields[field_index]);currField._id="cloned"+_.uniqueId(),currField.title+=" copy",$scope.myform.form_fields.splice(field_index+1,0,currField)},$scope.addButton=function(){var newButton={};newButton.bgColor="#ddd",newButton.color="#ffffff",newButton.text="Button",newButton._id=Math.floor(1e5*Math.random()),$scope.myform.startPage.buttons.push(newButton)},$scope.deleteButton=function(button){for(var currID,i=0;i<$scope.myform.startPage.buttons.length;i++)if(currID=$scope.myform.startPage.buttons[i]._id,console.log(currID),currID===button._id){$scope.myform.startPage.buttons.splice(i,1);break}},$scope.addOption=function(field_index){var currField=$scope.myform.form_fields[field_index];if(console.log(field_index),console.log(currField),"checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType){currField.fieldOptions||($scope.myform.form_fields[field_index].fieldOptions=[]);var lastOptionID=0;currField.fieldOptions[currField.fieldOptions.length-1]&&(lastOptionID=currField.fieldOptions[currField.fieldOptions.length-1].option_id);var newOption={option_id:Math.floor(1e5*Math.random()),option_title:"Option "+lastOptionID,option_value:"Option "+lastOptionID};$scope.myform.form_fields[field_index].fieldOptions.push(newOption)}},$scope.deleteOption=function(field_index,option){var currField=$scope.myform.form_fields[field_index];if("checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType)for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:["$scope",function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}]}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope","$templateCache",function($http,$compile,$rootScope,$templateCache){var getTemplateUrl=function(fieldType){var type=fieldType,templateUrl="modules/forms/views/directiveViews/field/",supported_fields=["textfield","textarea","date","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0&&(templateUrl=templateUrl+type+".html"),$templateCache.get("../public/"+templateUrl)};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&",design:"=",index:"=",forms:"="},link:function(scope,element){$rootScope.chooseDefaultOption=scope.chooseDefaultOption=function(type){"yes_no"===type?scope.field.fieldValue="true":"rating"===type?scope.field.fieldValue=0:"radio"===scope.field.fieldType?(console.log(scope.field),scope.field.fieldValue=scope.field.fieldOptions[0].option_value,console.log(scope.field.fieldValue)):"legal"===type&&(scope.field.fieldValue="true",$rootScope.nextField())},scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType&&(scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0});var fieldType=scope.field.fieldType;if("number"===scope.field.fieldType||"textfield"===scope.field.fieldType||"email"===scope.field.fieldType||"link"===scope.field.fieldType){switch(scope.field.fieldType){case"textfield":scope.field.input_type="text";break;case"email":scope.field.input_type="email",scope.field.placeholder="joesmith@example.com";break;case"number":scope.field.input_type="text",scope.field.validateRegex=/^\d+$/;break;default:scope.field.input_type="url",scope.field.placeholder="http://example.com"}fieldType="textfield"}var template=getTemplateUrl(fieldType);element.html(template).show(),$compile(element.contents())(scope)}}}]),angular.module("forms").directive("onEnterKey",["$rootScope",function($rootScope){return{restrict:"A",link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode;13===keyCode&&($rootScope.$apply(function(){$rootScope.$eval($attrs.onEnterKey)}),event.preventDefault())})}}}]),angular.module("forms").directive("onFinishRender",["$rootScope","$timeout",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")||element.attr("data-ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$first&&!scope.$last?scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Started")}):scope.$last&&scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Finished")})}}}}]),angular.module("forms").directive("submitFormDirective",["$http","TimeCounter","$filter","$rootScope","Auth",function($http,TimeCounter,$filter,$rootScope,Auth){return{templateUrl:"modules/forms/views/directiveViews/form/submit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:["$document","$window","$scope",function($document,$window,$scope){ -$scope.authentication=$rootScope.authentication,$scope.noscroll=!1,$scope.forms={},$scope.form_fields_count=$scope.myform.visible_form_fields.filter(function(field){return"statement"!==field.fieldType&&"rating"!==field.fieldType}).length,$scope.reloadForm=function(){$scope.myform.submitted=!1,$scope.myform.form_fields=_.chain($scope.myform.visible_form_fields).map(function(field){return field.fieldValue="",field}).value(),$scope.loading=!1,$scope.error="",$scope.selected={_id:"",index:0},$scope.setActiveField($scope.myform.visible_form_fields[0]._id,0,!1),TimeCounter.restartClock()},$window.onscroll=function(){$scope.scrollPos=document.body.scrollTop||document.documentElement.scrollTop||0;var elemBox=document.getElementsByClassName("activeField")[0].getBoundingClientRect();if($scope.fieldTop=elemBox.top,$scope.fieldBottom=elemBox.bottom,!$scope.noscroll){if($scope.selected.index===$scope.myform.form_fields.length-1&&$scope.fieldBottom<200){var field_index=$scope.selected.index+1,field_id="submit_field";$scope.setActiveField(field_id,field_index,!1)}else if($scope.selected.index===$scope.myform.form_fields.length){if($scope.fieldTop>200){var field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id;$scope.setActiveField(field_id,field_index,!1)}}else if($scope.fieldBottom<0){var field_index=$scope.selected.index+1,field_id=$scope.myform.form_fields[field_index]._id;$scope.setActiveField(field_id,field_index,!1)}else if(0!==$scope.selected.index&&$scope.fieldTop>0){var field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id;$scope.setActiveField(field_id,field_index,!1)}$scope.$apply()}},$scope.setActiveField=$rootScope.setActiveField=function(field_id,field_index,animateScroll){null!==$scope.selected&&$scope.selected._id!==field_id&&($scope.selected._id=field_id,$scope.selected.index=field_index,animateScroll&&($scope.noscroll=!0,setTimeout(function(){$document.scrollToElement(angular.element(".activeField"),-10,200).then(function(){$scope.noscroll=!1,document.querySelectorAll(".activeField .focusOn")[0].focus()})},20)))},$rootScope.nextField=$scope.nextField=function(){if($scope.selected.index<$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id=$scope.myform.form_fields[selected_index]._id;$rootScope.setActiveField(selected_id,selected_index,!0)}else if($scope.selected.index===$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id="submit_field";$rootScope.setActiveField(selected_id,selected_index,!0)}},$rootScope.prevField=$scope.prevField=function(){if($scope.selected.index>0){var selected_index=$scope.selected.index-1,selected_id=$scope.myform.form_fields[selected_index]._id;$scope.setActiveField(selected_id,selected_index,!0)}},$scope.exitStartPage=function(){$scope.myform.startPage.showStart=!1,$scope.myform.form_fields.length>0&&($scope.selected._id=$scope.myform.form_fields[0]._id)},$scope.submitForm=function(){var _timeElapsed=TimeCounter.stopClock();$scope.loading=!0;var form=_.cloneDeep($scope.myform);form.timeElapsed=_timeElapsed,form.percentageComplete=$filter("formValidity")($scope.myform)/$scope.myform.visible_form_fields.length*100,delete form.visible_form_fields,setTimeout(function(){$scope.submitPromise=$http.post("/forms/"+$scope.myform._id,form).success(function(data,status,headers){$scope.myform.submitted=!0,$scope.loading=!1}).error(function(error){$scope.loading=!1,$scope.error=error.message})},500)},$scope.reloadForm()}]}}]),angular.module("forms").service("CurrentForm",function(){var _form={};this.getForm=function(){return _form},this.setForm=function(form){_form=form}}),angular.module("forms").service("FormFields",[function(){this.types=[{name:"textfield",value:"Short Text"},{name:"email",value:"Email"},{name:"radio",value:"Multiple Choice"},{name:"dropdown",value:"Dropdown"},{name:"date",value:"Date"},{name:"textarea",value:"Paragraph Text"},{name:"yes_no",value:"Yes/No"},{name:"legal",value:"Legal"},{name:"rating",value:"Rating"},{name:"link",value:"Link"},{name:"number",value:"Numbers"},{name:"statement",value:"Statement"}]}]),angular.module("forms").factory("Forms",["$resource",function($resource){return $resource("/forms/:formId",{formId:"@_id"},{query:{method:"GET",isArray:!0},get:{method:"GET",transformResponse:function(data,header){var form=angular.fromJson(data);return form.visible_form_fields=_.filter(form.form_fields,function(field){return field.deletePreserved===!1}),form}},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").factory("Submissions",["$resource",function($resource){return $resource("forms/:formID/submissions/:submissionId",{submissionId:"@_id",formId:"@_id"},{query:{method:"GET",isArray:!0},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").service("TimeCounter",[function(){var _startTime,_endTime,that=this;this.timeSpent=0,this.restartClock=function(){_startTime=Date.now(),_endTime=_startTime},this.stopClock=function(){return _startTime?(_endTime=Date.now(),that.timeSpent=Math.abs(_endTime.valueOf()-_startTime.valueOf())/1e3,that.timeSpent):new Error("Clock has not been started")},this.clockStarted=function(){return!!this._startTime}}]),angular.module("users").config(["$httpProvider",function($httpProvider){$httpProvider.interceptors.push(["$q","$location",function($q,$location){return{responseError:function(response){return"/users/me"!==$location.path()&&response.config&&"/users/me"!==response.config.url&&(console.log("intercepted rejection of ",response.config.url,response.status),401===response.status?($location.nextAfterLogin=$location.path(),$location.path("/signin")):403===response.status&&$location.path("/access_denied")),$q.reject(response)}}}])}]),angular.module("users").config(["$stateProvider",function($stateProvider){var checkLoggedin=function($q,$timeout,$state,User,Auth){var deferred=$q.defer();return Auth.currentUser&&Auth.currentUser.email?$timeout(deferred.resolve):Auth.currentUser=User.getCurrent(function(){Auth.login(),$timeout(deferred.resolve())},function(){Auth.logout(),$timeout(deferred.reject()),$state.go("sigin",{reload:!0})}),deferred.promise};checkLoggedin.$inject=["$q","$timeout","$state","User","Auth"],$stateProvider.state("profile",{resolve:{loggedin:checkLoggedin},url:"/settings/profile",templateUrl:"modules/users/views/settings/edit-profile.client.view.html"}).state("password",{resolve:{loggedin:checkLoggedin},url:"/settings/password",templateUrl:"modules/users/views/settings/change-password.client.view.html"}).state("accounts",{resolve:{loggedin:checkLoggedin},url:"/settings/accounts",templateUrl:"modules/users/views/settings/social-accounts.client.view.html"}).state("signup",{url:"/signup",templateUrl:"modules/users/views/authentication/signup.client.view.html"}).state("signup-success",{url:"/signup-success",templateUrl:"modules/users/views/authentication/signup-success.client.view.html"}).state("signin",{url:"/signin",templateUrl:"modules/users/views/authentication/signin.client.view.html"}).state("access_denied",{url:"/access_denied",templateUrl:"modules/users/views/authentication/access-denied.client.view.html"}).state("resendVerifyEmail",{url:"/verify",templateUrl:"modules/users/views/verify/resend-verify-email.client.view.html"}).state("verify",{url:"/verify/:token",templateUrl:"modules/users/views/verify/verify-account.client.view.html"}).state("forgot",{url:"/password/forgot",templateUrl:"modules/users/views/password/forgot-password.client.view.html"}).state("reset-invalid",{url:"/password/reset/invalid",templateUrl:"modules/users/views/password/reset-password-invalid.client.view.html"}).state("reset-success",{url:"/password/reset/success",templateUrl:"modules/users/views/password/reset-password-success.client.view.html"}).state("reset",{url:"/password/reset/:token",templateUrl:"modules/users/views/password/reset-password.client.view.html"})}]),angular.module("users").controller("AuthenticationController",["$scope","$location","$state","$rootScope","User","Auth",function($scope,$location,$state,$rootScope,User,Auth){$scope=$rootScope,$scope.credentials={},$scope.error="",$scope.signin=function(){$scope.credentials.email=$scope.credentials.username,User.login($scope.credentials).then(function(response){Auth.login(response),$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),"home"!==$state.previous.name&&"verify"!==$state.previous.name&&""!==$state.previous.name?$state.go($state.previous.name):$state.go("listForms")},function(error){$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user,$scope.error=error,console.log("loginError: "+error)})},$scope.signup=function(){console.log($scope.credentials),User.signup($scope.credentials).then(function(response){console.log("signup-success"),$state.go("signup-success")},function(error){console.log("Error: "),console.log(error),error?($scope.error=error,console.log(error)):console.log("No response received")})}}]),angular.module("users").controller("PasswordController",["$scope","$stateParams","$state","User",function($scope,$stateParams,$state,User){$scope.error="",$scope.askForPasswordReset=function(){User.askForPasswordReset($scope.credentials).then(function(response){$scope.success=response.message,$scope.credentials=null},function(error){$scope.error=error,$scope.credentials=null})},$scope.resetUserPassword=function(){$scope.success=$scope.error=null,User.resetPassword($scope.passwordDetails,$stateParams.token).then(function(response){$scope.success=response.message,$scope.passwordDetails=null,$state.go("reset-success")},function(error){$scope.error=error.message||error,$scope.passwordDetails=null})}}]),angular.module("users").controller("SettingsController",["$scope","$rootScope","$http","$state","Users",function($scope,$rootScope,$http,$state,Users){$scope.user=$rootScope.user,$scope.hasConnectedAdditionalSocialAccounts=function(provider){for(var i in $scope.user.additionalProvidersData)return!0;return!1},$scope.isConnectedSocialAccount=function(provider){return $scope.user.provider===provider||$scope.user.additionalProvidersData&&$scope.user.additionalProvidersData[provider]},$scope.removeUserSocialAccount=function(provider){$scope.success=$scope.error=null,$http["delete"]("/users/accounts",{params:{provider:provider}}).success(function(response){$scope.success=!0,$scope.user=response}).error(function(response){$scope.error=response.message})},$scope.updateUserProfile=function(isValid){if(isValid){$scope.success=$scope.error=null;var user=new Users($scope.user);user.$update(function(response){$scope.success=!0,$scope.user=response},function(response){$scope.error=response.data.message})}else $scope.submitted=!0},$scope.changeUserPassword=function(){$scope.success=$scope.error=null,$http.post("/users/password",$scope.passwordDetails).success(function(response){$scope.success=!0,$scope.passwordDetails=null}).error(function(response){$scope.error=response.message})}}]),angular.module("users").controller("VerifyController",["$scope","$state","$rootScope","User","Auth","$stateParams",function($scope,$state,$rootScope,User,Auth,$stateParams){$scope.isResetSent=!1,$scope.credentials={},$scope.error="",$scope.resendVerifyEmail=function(){User.resendVerifyEmail($scope.credentials.email).then(function(response){console.log(response),$scope.success=response.message,$scope.credentials=null,$scope.isResetSent=!0},function(error){$scope.error=error,$scope.credentials.email=null,$scope.isResetSent=!1})},$scope.validateVerifyToken=function(){$stateParams.token&&(console.log($stateParams.token),User.validateVerifyToken($stateParams.token).then(function(response){console.log("Success: "+response.message),$scope.success=response.message,$scope.isResetSent=!0,$scope.credentials.email=null},function(error){console.log("Error: "+error.message),$scope.isResetSent=!1,$scope.error=error,$scope.credentials.email=null}))}}]),angular.module("users").factory("Auth",["$window",function($window){var userState={isLoggedIn:!1},service={_currentUser:null,get currentUser(){return this._currentUser},ensureHasCurrentUser:function(User){return service._currentUser&&service._currentUser.username?service._currentUser:$window.user?(service._currentUser=$window.user,service._currentUser):void User.getCurrent().then(function(user){return service._currentUser=user,userState.isLoggedIn=!0,$window.user=service._currentUser,service._currentUser},function(response){return userState.isLoggedIn=!1,service._currentUser=null,$window.user=null,console.log("User.getCurrent() err",response),null})},isAuthenticated:function(){return!!service._currentUser},getUserState:function(){return userState},login:function(new_user){userState.isLoggedIn=!0,service._currentUser=new_user},logout:function(){$window.user=null,userState.isLoggedIn=!1,service._currentUser=null}};return service}]),angular.module("users").service("Authorizer",["APP_PERMISSIONS","USER_ROLES",function(APP_PERMISSIONS,USER_ROLES){return function(user){return{canAccess:function(permissions){var i,len,permission;for(angular.isArray(permissions)||(permissions=[permissions]),i=0,len=permissions.length;len>i;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}]),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var validTokenRe=/^([A-Za-z0-9]{48})$/g;if(!validTokenRe.test(token))throw new Error("Error token: "+token+" is not a valid verification token");var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file +$templateCache.put("../public/modules/users/views/settings/social-accounts.client.view.html",'

Connected social accounts:

Connect other social accounts:

'),$templateCache.put("../public/modules/users/views/verify/resend-verify-email.client.view.html",'

Resend your account verification email

Enter your account email.

{{error}}

Verification Email has been Sent

A verification email has been sent to {{username}}.
But your account is still not activated yet

Check your email and click on the activation link to activate your account. If you have any questions drop us a line at hi@TellForm.com

'),$templateCache.put("../public/modules/users/views/verify/verify-account.client.view.html",'

Account successfuly activated

Continue to login page

Verification link is invalid or has expired

Resend your verification email Signin to your account
')}]);var ApplicationConfiguration=function(){var applicationModuleName="NodeForm",applicationModuleVendorDependencies=["duScroll","ui.select","cgBusy","ngSanitize","vButton","ngResource","NodeForm.templates","ui.router","ui.bootstrap","ui.utils"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","$state","$stateParams",function($rootScope,Auth,$state,$stateParams){$rootScope.$state=$state,$rootScope.$stateParams=$stateParams,$rootScope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState){$state.previous=fromState,"home"===toState.name||"signin"===toState.name||"resendVerifyEmail"===toState.name||"verify"===toState.name||"signup"===toState.name||"signup-success"===toState.name?Auth.isAuthenticated()&&(event.preventDefault(),$state.go("listForms")):"access_denied"===toState.name||Auth.isAuthenticated()||"submitForm"===toState.name||(event.preventDefault(),$state.go("listForms"))})}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","User","Authorizer","$state","$stateParams",function($rootScope,Auth,User,Authorizer,$state,$stateParams){$rootScope.$on("$stateChangeStart",function(event,next){var authenticator,permissions,user;permissions=next&&next.data&&next.data.permissions?next.data.permissions:null,Auth.ensureHasCurrentUser(User),user=Auth.currentUser,user&&(authenticator=new Authorizer(user),null!=permissions&&(authenticator.canAccess(permissions)||(event.preventDefault(),$state.go("access_denied"))))})}]),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.router.tabs","colorpicker.module","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/forms")}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User",function($rootScope,$scope,Menus,$state,Auth,User){$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["english","french","spanish"],$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("listForms")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").controller("HomeController",["$rootScope","$scope","User","$state",function($rootScope,$scope,User,$state){$scope=$rootScope}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field&&"statement"!==field.fieldType&&"rating"!==field.fieldType?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",["$delegate",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate}])}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/views/list-forms.client.view.html"}).state("submitForm",{url:"/forms/:formId",templateUrl:"modules/forms/views/submit-form.client.view.html",data:{hideNav:!0},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"SubmitFormController",controllerAs:"ctrl"}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/views/admin-form.client.view.html",data:{permissions:["editForm"]},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"AdminFormController"}).state("viewForm.configure",{url:"/configure",templateUrl:"modules/forms/views/adminTabs/configure.html"}).state("viewForm.design",{url:"/design",templateUrl:"modules/forms/views/adminTabs/design.html"}).state("viewForm.analyze",{url:"/analyze",templateUrl:"modules/forms/views/adminTabs/analyze.html"}).state("viewForm.create",{url:"/create",templateUrl:"modules/forms/views/adminTabs/create.html"})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$uibModal","myForm",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$uibModal,myForm){$scope=$rootScope,$scope.animationsEnabled=!0,$scope.myform=myForm,$rootScope.saveInProgress=!1,CurrentForm.setForm($scope.myform),$scope.tabData=[{heading:"Create",route:"viewForm.create"},{heading:"Design",route:"viewForm.design"},{heading:"Configure",route:"viewForm.configure"},{heading:"Analyze",route:"viewForm.analyze"}],$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.openDeleteModal=function(){$scope.deleteModal=$uibModal.open({animation:$scope.animationsEnabled,templateUrl:"myModalContent.html",controller:"AdminFormController",resolve:{myForm:function(){return $scope.myform}}}),$scope.deleteModal.result.then(function(selectedItem){$scope.selected=selectedItem},function(){console.log("Modal dismissed at: "+new Date)})},$scope.cancelDeleteModal=function(){$scope.deleteModal&&$scope.deleteModal.dismiss("cancel")},$scope.removeCurrentForm=function(){if($scope.deleteModal&&$scope.deleteModal.opened){$scope.deleteModal.close();var form_id=$scope.myform._id;if(!form_id)throw new Error("Error - removeCurrentForm(): $scope.myform._id does not exist");$http["delete"]("/forms/"+form_id).success(function(data,status,headers){console.log("form deleted successfully"),$state.go("listForms",{},{reload:!0})}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}},$scope.update=$rootScope.update=function(updateImmediately,cb){var continueUpdate=!0;if(updateImmediately||(continueUpdate=!$rootScope.saveInProgress),continueUpdate){var err=null;updateImmediately||($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),err=response.data})["finally"](function(){return updateImmediately||($rootScope.saveInProgress=!1),"function"==typeof cb?cb(err):void 0})}}}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$scope.forms={},$scope.showCreateModal=!1,$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$scope.showCreateModal||($scope.showCreateModal=!0)},$scope.closeCreateModal=function(){$scope.showCreateModal&&($scope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicateForm=function(form_index){var form=_.cloneDeep($scope.myforms[form_index]);delete form._id,$http.post("/forms",{form:form}).success(function(data,status,headers){$scope.myforms.splice(form_index+1,0,data)}).error(function(errorResponse){console.error(errorResponse),null===errorResponse&&($scope.error=errorResponse.data.message)})},$scope.createNewForm=function(){var form={};form.title=$scope.forms.createForm.title.$modelValue,form.language=$scope.forms.createForm.language.$modelValue,$scope.forms.createForm.$valid&&$scope.forms.createForm.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("new form created"),$scope.goToWithId("viewForm.create",data._id+"")}).error(function(errorResponse){console.error(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeForm=function(form_index){if(form_index>=$scope.myforms.length||0>form_index)throw new Error("Error: form_index in removeForm() must be between 0 and "+$scope.myforms.length-1);$http["delete"]("/forms/"+$scope.myforms[form_index]._id).success(function(data,status,headers){console.log("form deleted successfully"),$scope.myforms.splice(form_index,1)}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}}]),angular.module("forms").controller("SubmitFormController",["$scope","$rootScope","$state","myForm","Auth",function($scope,$rootScope,$state,myForm,Auth){$scope.authentication=Auth,$scope.myform=myForm,$scope.myform.isLive?$scope.hideNav=$rootScope.hideNav=!0:$scope.authentication.isAuthenticated()?$scope.hideNav=$rootScope.hideNav=!1:($scope.hideNav=$rootScope.hideNav=!0,$state.go("access_denied"))}]),_.mixin({removeDateFields:removeDateFieldsFunc}),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFields Started",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFields Finished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!0,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine(),$formCtrl.$setUntouched())})};$scope.$watch(function(newValue,oldValue){console.log("introParagraphStartPage.$dirty: "+$scope.editForm.introParagraphStartPage.$dirty),console.log("introParagraphStartPage.$touched: "+$scope.editForm.introParagraphStartPage.$touched),$rootScope.finishedRender&&$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&(console.log("Form saving started"),debounceSave(),console.log("introParagraphStartPage.$dirty AFTER: "+$scope.editForm.introParagraphStartPage.$dirty))}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){newValue=angular.copy(newValue),oldValue=angular.copy(oldValue),newValue.form_fields=_.removeDateFields(newValue.form_fields),oldValue.form_fields=_.removeDateFields(oldValue.form_fields);var changedFields=!_.isEqual(oldValue.form_fields,newValue.form_fields)||!_.isEqual(oldValue.startPage,newValue.startPage),changedFieldMap=!1;oldValue.hasOwnProperty("plugins.oscarhost.settings.fieldMap")&&(changedFieldMap=!!oldValue.plugins.oscarhost.settings.fieldMap&&!_.isEqual(oldValue.plugins.oscarhost.settings.fieldMap,newValue.plugins.oscarhost.settings.fieldMap)),(newValue||oldValue)&&oldValue&&(0===oldValue.form_fields.length&&($rootScope.finishedRender=!0),$rootScope.finishedRender&&(changedFields&&!$formCtrl.$dirty||changedFieldMap)&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","CurrentForm",function($rootScope,$http,Upload,CurrentForm){return{templateUrl:"modules/forms/views/directiveViews/form/configure-form.client.view.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:["$scope",function($scope){console.log($scope.myform),CurrentForm.getForm().plugins?CurrentForm.getForm().plugins.oscarhost.baseUrl&&($scope.oscarhostAPI=!0):$scope.oscarhostAPI=!1,$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages,this._current_upload=null,$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update,this._unbindedPdfFields=$scope.pdfFields,$scope.cancelUpload=function(){this._current_upload.abort(),$scope.pdfLoading=!1,$scope.removePDF()},$scope.removePDF=function(){$scope.myform.pdf=null,$scope.myform.isGenerated=!1,$scope.myform.autofillPDFs=!1,console.log("form.pdf: "+$scope.myform.pdf+" REMOVED")},$scope.uploadPDF=function(file){file&&(console.log(file),Upload.upload({url:"/upload/pdf",data:{user:$scope.user,file:file}}).then(function(resp){var data=resp.data;$scope.log="file "+data.originalname+" uploaded as "+data.filename+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()},function(resp){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(resp.status)},function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total,10);$scope.log="progress: "+progressPercentage+"% "+evt.config.data.file.name+"\n"+$scope.log,console.log($scope.log),$scope.pdfLoading=!0}))}}]}}]),angular.module("forms").directive("editFormDirective",["$rootScope","FormFields",function($rootScope,FormFields){return{templateUrl:"modules/forms/views/directiveViews/form/edit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:["$scope",function($scope){for(var field_ids=_($scope.myform.form_fields).pluck("_id"),i=0;i0){$scope.myform.plugins.oscarhost.settings.fieldMap||($scope.myform.plugins.oscarhost.settings.fieldMap={});var oscarhostFields=$scope.myform.plugins.oscarhost.settings.validFields,currentFields=_($scope.myform.plugins.oscarhost.settings.fieldMap).invert().keys().value();return $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id)&&(currentFields=_(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id])),_(oscarhostFields).difference(currentFields).value()}return[]},$scope.dropzone={handle:" .handle",containment:".dropzoneContainer",cursor:"grabbing"},$scope.addNewField=function(modifyForm,fieldType){$scope.addField.lastAddedID++;for(var fieldTitle,i=0;i<$scope.addField.types.length;i++)if($scope.addField.types[i].name===fieldType){$scope.addField.types[i].lastAddedID++,fieldTitle=$scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;break}var newField={title:fieldTitle,fieldType:fieldType,fieldValue:"",required:!0,disabled:!1,deletePreserved:!1};return modifyForm&&$scope.myform.form_fields.push(newField),newField},$scope.deleteField=function(field_index){var currFieldId=$scope.myform.form_fields[field_index]._id;$scope.myform.hasOwnProperty("plugins.oscarhost.baseUrl")&&delete $scope.myform.plugins.oscarhost.settings.fieldMap[currFieldId],$scope.myform.form_fields.splice(field_index,1)},$scope.duplicateField=function(field_index){var currField=_.cloneDeep($scope.myform.form_fields[field_index]);currField._id="cloned"+_.uniqueId(),currField.title+=" copy",$scope.myform.form_fields.splice(field_index+1,0,currField)},$scope.addButton=function(){var newButton={};newButton.bgColor="#ddd",newButton.color="#ffffff",newButton.text="Button",newButton._id=Math.floor(1e5*Math.random()),$scope.myform.startPage.buttons.push(newButton)},$scope.deleteButton=function(button){for(var currID,i=0;i<$scope.myform.startPage.buttons.length;i++)if(currID=$scope.myform.startPage.buttons[i]._id,console.log(currID),currID===button._id){$scope.myform.startPage.buttons.splice(i,1);break}},$scope.addOption=function(field_index){var currField=$scope.myform.form_fields[field_index];if(console.log(field_index),console.log(currField),"checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType){currField.fieldOptions||($scope.myform.form_fields[field_index].fieldOptions=[]);var lastOptionID=0;currField.fieldOptions[currField.fieldOptions.length-1]&&(lastOptionID=currField.fieldOptions[currField.fieldOptions.length-1].option_id);var newOption={option_id:Math.floor(1e5*Math.random()),option_title:"Option "+lastOptionID,option_value:"Option "+lastOptionID};$scope.myform.form_fields[field_index].fieldOptions.push(newOption)}},$scope.deleteOption=function(field_index,option){var currField=$scope.myform.form_fields[field_index];if("checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType)for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:["$scope",function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}]}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope","$templateCache",function($http,$compile,$rootScope,$templateCache){var getTemplateUrl=function(fieldType){var type=fieldType,templateUrl="modules/forms/views/directiveViews/field/",supported_fields=["textfield","textarea","date","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0&&(templateUrl=templateUrl+type+".html"),$templateCache.get("../public/"+templateUrl)};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&",design:"=",index:"=",forms:"="},link:function(scope,element){$rootScope.chooseDefaultOption=scope.chooseDefaultOption=function(type){"yes_no"===type?scope.field.fieldValue="true":"rating"===type?scope.field.fieldValue=0:"radio"===scope.field.fieldType?(console.log(scope.field),scope.field.fieldValue=scope.field.fieldOptions[0].option_value,console.log(scope.field.fieldValue)):"legal"===type&&(scope.field.fieldValue="true",$rootScope.nextField())},scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType&&(scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0});var fieldType=scope.field.fieldType;if("number"===scope.field.fieldType||"textfield"===scope.field.fieldType||"email"===scope.field.fieldType||"link"===scope.field.fieldType){switch(scope.field.fieldType){case"textfield":scope.field.input_type="text";break;case"email":scope.field.input_type="email",scope.field.placeholder="joesmith@example.com";break;case"number":scope.field.input_type="text",scope.field.validateRegex=/^\d+$/;break;default:scope.field.input_type="url",scope.field.placeholder="http://example.com"}fieldType="textfield"}var template=getTemplateUrl(fieldType);element.html(template).show(),$compile(element.contents())(scope)}}}]),angular.module("forms").directive("onEnterKey",["$rootScope",function($rootScope){return{restrict:"A",link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode;13===keyCode&&($rootScope.$apply(function(){$rootScope.$eval($attrs.onEnterKey)}),event.preventDefault())})}}}]),angular.module("forms").directive("onFinishRender",["$rootScope","$timeout",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")||element.attr("data-ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$first&&!scope.$last?scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Started")}):scope.$last&&scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Finished")})}}}}]),angular.module("forms").directive("submitFormDirective",["$http","TimeCounter","$filter","$rootScope","Auth",function($http,TimeCounter,$filter,$rootScope,Auth){return{templateUrl:"modules/forms/views/directiveViews/form/submit-form.client.view.html",restrict:"E",scope:{ +myform:"="},controller:["$document","$window","$scope",function($document,$window,$scope){$scope.authentication=$rootScope.authentication,$scope.noscroll=!1,$scope.forms={},$scope.form_fields_count=$scope.myform.visible_form_fields.filter(function(field){return"statement"!==field.fieldType&&"rating"!==field.fieldType}).length,$scope.reloadForm=function(){$scope.myform.submitted=!1,$scope.myform.form_fields=_.chain($scope.myform.visible_form_fields).map(function(field){return field.fieldValue="",field}).value(),$scope.loading=!1,$scope.error="",$scope.selected={_id:"",index:0},$scope.setActiveField($scope.myform.visible_form_fields[0]._id,0,!1),TimeCounter.restartClock()},$window.onscroll=function(){$scope.scrollPos=document.body.scrollTop||document.documentElement.scrollTop||0;var elemBox=document.getElementsByClassName("activeField")[0].getBoundingClientRect();$scope.fieldTop=elemBox.top,$scope.fieldBottom=elemBox.bottom;var field_id,field_index;$scope.noscroll||($scope.selected.index===$scope.myform.form_fields.length-1&&$scope.fieldBottom<200?(field_index=$scope.selected.index+1,field_id="submit_field",$scope.setActiveField(field_id,field_index,!1)):$scope.selected.index===$scope.myform.form_fields.length?$scope.fieldTop>200&&(field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)):$scope.fieldBottom<0?(field_index=$scope.selected.index+1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)):0!==$scope.selected.index&&$scope.fieldTop>0&&(field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)),$scope.$apply())},$scope.setActiveField=$rootScope.setActiveField=function(field_id,field_index,animateScroll){null!==$scope.selected&&$scope.selected._id!==field_id&&($scope.selected._id=field_id,$scope.selected.index=field_index,animateScroll&&($scope.noscroll=!0,setTimeout(function(){$document.scrollToElement(angular.element(".activeField"),-10,200).then(function(){$scope.noscroll=!1,document.querySelectorAll(".activeField .focusOn")[0].focus()})},20)))},$rootScope.nextField=$scope.nextField=function(){if($scope.selected.index<$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id=$scope.myform.form_fields[selected_index]._id;$rootScope.setActiveField(selected_id,selected_index,!0)}else if($scope.selected.index===$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id="submit_field";$rootScope.setActiveField(selected_id,selected_index,!0)}},$rootScope.prevField=$scope.prevField=function(){if($scope.selected.index>0){var selected_index=$scope.selected.index-1,selected_id=$scope.myform.form_fields[selected_index]._id;$scope.setActiveField(selected_id,selected_index,!0)}},$scope.exitStartPage=function(){$scope.myform.startPage.showStart=!1,$scope.myform.form_fields.length>0&&($scope.selected._id=$scope.myform.form_fields[0]._id)},$scope.submitForm=function(){var _timeElapsed=TimeCounter.stopClock();$scope.loading=!0;var form=_.cloneDeep($scope.myform);form.timeElapsed=_timeElapsed,form.percentageComplete=$filter("formValidity")($scope.myform)/$scope.myform.visible_form_fields.length*100,delete form.visible_form_fields,setTimeout(function(){$scope.submitPromise=$http.post("/forms/"+$scope.myform._id,form).success(function(data,status,headers){$scope.myform.submitted=!0,$scope.loading=!1}).error(function(error){$scope.loading=!1,$scope.error=error.message})},500)},$scope.reloadForm()}]}}]),angular.module("forms").service("CurrentForm",function(){var _form={};this.getForm=function(){return _form},this.setForm=function(form){_form=form}}),angular.module("forms").service("FormFields",[function(){this.types=[{name:"textfield",value:"Short Text"},{name:"email",value:"Email"},{name:"radio",value:"Multiple Choice"},{name:"dropdown",value:"Dropdown"},{name:"date",value:"Date"},{name:"textarea",value:"Paragraph Text"},{name:"yes_no",value:"Yes/No"},{name:"legal",value:"Legal"},{name:"rating",value:"Rating"},{name:"link",value:"Link"},{name:"number",value:"Numbers"},{name:"statement",value:"Statement"}]}]),angular.module("forms").factory("Forms",["$resource",function($resource){return $resource("/forms/:formId",{formId:"@_id"},{query:{method:"GET",isArray:!0},get:{method:"GET",transformResponse:function(data,header){var form=angular.fromJson(data);return form.visible_form_fields=_.filter(form.form_fields,function(field){return field.deletePreserved===!1}),form}},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").factory("Submissions",["$resource",function($resource){return $resource("forms/:formID/submissions/:submissionId",{submissionId:"@_id",formId:"@_id"},{query:{method:"GET",isArray:!0},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").service("TimeCounter",[function(){var _startTime,_endTime,that=this;this.timeSpent=0,this.restartClock=function(){_startTime=Date.now(),_endTime=_startTime},this.stopClock=function(){return _startTime?(_endTime=Date.now(),that.timeSpent=Math.abs(_endTime.valueOf()-_startTime.valueOf())/1e3,that.timeSpent):new Error("Clock has not been started")},this.clockStarted=function(){return!!this._startTime}}]),angular.module("users").config(["$httpProvider",function($httpProvider){$httpProvider.interceptors.push(["$q","$location",function($q,$location){return{responseError:function(response){return"/users/me"!==$location.path()&&response.config&&"/users/me"!==response.config.url&&(console.log("intercepted rejection of ",response.config.url,response.status),401===response.status?($location.nextAfterLogin=$location.path(),$location.path("/signin")):403===response.status&&$location.path("/access_denied")),$q.reject(response)}}}])}]),angular.module("users").config(["$stateProvider",function($stateProvider){var checkLoggedin=function($q,$timeout,$state,User,Auth){var deferred=$q.defer();return Auth.currentUser&&Auth.currentUser.email?$timeout(deferred.resolve):Auth.currentUser=User.getCurrent(function(){Auth.login(),$timeout(deferred.resolve())},function(){Auth.logout(),$timeout(deferred.reject()),$state.go("sigin",{reload:!0})}),deferred.promise};checkLoggedin.$inject=["$q","$timeout","$state","User","Auth"],$stateProvider.state("profile",{resolve:{loggedin:checkLoggedin},url:"/settings/profile",templateUrl:"modules/users/views/settings/edit-profile.client.view.html"}).state("password",{resolve:{loggedin:checkLoggedin},url:"/settings/password",templateUrl:"modules/users/views/settings/change-password.client.view.html"}).state("accounts",{resolve:{loggedin:checkLoggedin},url:"/settings/accounts",templateUrl:"modules/users/views/settings/social-accounts.client.view.html"}).state("signup",{url:"/signup",templateUrl:"modules/users/views/authentication/signup.client.view.html"}).state("signup-success",{url:"/signup-success",templateUrl:"modules/users/views/authentication/signup-success.client.view.html"}).state("signin",{url:"/signin",templateUrl:"modules/users/views/authentication/signin.client.view.html"}).state("access_denied",{url:"/access_denied",templateUrl:"modules/users/views/authentication/access-denied.client.view.html"}).state("resendVerifyEmail",{url:"/verify",templateUrl:"modules/users/views/verify/resend-verify-email.client.view.html"}).state("verify",{url:"/verify/:token",templateUrl:"modules/users/views/verify/verify-account.client.view.html"}).state("forgot",{url:"/password/forgot",templateUrl:"modules/users/views/password/forgot-password.client.view.html"}).state("reset-invalid",{url:"/password/reset/invalid",templateUrl:"modules/users/views/password/reset-password-invalid.client.view.html"}).state("reset-success",{url:"/password/reset/success",templateUrl:"modules/users/views/password/reset-password-success.client.view.html"}).state("reset",{url:"/password/reset/:token",templateUrl:"modules/users/views/password/reset-password.client.view.html"})}]),angular.module("users").controller("AuthenticationController",["$scope","$location","$state","$rootScope","User","Auth",function($scope,$location,$state,$rootScope,User,Auth){$scope=$rootScope,$scope.credentials={},$scope.error="",$scope.signin=function(){$scope.credentials.email=$scope.credentials.username,User.login($scope.credentials).then(function(response){Auth.login(response),$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),"home"!==$state.previous.name&&"verify"!==$state.previous.name&&""!==$state.previous.name?$state.go($state.previous.name):$state.go("listForms")},function(error){$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user,$scope.error=error,console.log("loginError: "+error)})},$scope.signup=function(){console.log($scope.credentials),User.signup($scope.credentials).then(function(response){console.log("signup-success"),$state.go("signup-success")},function(error){console.log("Error: "),console.log(error),error?($scope.error=error,console.log(error)):console.log("No response received")})}}]),angular.module("users").controller("PasswordController",["$scope","$stateParams","$state","User",function($scope,$stateParams,$state,User){$scope.error="",$scope.askForPasswordReset=function(){User.askForPasswordReset($scope.credentials).then(function(response){$scope.success=response.message,$scope.credentials=null},function(error){$scope.error=error,$scope.credentials=null})},$scope.resetUserPassword=function(){$scope.success=$scope.error=null,User.resetPassword($scope.passwordDetails,$stateParams.token).then(function(response){$scope.success=response.message,$scope.passwordDetails=null,$state.go("reset-success")},function(error){$scope.error=error.message||error,$scope.passwordDetails=null})}}]),angular.module("users").controller("SettingsController",["$scope","$rootScope","$http","$state","Users",function($scope,$rootScope,$http,$state,Users){$scope.user=$rootScope.user,$scope.hasConnectedAdditionalSocialAccounts=function(provider){for(var i in $scope.user.additionalProvidersData)return!0;return!1},$scope.isConnectedSocialAccount=function(provider){return $scope.user.provider===provider||$scope.user.additionalProvidersData&&$scope.user.additionalProvidersData[provider]},$scope.removeUserSocialAccount=function(provider){$scope.success=$scope.error=null,$http["delete"]("/users/accounts",{params:{provider:provider}}).success(function(response){$scope.success=!0,$scope.user=response}).error(function(response){$scope.error=response.message})},$scope.updateUserProfile=function(isValid){if(isValid){$scope.success=$scope.error=null;var user=new Users($scope.user);user.$update(function(response){$scope.success=!0,$scope.user=response},function(response){$scope.error=response.data.message})}else $scope.submitted=!0},$scope.changeUserPassword=function(){$scope.success=$scope.error=null,$http.post("/users/password",$scope.passwordDetails).success(function(response){$scope.success=!0,$scope.passwordDetails=null}).error(function(response){$scope.error=response.message})}}]),angular.module("users").controller("VerifyController",["$scope","$state","$rootScope","User","Auth","$stateParams",function($scope,$state,$rootScope,User,Auth,$stateParams){$scope.isResetSent=!1,$scope.credentials={},$scope.error="",$scope.resendVerifyEmail=function(){User.resendVerifyEmail($scope.credentials.email).then(function(response){console.log(response),$scope.success=response.message,$scope.credentials=null,$scope.isResetSent=!0},function(error){$scope.error=error,$scope.credentials.email=null,$scope.isResetSent=!1})},$scope.validateVerifyToken=function(){$stateParams.token&&(console.log($stateParams.token),User.validateVerifyToken($stateParams.token).then(function(response){console.log("Success: "+response.message),$scope.success=response.message,$scope.isResetSent=!0,$scope.credentials.email=null},function(error){console.log("Error: "+error.message),$scope.isResetSent=!1,$scope.error=error,$scope.credentials.email=null}))}}]),angular.module("users").factory("Auth",["$window",function($window){var userState={isLoggedIn:!1},service={_currentUser:null,get currentUser(){return this._currentUser},ensureHasCurrentUser:function(User){return service._currentUser&&service._currentUser.username?service._currentUser:$window.user?(service._currentUser=$window.user,service._currentUser):void User.getCurrent().then(function(user){return service._currentUser=user,userState.isLoggedIn=!0,$window.user=service._currentUser,service._currentUser},function(response){return userState.isLoggedIn=!1,service._currentUser=null,$window.user=null,console.log("User.getCurrent() err",response),null})},isAuthenticated:function(){return!!service._currentUser},getUserState:function(){return userState},login:function(new_user){userState.isLoggedIn=!0,service._currentUser=new_user},logout:function(){$window.user=null,userState.isLoggedIn=!1,service._currentUser=null}};return service}]),angular.module("users").service("Authorizer",["APP_PERMISSIONS","USER_ROLES",function(APP_PERMISSIONS,USER_ROLES){return function(user){return{canAccess:function(permissions){var i,len,permission;for(angular.isArray(permissions)||(permissions=[permissions]),i=0,len=permissions.length;len>i;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}]),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var validTokenRe=/^([A-Za-z0-9]{48})$/g;if(!validTokenRe.test(token))throw new Error("Error token: "+token+" is not a valid verification token");var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file diff --git a/scripts/setup.js b/scripts/setup.js new file mode 100644 index 00000000..6330f76e --- /dev/null +++ b/scripts/setup.js @@ -0,0 +1,201 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ +process.env.NODE_ENV = 'production'; + +var init = require('../config/init')(), + config = require('../config/config'), + mongoose = require('mongoose'), + inquirer = require('inquirer'), + envfile = require('envfile'), + fs = require('fs-extra'), + chalk = require('chalk'); + +/** + * Main application entry file. + * Please note that the order of loading is important. + */ + +// Bootstrap db connection +var db = mongoose.connect(config.db.uri, config.db.options, function(err) { + if (err) { + console.error(chalk.red('Could not connect to MongoDB!')); + console.log(chalk.red(err)); + } +}); +mongoose.connection.on('error', function(err) { + console.error(chalk.red('MongoDB connection error: ' + err)); + process.exit(-1); +}); + +// Init the express application +var app = require('../config/express')(db); + +// Bootstrap passport config +require('../config/passport')(); + +var User = mongoose.model('User'); +require('../app/models/user.server.model.js'); + +var nodemailer_providers = [ + '1und1', + 'AOL', + 'DebugMail.io', + 'DynectEmail', + 'FastMail', + 'GandiMail', + 'Gmail', + 'Godaddy', + 'GodaddyAsia', + 'GodaddyEurope', + 'hot.ee', + 'Hotmail', + 'iCloud', + 'mail.ee', + 'Mail.ru', + 'Mailgun', + 'Mailjet', + 'Mandrill', + 'Naver', + 'OpenMailBox', + 'Postmark', + 'QQ', + 'QQex', + 'SendCloud', + 'SendGrid', + 'SES', + 'SES-US-EAST-1', + 'SES-US-WEST-1', + 'SES-EU-WEST-1', + 'Sparkpost', + 'Yahoo', + 'Yandex', + 'Zoho' +]; + +var questions = [ + { + type: 'confirm', + name: 'shouldContinue', + message: 'Do you wish to configure your deployment now?' + }, + { + type: 'input', + name: 'APP_NAME', + message: 'What do you want to name your TellForm deployment?' + }, + { + type: 'input', + name: 'APP_DESC', + message: 'Describe your project (for SEO)' + }, + { + type: 'input', + name: 'APP_KEYWORDS', + message: 'What keywords are relevant to your project (seperate by commas)' + }, + { + type: 'confirm', + name: 'SIGNUP_DISABLED', + message: 'Do you want to disable signups?', + default: false + }, + { + type: 'list', + name: 'NODE_ENV', + message: 'What should be the default environment', + choices: ['dev','production'] + }, + { + type: 'list', + name: 'MAILER_SERVICE_PROVIDER', + message: 'What email service provider are you using?', + choices: nodemailer_providers + }, + { + type: 'input', + name: 'MAILER_EMAIL_ID', + message: 'What is your SMTP username?' + }, + { + type: 'password', + name: 'MAILER_PASSWORD', + message: 'What is your SMTP password?' + }, + { + type: 'input', + name: 'MAILER_FROM', + message: 'What do you want the default "from" email address to be?' + }, + { + type: 'input', + name: 'BASE_URL', + message: 'What is the url your TellForm will be hosted at?', + default: '127.0.0.1' + }, + { + type: 'input', + name: 'PORT', + message: 'What port should the TellForm server run on?', + default: '3000' + }, + { + type: 'input', + name: 'GOOGLE_ANALYTICS_ID', + message: 'What is your Google Analytics Tag?' + }, + { + type: 'input', + name: 'email', + message: 'What should be the email for your admin account?' + }, + { + type: 'password', + name: 'password', + message: 'What should be the password for your admin account?' + } +]; + +console.log(chalk.green('\n\nHi, welcome to TellForm Setup')); + +console.log(chalk.green('This will only run the first time you run TellForm\n--------------------------------------------------\n\n')); + +inquirer.prompt([questions[0]]).then(function (confirmAns) { + if(confirmAns['shouldContinue']) { + + inquirer.prompt(questions.slice(1)).then(function (answers) { + + var email = answers['email']; + var pass = answers['password']; + delete answers['email']; + delete answers['password']; + + envfile.stringify(answers, function (err, str) { + fs.outputFile('..//.env', str, function(err){ + if (err) return console.error(chalk.red(err)); + console.log(chalk.green('Successfully created .env file')); + }); + user = new User({ + firstName: 'Admin', + lastName: 'Account', + email: email, + username: email, + password: pass, + provider: 'local', + roles: ['admin', 'user'] + }); + + user.save(function (err) { + if (err) return console.error(chalk.red(err)); + console.log(chalk.green('Succesfully created user')); + delete email; + delete pass; + }); + }); + }); + } else { + console.log(chalk.green('Have fun using TellForm!')); + } +}); From 898f31181b04d8464ec8ed2470967da8dcc07020 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Tue, 10 May 2016 00:25:00 -0700 Subject: [PATCH 3/8] got setup script to work --- a.txt | 14 ----------- app/views/layout.server.view.html | 5 ++++ config/env/all.js | 2 +- config/express.js | 11 +++++---- ecosystem.json | 2 +- public/dist/application.js | 20 +++++++++++++--- public/dist/application.min.js | 2 +- .../controllers/header.client.controller.js | 6 +++-- .../core/views/header.client.view.html | 2 +- .../users/config/users.client.routes.js | 23 +++++++++++++++---- .../authentication/signin.client.view.html | 11 ++++++--- 11 files changed, 63 insertions(+), 35 deletions(-) delete mode 100644 a.txt diff --git a/a.txt b/a.txt deleted file mode 100644 index f6491dff..00000000 --- a/a.txt +++ /dev/null @@ -1,14 +0,0 @@ -APP_NAME= -APP_DESC= -APP_KEYWORDS= -SIGNUP_DISABLED=false -NODE_ENV=dev -MAILER_SERVICE_PROVIDER=1und1 -MAILER_EMAIL_ID= -MAILER_PASSWORD= -MAILER_FROM= -BASE_URL=127.0.0.1 -PORT=3000 -GOOGLE_ANALYTICS_ID= -email= -password= diff --git a/app/views/layout.server.view.html b/app/views/layout.server.view.html index c8caccbd..16e8532f 100755 --- a/app/views/layout.server.view.html +++ b/app/views/layout.server.view.html @@ -77,6 +77,11 @@ var user = {{ user | json | safe }}; + + + {% for bowerJSFile in bowerJSFiles %} diff --git a/config/env/all.js b/config/env/all.js index 7172f61e..a80f252a 100755 --- a/config/env/all.js +++ b/config/env/all.js @@ -10,7 +10,7 @@ module.exports = { port: process.env.PORT || 3000, templateEngine: 'swig', - signupDisabled: process.env.SIGNUP_DISABLED || false, + signupDisabled: !!process.env.SIGNUP_DISABLED || false, baseUrl: '', tempUserCollection: 'temporary_users', diff --git a/config/express.js b/config/express.js index 878450a3..e2f218b4 100755 --- a/config/express.js +++ b/config/express.js @@ -31,7 +31,7 @@ var fs = require('fs-extra'), module.exports = function(db) { // Initialize express app var app = express(); - + // Globbing model files config.getGlobbedFiles('./app/models/**/*.js').forEach(function(modelPath) { require(path.resolve(modelPath)); @@ -40,6 +40,7 @@ module.exports = function(db) { // Setting application local variables app.locals.google_analytics_id = config.app.google_analytics_id; app.locals.title = config.app.title; + app.locals.signupDisabled = config.signupDisabled; app.locals.description = config.app.description; app.locals.keywords = config.app.keywords; @@ -52,7 +53,7 @@ module.exports = function(db) { //Setup Prerender.io app.use(require('prerender-node').set('prerenderToken', process.env.PRERENDER_TOKEN)); - + // Passing the request url to environment locals app.use(function(req, res, next) { if(config.baseUrl === ''){ @@ -107,7 +108,7 @@ module.exports = function(db) { app.use(helmet.ienoopen()); app.disable('x-powered-by'); - + // Setting the app router and static folder app.use('/', express.static(path.resolve('./public'))); app.use('/uploads', express.static(path.resolve('./uploads'))); @@ -127,7 +128,7 @@ module.exports = function(db) { cookie: config.sessionCookie, name: config.sessionName })); - + // use passport session app.use(passport.initialize()); app.use(passport.session()); @@ -143,7 +144,7 @@ module.exports = function(db) { require(path.resolve(routePath))(app); }); - + // Add headers for Sentry /* app.use(function (req, res, next) { diff --git a/ecosystem.json b/ecosystem.json index d8a3db0f..efa6ff85 100644 --- a/ecosystem.json +++ b/ecosystem.json @@ -14,7 +14,7 @@ "env" : { "NODE_ENV": "production", "BASE_URL": "stage.tellform.com" - } + } }, "prod" : { "user" : "polydaic", diff --git a/public/dist/application.js b/public/dist/application.js index 85651997..c825a76a 100644 --- a/public/dist/application.js +++ b/public/dist/application.js @@ -2181,7 +2181,7 @@ angular.module('users').config(['$stateProvider', var checkLoggedin = function($q, $timeout, $state, User, Auth) { var deferred = $q.defer(); - // console.log(Auth.ensureHasCurrentUser(User)); + console.log(Auth.ensureHasCurrentUser(User)); if (Auth.currentUser && Auth.currentUser.email) { $timeout(deferred.resolve); @@ -2202,6 +2202,15 @@ angular.module('users').config(['$stateProvider', }; checkLoggedin.$inject = ["$q", "$timeout", "$state", "User", "Auth"]; + var checkSignupDisabled = function($window, $timeout, $q) { + console.log($window.signupDisabled); + var deferred = $q.defer(); + $timeout(deferred.reject()); + return deferred.promise; + //return !$window.signupDisabled; + }; + checkSignupDisabled.$inject = ["$window", "$timeout", "$q"]; + // Users state routing $stateProvider. state('profile', { @@ -2225,12 +2234,17 @@ angular.module('users').config(['$stateProvider', url: '/settings/accounts', templateUrl: 'modules/users/views/settings/social-accounts.client.view.html' }). - state('signup', { + resolve: { + isDisabled: checkSignupDisabled + }, url: '/signup', templateUrl: 'modules/users/views/authentication/signup.client.view.html' }). state('signup-success', { + resolve: { + isDisabled: checkSignupDisabled + }, url: '/signup-success', templateUrl: 'modules/users/views/authentication/signup-success.client.view.html' }). @@ -2242,7 +2256,6 @@ angular.module('users').config(['$stateProvider', url: '/access_denied', templateUrl: 'modules/users/views/authentication/access-denied.client.view.html' }). - state('resendVerifyEmail', { url: '/verify', templateUrl: 'modules/users/views/verify/resend-verify-email.client.view.html' @@ -2270,6 +2283,7 @@ angular.module('users').config(['$stateProvider', }); } ]); + 'use strict'; angular.module('users').controller('AuthenticationController', ['$scope', '$location', '$state', '$rootScope', 'User', 'Auth', diff --git a/public/dist/application.min.js b/public/dist/application.min.js index 18990061..37b88696 100644 --- a/public/dist/application.min.js +++ b/public/dist/application.min.js @@ -1,4 +1,4 @@ function removeDateFieldsFunc(o){function eachObject(v,k){"lastModified"!==k&&"created"!==k||delete clone[i][k]}for(var clone=_.clone(o),i=0;i'),$templateCache.put("../public/modules/core/views/home.client.view.html",'

Craft beautiful forms in seconds.

Create your next ______.

Tell a story with a form.

'),$templateCache.put("../public/modules/forms/views/admin-form.client.view.html",'
'),$templateCache.put("../public/modules/forms/views/list-forms.client.view.html",'

Create a new form
Name
Language

'),$templateCache.put("../public/modules/forms/views/submit-form.client.view.html","
"),$templateCache.put("../public/modules/forms/views/adminTabs/analyze.html",""),$templateCache.put("../public/modules/forms/views/adminTabs/configure.html",""),$templateCache.put("../public/modules/forms/views/adminTabs/create.html",""),$templateCache.put("../public/modules/forms/views/adminTabs/design.html",'
Background Color
Question Text Color
Answer Text Color
Button Background Color
Button Text Color
'),$templateCache.put("../public/modules/forms/views/directiveViews/cgBusy/update-form-message-TypeA.html",'
{{$message}}
'),$templateCache.put("../public/modules/forms/views/directiveViews/cgBusy/update-form-message-TypeB.html",'
{{$message}}
'),$templateCache.put("../public/modules/forms/views/directiveViews/entryPage/startPage.html",'

{{pageData.introTitle}}

{{pageData.introParagraph}}

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/date.html",'

{{field.title}} optional

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/dropdown.html",'
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/file.html",'
{{field.title}} (* required)
{{field.file.originalname}}
Upload your File
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/hidden.html",''),$templateCache.put("../public/modules/forms/views/directiveViews/field/legal.html",'
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/radio.html",'

{{field.title}} optional


'),$templateCache.put("../public/modules/forms/views/directiveViews/field/rating.html",'

{{field.title}} optional

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/statement.html",'

{{field.title}}

{{field.description}}


'),$templateCache.put("../public/modules/forms/views/directiveViews/field/textarea.html",'

{{field.title}} optional

press ENTER
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/textfield.html",'

{{field.title}} (optional)

press ENTER
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/yes_no.html",'

{{field.title}} *(required)

{{field.description}}


'),$templateCache.put("../public/modules/forms/views/directiveViews/form/configure-form.client.view.html",'
Save Submissions as PDFs?
Upload Your PDF Template
{{myform.pdf.name}}
Upload your PDF
Autogenerate Form?
Use Oscarhost API?
Oscarhost API Username
Oscarhost API Password
Oscarhost API URL
Oscarhost API Update Type
Form Name
Form Status
Language
* required
Display Form Footer?
Display Start Page?
'), $templateCache.put("../public/modules/forms/views/directiveViews/form/edit-form.client.view.html",'

Edit Start Page


Intro Title:
Intro Paragraph:
\n
\n\n

\n
\n
Options:
\n
\n
\n \n\n \n \n \n
\n
\n \n
\n
\n
\n\n

\n\n
\n
Required:
\n
\n \n\n \n
\n
\n\n
\n
Disabled:
\n
\n \n\n \n
\n
\n\n
\n \n\n
\n
\n

\n Click on Fields to add them here\n

\n
\n
\n\n
\n \n
\n\n \n \n\n \n
\n
\n\n'),$templateCache.put("../public/modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html",'
#{{value.title}}OscarEMR User ProfilePercentage CompleteTime ElapsedDeviceLocationIP AddressDate Submitted (UTC)Generated PDF
{{$index+1}}{{field.fieldValue}}User Profile #{{row.oscarDemoNum}}{{row.percentageComplete}}%{{row.timeElapsed}}{{row.device.name}}, {{row.device.type}}{{row.geoLocation.city}}, {{row.geoLocation.country}}{{row.ipAddr}}{{row.created | date:\'yyyy-MM-dd HH:mm:ss\'}}Generated PDF
'),$templateCache.put("../public/modules/forms/views/directiveViews/form/submit-form.client.view.html",'
press ENTER
'),$templateCache.put("../public/modules/users/views/authentication/access-denied.client.view.html",'

You need to be logged in to access this page

Login
'),$templateCache.put("../public/modules/users/views/authentication/signin.client.view.html",'

Sign into your account

'),$templateCache.put("../public/modules/users/views/authentication/signup-success.client.view.html",''),$templateCache.put("../public/modules/users/views/authentication/signup.client.view.html",''),$templateCache.put("../public/modules/users/views/password/forgot-password.client.view.html",'

Restore your password

Enter your account email.

'),$templateCache.put("../public/modules/users/views/password/reset-password-invalid.client.view.html",'

Password reset is invalid

Ask for a new password reset
'),$templateCache.put("../public/modules/users/views/password/reset-password-success.client.view.html",'

Password successfully reset

Continue to home page
'),$templateCache.put("../public/modules/users/views/password/reset-password.client.view.html",'

Reset your password

'),$templateCache.put("../public/modules/users/views/settings/change-password.client.view.html",'

Change your password

'),$templateCache.put("../public/modules/users/views/settings/edit-profile.client.view.html",'

Edit your profile

'), $templateCache.put("../public/modules/users/views/settings/social-accounts.client.view.html",'

Connected social accounts:

Connect other social accounts:

'),$templateCache.put("../public/modules/users/views/verify/resend-verify-email.client.view.html",'

Resend your account verification email

Enter your account email.

{{error}}

Verification Email has been Sent

A verification email has been sent to {{username}}.
But your account is still not activated yet

Check your email and click on the activation link to activate your account. If you have any questions drop us a line at hi@TellForm.com

'),$templateCache.put("../public/modules/users/views/verify/verify-account.client.view.html",'

Account successfuly activated

Continue to login page

Verification link is invalid or has expired

Resend your verification email Signin to your account
')}]);var ApplicationConfiguration=function(){var applicationModuleName="NodeForm",applicationModuleVendorDependencies=["duScroll","ui.select","cgBusy","ngSanitize","vButton","ngResource","NodeForm.templates","ui.router","ui.bootstrap","ui.utils"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","$state","$stateParams",function($rootScope,Auth,$state,$stateParams){$rootScope.$state=$state,$rootScope.$stateParams=$stateParams,$rootScope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState){$state.previous=fromState,"home"===toState.name||"signin"===toState.name||"resendVerifyEmail"===toState.name||"verify"===toState.name||"signup"===toState.name||"signup-success"===toState.name?Auth.isAuthenticated()&&(event.preventDefault(),$state.go("listForms")):"access_denied"===toState.name||Auth.isAuthenticated()||"submitForm"===toState.name||(event.preventDefault(),$state.go("listForms"))})}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","User","Authorizer","$state","$stateParams",function($rootScope,Auth,User,Authorizer,$state,$stateParams){$rootScope.$on("$stateChangeStart",function(event,next){var authenticator,permissions,user;permissions=next&&next.data&&next.data.permissions?next.data.permissions:null,Auth.ensureHasCurrentUser(User),user=Auth.currentUser,user&&(authenticator=new Authorizer(user),null!=permissions&&(authenticator.canAccess(permissions)||(event.preventDefault(),$state.go("access_denied"))))})}]),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.router.tabs","colorpicker.module","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/forms")}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User",function($rootScope,$scope,Menus,$state,Auth,User){$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["english","french","spanish"],$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("listForms")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").controller("HomeController",["$rootScope","$scope","User","$state",function($rootScope,$scope,User,$state){$scope=$rootScope}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field&&"statement"!==field.fieldType&&"rating"!==field.fieldType?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",["$delegate",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate}])}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/views/list-forms.client.view.html"}).state("submitForm",{url:"/forms/:formId",templateUrl:"modules/forms/views/submit-form.client.view.html",data:{hideNav:!0},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"SubmitFormController",controllerAs:"ctrl"}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/views/admin-form.client.view.html",data:{permissions:["editForm"]},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"AdminFormController"}).state("viewForm.configure",{url:"/configure",templateUrl:"modules/forms/views/adminTabs/configure.html"}).state("viewForm.design",{url:"/design",templateUrl:"modules/forms/views/adminTabs/design.html"}).state("viewForm.analyze",{url:"/analyze",templateUrl:"modules/forms/views/adminTabs/analyze.html"}).state("viewForm.create",{url:"/create",templateUrl:"modules/forms/views/adminTabs/create.html"})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$uibModal","myForm",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$uibModal,myForm){$scope=$rootScope,$scope.animationsEnabled=!0,$scope.myform=myForm,$rootScope.saveInProgress=!1,CurrentForm.setForm($scope.myform),$scope.tabData=[{heading:"Create",route:"viewForm.create"},{heading:"Design",route:"viewForm.design"},{heading:"Configure",route:"viewForm.configure"},{heading:"Analyze",route:"viewForm.analyze"}],$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.openDeleteModal=function(){$scope.deleteModal=$uibModal.open({animation:$scope.animationsEnabled,templateUrl:"myModalContent.html",controller:"AdminFormController",resolve:{myForm:function(){return $scope.myform}}}),$scope.deleteModal.result.then(function(selectedItem){$scope.selected=selectedItem},function(){console.log("Modal dismissed at: "+new Date)})},$scope.cancelDeleteModal=function(){$scope.deleteModal&&$scope.deleteModal.dismiss("cancel")},$scope.removeCurrentForm=function(){if($scope.deleteModal&&$scope.deleteModal.opened){$scope.deleteModal.close();var form_id=$scope.myform._id;if(!form_id)throw new Error("Error - removeCurrentForm(): $scope.myform._id does not exist");$http["delete"]("/forms/"+form_id).success(function(data,status,headers){console.log("form deleted successfully"),$state.go("listForms",{},{reload:!0})}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}},$scope.update=$rootScope.update=function(updateImmediately,cb){var continueUpdate=!0;if(updateImmediately||(continueUpdate=!$rootScope.saveInProgress),continueUpdate){var err=null;updateImmediately||($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),err=response.data})["finally"](function(){return updateImmediately||($rootScope.saveInProgress=!1),"function"==typeof cb?cb(err):void 0})}}}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$scope.forms={},$scope.showCreateModal=!1,$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$scope.showCreateModal||($scope.showCreateModal=!0)},$scope.closeCreateModal=function(){$scope.showCreateModal&&($scope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicateForm=function(form_index){var form=_.cloneDeep($scope.myforms[form_index]);delete form._id,$http.post("/forms",{form:form}).success(function(data,status,headers){$scope.myforms.splice(form_index+1,0,data)}).error(function(errorResponse){console.error(errorResponse),null===errorResponse&&($scope.error=errorResponse.data.message)})},$scope.createNewForm=function(){var form={};form.title=$scope.forms.createForm.title.$modelValue,form.language=$scope.forms.createForm.language.$modelValue,$scope.forms.createForm.$valid&&$scope.forms.createForm.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("new form created"),$scope.goToWithId("viewForm.create",data._id+"")}).error(function(errorResponse){console.error(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeForm=function(form_index){if(form_index>=$scope.myforms.length||0>form_index)throw new Error("Error: form_index in removeForm() must be between 0 and "+$scope.myforms.length-1);$http["delete"]("/forms/"+$scope.myforms[form_index]._id).success(function(data,status,headers){console.log("form deleted successfully"),$scope.myforms.splice(form_index,1)}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}}]),angular.module("forms").controller("SubmitFormController",["$scope","$rootScope","$state","myForm","Auth",function($scope,$rootScope,$state,myForm,Auth){$scope.authentication=Auth,$scope.myform=myForm,$scope.myform.isLive?$scope.hideNav=$rootScope.hideNav=!0:$scope.authentication.isAuthenticated()?$scope.hideNav=$rootScope.hideNav=!1:($scope.hideNav=$rootScope.hideNav=!0,$state.go("access_denied"))}]),_.mixin({removeDateFields:removeDateFieldsFunc}),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFields Started",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFields Finished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!0,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine(),$formCtrl.$setUntouched())})};$scope.$watch(function(newValue,oldValue){console.log("introParagraphStartPage.$dirty: "+$scope.editForm.introParagraphStartPage.$dirty),console.log("introParagraphStartPage.$touched: "+$scope.editForm.introParagraphStartPage.$touched),$rootScope.finishedRender&&$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&(console.log("Form saving started"),debounceSave(),console.log("introParagraphStartPage.$dirty AFTER: "+$scope.editForm.introParagraphStartPage.$dirty))}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){newValue=angular.copy(newValue),oldValue=angular.copy(oldValue),newValue.form_fields=_.removeDateFields(newValue.form_fields),oldValue.form_fields=_.removeDateFields(oldValue.form_fields);var changedFields=!_.isEqual(oldValue.form_fields,newValue.form_fields)||!_.isEqual(oldValue.startPage,newValue.startPage),changedFieldMap=!1;oldValue.hasOwnProperty("plugins.oscarhost.settings.fieldMap")&&(changedFieldMap=!!oldValue.plugins.oscarhost.settings.fieldMap&&!_.isEqual(oldValue.plugins.oscarhost.settings.fieldMap,newValue.plugins.oscarhost.settings.fieldMap)),(newValue||oldValue)&&oldValue&&(0===oldValue.form_fields.length&&($rootScope.finishedRender=!0),$rootScope.finishedRender&&(changedFields&&!$formCtrl.$dirty||changedFieldMap)&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","CurrentForm",function($rootScope,$http,Upload,CurrentForm){return{templateUrl:"modules/forms/views/directiveViews/form/configure-form.client.view.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:["$scope",function($scope){console.log($scope.myform),CurrentForm.getForm().plugins?CurrentForm.getForm().plugins.oscarhost.baseUrl&&($scope.oscarhostAPI=!0):$scope.oscarhostAPI=!1,$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages,this._current_upload=null,$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update,this._unbindedPdfFields=$scope.pdfFields,$scope.cancelUpload=function(){this._current_upload.abort(),$scope.pdfLoading=!1,$scope.removePDF()},$scope.removePDF=function(){$scope.myform.pdf=null,$scope.myform.isGenerated=!1,$scope.myform.autofillPDFs=!1,console.log("form.pdf: "+$scope.myform.pdf+" REMOVED")},$scope.uploadPDF=function(file){file&&(console.log(file),Upload.upload({url:"/upload/pdf",data:{user:$scope.user,file:file}}).then(function(resp){var data=resp.data;$scope.log="file "+data.originalname+" uploaded as "+data.filename+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()},function(resp){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(resp.status)},function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total,10);$scope.log="progress: "+progressPercentage+"% "+evt.config.data.file.name+"\n"+$scope.log,console.log($scope.log),$scope.pdfLoading=!0}))}}]}}]),angular.module("forms").directive("editFormDirective",["$rootScope","FormFields",function($rootScope,FormFields){return{templateUrl:"modules/forms/views/directiveViews/form/edit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:["$scope",function($scope){for(var field_ids=_($scope.myform.form_fields).pluck("_id"),i=0;i0){$scope.myform.plugins.oscarhost.settings.fieldMap||($scope.myform.plugins.oscarhost.settings.fieldMap={});var oscarhostFields=$scope.myform.plugins.oscarhost.settings.validFields,currentFields=_($scope.myform.plugins.oscarhost.settings.fieldMap).invert().keys().value();return $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id)&&(currentFields=_(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id])),_(oscarhostFields).difference(currentFields).value()}return[]},$scope.dropzone={handle:" .handle",containment:".dropzoneContainer",cursor:"grabbing"},$scope.addNewField=function(modifyForm,fieldType){$scope.addField.lastAddedID++;for(var fieldTitle,i=0;i<$scope.addField.types.length;i++)if($scope.addField.types[i].name===fieldType){$scope.addField.types[i].lastAddedID++,fieldTitle=$scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;break}var newField={title:fieldTitle,fieldType:fieldType,fieldValue:"",required:!0,disabled:!1,deletePreserved:!1};return modifyForm&&$scope.myform.form_fields.push(newField),newField},$scope.deleteField=function(field_index){var currFieldId=$scope.myform.form_fields[field_index]._id;$scope.myform.hasOwnProperty("plugins.oscarhost.baseUrl")&&delete $scope.myform.plugins.oscarhost.settings.fieldMap[currFieldId],$scope.myform.form_fields.splice(field_index,1)},$scope.duplicateField=function(field_index){var currField=_.cloneDeep($scope.myform.form_fields[field_index]);currField._id="cloned"+_.uniqueId(),currField.title+=" copy",$scope.myform.form_fields.splice(field_index+1,0,currField)},$scope.addButton=function(){var newButton={};newButton.bgColor="#ddd",newButton.color="#ffffff",newButton.text="Button",newButton._id=Math.floor(1e5*Math.random()),$scope.myform.startPage.buttons.push(newButton)},$scope.deleteButton=function(button){for(var currID,i=0;i<$scope.myform.startPage.buttons.length;i++)if(currID=$scope.myform.startPage.buttons[i]._id,console.log(currID),currID===button._id){$scope.myform.startPage.buttons.splice(i,1);break}},$scope.addOption=function(field_index){var currField=$scope.myform.form_fields[field_index];if(console.log(field_index),console.log(currField),"checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType){currField.fieldOptions||($scope.myform.form_fields[field_index].fieldOptions=[]);var lastOptionID=0;currField.fieldOptions[currField.fieldOptions.length-1]&&(lastOptionID=currField.fieldOptions[currField.fieldOptions.length-1].option_id);var newOption={option_id:Math.floor(1e5*Math.random()),option_title:"Option "+lastOptionID,option_value:"Option "+lastOptionID};$scope.myform.form_fields[field_index].fieldOptions.push(newOption)}},$scope.deleteOption=function(field_index,option){var currField=$scope.myform.form_fields[field_index];if("checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType)for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:["$scope",function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}]}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope","$templateCache",function($http,$compile,$rootScope,$templateCache){var getTemplateUrl=function(fieldType){var type=fieldType,templateUrl="modules/forms/views/directiveViews/field/",supported_fields=["textfield","textarea","date","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0&&(templateUrl=templateUrl+type+".html"),$templateCache.get("../public/"+templateUrl)};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&",design:"=",index:"=",forms:"="},link:function(scope,element){$rootScope.chooseDefaultOption=scope.chooseDefaultOption=function(type){"yes_no"===type?scope.field.fieldValue="true":"rating"===type?scope.field.fieldValue=0:"radio"===scope.field.fieldType?(console.log(scope.field),scope.field.fieldValue=scope.field.fieldOptions[0].option_value,console.log(scope.field.fieldValue)):"legal"===type&&(scope.field.fieldValue="true",$rootScope.nextField())},scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType&&(scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0});var fieldType=scope.field.fieldType;if("number"===scope.field.fieldType||"textfield"===scope.field.fieldType||"email"===scope.field.fieldType||"link"===scope.field.fieldType){switch(scope.field.fieldType){case"textfield":scope.field.input_type="text";break;case"email":scope.field.input_type="email",scope.field.placeholder="joesmith@example.com";break;case"number":scope.field.input_type="text",scope.field.validateRegex=/^\d+$/;break;default:scope.field.input_type="url",scope.field.placeholder="http://example.com"}fieldType="textfield"}var template=getTemplateUrl(fieldType);element.html(template).show(),$compile(element.contents())(scope)}}}]),angular.module("forms").directive("onEnterKey",["$rootScope",function($rootScope){return{restrict:"A",link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode;13===keyCode&&($rootScope.$apply(function(){$rootScope.$eval($attrs.onEnterKey)}),event.preventDefault())})}}}]),angular.module("forms").directive("onFinishRender",["$rootScope","$timeout",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")||element.attr("data-ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$first&&!scope.$last?scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Started")}):scope.$last&&scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Finished")})}}}}]),angular.module("forms").directive("submitFormDirective",["$http","TimeCounter","$filter","$rootScope","Auth",function($http,TimeCounter,$filter,$rootScope,Auth){return{templateUrl:"modules/forms/views/directiveViews/form/submit-form.client.view.html",restrict:"E",scope:{ -myform:"="},controller:["$document","$window","$scope",function($document,$window,$scope){$scope.authentication=$rootScope.authentication,$scope.noscroll=!1,$scope.forms={},$scope.form_fields_count=$scope.myform.visible_form_fields.filter(function(field){return"statement"!==field.fieldType&&"rating"!==field.fieldType}).length,$scope.reloadForm=function(){$scope.myform.submitted=!1,$scope.myform.form_fields=_.chain($scope.myform.visible_form_fields).map(function(field){return field.fieldValue="",field}).value(),$scope.loading=!1,$scope.error="",$scope.selected={_id:"",index:0},$scope.setActiveField($scope.myform.visible_form_fields[0]._id,0,!1),TimeCounter.restartClock()},$window.onscroll=function(){$scope.scrollPos=document.body.scrollTop||document.documentElement.scrollTop||0;var elemBox=document.getElementsByClassName("activeField")[0].getBoundingClientRect();$scope.fieldTop=elemBox.top,$scope.fieldBottom=elemBox.bottom;var field_id,field_index;$scope.noscroll||($scope.selected.index===$scope.myform.form_fields.length-1&&$scope.fieldBottom<200?(field_index=$scope.selected.index+1,field_id="submit_field",$scope.setActiveField(field_id,field_index,!1)):$scope.selected.index===$scope.myform.form_fields.length?$scope.fieldTop>200&&(field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)):$scope.fieldBottom<0?(field_index=$scope.selected.index+1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)):0!==$scope.selected.index&&$scope.fieldTop>0&&(field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)),$scope.$apply())},$scope.setActiveField=$rootScope.setActiveField=function(field_id,field_index,animateScroll){null!==$scope.selected&&$scope.selected._id!==field_id&&($scope.selected._id=field_id,$scope.selected.index=field_index,animateScroll&&($scope.noscroll=!0,setTimeout(function(){$document.scrollToElement(angular.element(".activeField"),-10,200).then(function(){$scope.noscroll=!1,document.querySelectorAll(".activeField .focusOn")[0].focus()})},20)))},$rootScope.nextField=$scope.nextField=function(){if($scope.selected.index<$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id=$scope.myform.form_fields[selected_index]._id;$rootScope.setActiveField(selected_id,selected_index,!0)}else if($scope.selected.index===$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id="submit_field";$rootScope.setActiveField(selected_id,selected_index,!0)}},$rootScope.prevField=$scope.prevField=function(){if($scope.selected.index>0){var selected_index=$scope.selected.index-1,selected_id=$scope.myform.form_fields[selected_index]._id;$scope.setActiveField(selected_id,selected_index,!0)}},$scope.exitStartPage=function(){$scope.myform.startPage.showStart=!1,$scope.myform.form_fields.length>0&&($scope.selected._id=$scope.myform.form_fields[0]._id)},$scope.submitForm=function(){var _timeElapsed=TimeCounter.stopClock();$scope.loading=!0;var form=_.cloneDeep($scope.myform);form.timeElapsed=_timeElapsed,form.percentageComplete=$filter("formValidity")($scope.myform)/$scope.myform.visible_form_fields.length*100,delete form.visible_form_fields,setTimeout(function(){$scope.submitPromise=$http.post("/forms/"+$scope.myform._id,form).success(function(data,status,headers){$scope.myform.submitted=!0,$scope.loading=!1}).error(function(error){$scope.loading=!1,$scope.error=error.message})},500)},$scope.reloadForm()}]}}]),angular.module("forms").service("CurrentForm",function(){var _form={};this.getForm=function(){return _form},this.setForm=function(form){_form=form}}),angular.module("forms").service("FormFields",[function(){this.types=[{name:"textfield",value:"Short Text"},{name:"email",value:"Email"},{name:"radio",value:"Multiple Choice"},{name:"dropdown",value:"Dropdown"},{name:"date",value:"Date"},{name:"textarea",value:"Paragraph Text"},{name:"yes_no",value:"Yes/No"},{name:"legal",value:"Legal"},{name:"rating",value:"Rating"},{name:"link",value:"Link"},{name:"number",value:"Numbers"},{name:"statement",value:"Statement"}]}]),angular.module("forms").factory("Forms",["$resource",function($resource){return $resource("/forms/:formId",{formId:"@_id"},{query:{method:"GET",isArray:!0},get:{method:"GET",transformResponse:function(data,header){var form=angular.fromJson(data);return form.visible_form_fields=_.filter(form.form_fields,function(field){return field.deletePreserved===!1}),form}},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").factory("Submissions",["$resource",function($resource){return $resource("forms/:formID/submissions/:submissionId",{submissionId:"@_id",formId:"@_id"},{query:{method:"GET",isArray:!0},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").service("TimeCounter",[function(){var _startTime,_endTime,that=this;this.timeSpent=0,this.restartClock=function(){_startTime=Date.now(),_endTime=_startTime},this.stopClock=function(){return _startTime?(_endTime=Date.now(),that.timeSpent=Math.abs(_endTime.valueOf()-_startTime.valueOf())/1e3,that.timeSpent):new Error("Clock has not been started")},this.clockStarted=function(){return!!this._startTime}}]),angular.module("users").config(["$httpProvider",function($httpProvider){$httpProvider.interceptors.push(["$q","$location",function($q,$location){return{responseError:function(response){return"/users/me"!==$location.path()&&response.config&&"/users/me"!==response.config.url&&(console.log("intercepted rejection of ",response.config.url,response.status),401===response.status?($location.nextAfterLogin=$location.path(),$location.path("/signin")):403===response.status&&$location.path("/access_denied")),$q.reject(response)}}}])}]),angular.module("users").config(["$stateProvider",function($stateProvider){var checkLoggedin=function($q,$timeout,$state,User,Auth){var deferred=$q.defer();return Auth.currentUser&&Auth.currentUser.email?$timeout(deferred.resolve):Auth.currentUser=User.getCurrent(function(){Auth.login(),$timeout(deferred.resolve())},function(){Auth.logout(),$timeout(deferred.reject()),$state.go("sigin",{reload:!0})}),deferred.promise};checkLoggedin.$inject=["$q","$timeout","$state","User","Auth"],$stateProvider.state("profile",{resolve:{loggedin:checkLoggedin},url:"/settings/profile",templateUrl:"modules/users/views/settings/edit-profile.client.view.html"}).state("password",{resolve:{loggedin:checkLoggedin},url:"/settings/password",templateUrl:"modules/users/views/settings/change-password.client.view.html"}).state("accounts",{resolve:{loggedin:checkLoggedin},url:"/settings/accounts",templateUrl:"modules/users/views/settings/social-accounts.client.view.html"}).state("signup",{url:"/signup",templateUrl:"modules/users/views/authentication/signup.client.view.html"}).state("signup-success",{url:"/signup-success",templateUrl:"modules/users/views/authentication/signup-success.client.view.html"}).state("signin",{url:"/signin",templateUrl:"modules/users/views/authentication/signin.client.view.html"}).state("access_denied",{url:"/access_denied",templateUrl:"modules/users/views/authentication/access-denied.client.view.html"}).state("resendVerifyEmail",{url:"/verify",templateUrl:"modules/users/views/verify/resend-verify-email.client.view.html"}).state("verify",{url:"/verify/:token",templateUrl:"modules/users/views/verify/verify-account.client.view.html"}).state("forgot",{url:"/password/forgot",templateUrl:"modules/users/views/password/forgot-password.client.view.html"}).state("reset-invalid",{url:"/password/reset/invalid",templateUrl:"modules/users/views/password/reset-password-invalid.client.view.html"}).state("reset-success",{url:"/password/reset/success",templateUrl:"modules/users/views/password/reset-password-success.client.view.html"}).state("reset",{url:"/password/reset/:token",templateUrl:"modules/users/views/password/reset-password.client.view.html"})}]),angular.module("users").controller("AuthenticationController",["$scope","$location","$state","$rootScope","User","Auth",function($scope,$location,$state,$rootScope,User,Auth){$scope=$rootScope,$scope.credentials={},$scope.error="",$scope.signin=function(){$scope.credentials.email=$scope.credentials.username,User.login($scope.credentials).then(function(response){Auth.login(response),$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),"home"!==$state.previous.name&&"verify"!==$state.previous.name&&""!==$state.previous.name?$state.go($state.previous.name):$state.go("listForms")},function(error){$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user,$scope.error=error,console.log("loginError: "+error)})},$scope.signup=function(){console.log($scope.credentials),User.signup($scope.credentials).then(function(response){console.log("signup-success"),$state.go("signup-success")},function(error){console.log("Error: "),console.log(error),error?($scope.error=error,console.log(error)):console.log("No response received")})}}]),angular.module("users").controller("PasswordController",["$scope","$stateParams","$state","User",function($scope,$stateParams,$state,User){$scope.error="",$scope.askForPasswordReset=function(){User.askForPasswordReset($scope.credentials).then(function(response){$scope.success=response.message,$scope.credentials=null},function(error){$scope.error=error,$scope.credentials=null})},$scope.resetUserPassword=function(){$scope.success=$scope.error=null,User.resetPassword($scope.passwordDetails,$stateParams.token).then(function(response){$scope.success=response.message,$scope.passwordDetails=null,$state.go("reset-success")},function(error){$scope.error=error.message||error,$scope.passwordDetails=null})}}]),angular.module("users").controller("SettingsController",["$scope","$rootScope","$http","$state","Users",function($scope,$rootScope,$http,$state,Users){$scope.user=$rootScope.user,$scope.hasConnectedAdditionalSocialAccounts=function(provider){for(var i in $scope.user.additionalProvidersData)return!0;return!1},$scope.isConnectedSocialAccount=function(provider){return $scope.user.provider===provider||$scope.user.additionalProvidersData&&$scope.user.additionalProvidersData[provider]},$scope.removeUserSocialAccount=function(provider){$scope.success=$scope.error=null,$http["delete"]("/users/accounts",{params:{provider:provider}}).success(function(response){$scope.success=!0,$scope.user=response}).error(function(response){$scope.error=response.message})},$scope.updateUserProfile=function(isValid){if(isValid){$scope.success=$scope.error=null;var user=new Users($scope.user);user.$update(function(response){$scope.success=!0,$scope.user=response},function(response){$scope.error=response.data.message})}else $scope.submitted=!0},$scope.changeUserPassword=function(){$scope.success=$scope.error=null,$http.post("/users/password",$scope.passwordDetails).success(function(response){$scope.success=!0,$scope.passwordDetails=null}).error(function(response){$scope.error=response.message})}}]),angular.module("users").controller("VerifyController",["$scope","$state","$rootScope","User","Auth","$stateParams",function($scope,$state,$rootScope,User,Auth,$stateParams){$scope.isResetSent=!1,$scope.credentials={},$scope.error="",$scope.resendVerifyEmail=function(){User.resendVerifyEmail($scope.credentials.email).then(function(response){console.log(response),$scope.success=response.message,$scope.credentials=null,$scope.isResetSent=!0},function(error){$scope.error=error,$scope.credentials.email=null,$scope.isResetSent=!1})},$scope.validateVerifyToken=function(){$stateParams.token&&(console.log($stateParams.token),User.validateVerifyToken($stateParams.token).then(function(response){console.log("Success: "+response.message),$scope.success=response.message,$scope.isResetSent=!0,$scope.credentials.email=null},function(error){console.log("Error: "+error.message),$scope.isResetSent=!1,$scope.error=error,$scope.credentials.email=null}))}}]),angular.module("users").factory("Auth",["$window",function($window){var userState={isLoggedIn:!1},service={_currentUser:null,get currentUser(){return this._currentUser},ensureHasCurrentUser:function(User){return service._currentUser&&service._currentUser.username?service._currentUser:$window.user?(service._currentUser=$window.user,service._currentUser):void User.getCurrent().then(function(user){return service._currentUser=user,userState.isLoggedIn=!0,$window.user=service._currentUser,service._currentUser},function(response){return userState.isLoggedIn=!1,service._currentUser=null,$window.user=null,console.log("User.getCurrent() err",response),null})},isAuthenticated:function(){return!!service._currentUser},getUserState:function(){return userState},login:function(new_user){userState.isLoggedIn=!0,service._currentUser=new_user},logout:function(){$window.user=null,userState.isLoggedIn=!1,service._currentUser=null}};return service}]),angular.module("users").service("Authorizer",["APP_PERMISSIONS","USER_ROLES",function(APP_PERMISSIONS,USER_ROLES){return function(user){return{canAccess:function(permissions){var i,len,permission;for(angular.isArray(permissions)||(permissions=[permissions]),i=0,len=permissions.length;len>i;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}]),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var validTokenRe=/^([A-Za-z0-9]{48})$/g;if(!validTokenRe.test(token))throw new Error("Error token: "+token+" is not a valid verification token");var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file +myform:"="},controller:["$document","$window","$scope",function($document,$window,$scope){$scope.authentication=$rootScope.authentication,$scope.noscroll=!1,$scope.forms={},$scope.form_fields_count=$scope.myform.visible_form_fields.filter(function(field){return"statement"!==field.fieldType&&"rating"!==field.fieldType}).length,$scope.reloadForm=function(){$scope.myform.submitted=!1,$scope.myform.form_fields=_.chain($scope.myform.visible_form_fields).map(function(field){return field.fieldValue="",field}).value(),$scope.loading=!1,$scope.error="",$scope.selected={_id:"",index:0},$scope.setActiveField($scope.myform.visible_form_fields[0]._id,0,!1),TimeCounter.restartClock()},$window.onscroll=function(){$scope.scrollPos=document.body.scrollTop||document.documentElement.scrollTop||0;var elemBox=document.getElementsByClassName("activeField")[0].getBoundingClientRect();$scope.fieldTop=elemBox.top,$scope.fieldBottom=elemBox.bottom;var field_id,field_index;$scope.noscroll||($scope.selected.index===$scope.myform.form_fields.length-1&&$scope.fieldBottom<200?(field_index=$scope.selected.index+1,field_id="submit_field",$scope.setActiveField(field_id,field_index,!1)):$scope.selected.index===$scope.myform.form_fields.length?$scope.fieldTop>200&&(field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)):$scope.fieldBottom<0?(field_index=$scope.selected.index+1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)):0!==$scope.selected.index&&$scope.fieldTop>0&&(field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)),$scope.$apply())},$scope.setActiveField=$rootScope.setActiveField=function(field_id,field_index,animateScroll){null!==$scope.selected&&$scope.selected._id!==field_id&&($scope.selected._id=field_id,$scope.selected.index=field_index,animateScroll&&($scope.noscroll=!0,setTimeout(function(){$document.scrollToElement(angular.element(".activeField"),-10,200).then(function(){$scope.noscroll=!1,document.querySelectorAll(".activeField .focusOn")[0].focus()})},20)))},$rootScope.nextField=$scope.nextField=function(){if($scope.selected.index<$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id=$scope.myform.form_fields[selected_index]._id;$rootScope.setActiveField(selected_id,selected_index,!0)}else if($scope.selected.index===$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id="submit_field";$rootScope.setActiveField(selected_id,selected_index,!0)}},$rootScope.prevField=$scope.prevField=function(){if($scope.selected.index>0){var selected_index=$scope.selected.index-1,selected_id=$scope.myform.form_fields[selected_index]._id;$scope.setActiveField(selected_id,selected_index,!0)}},$scope.exitStartPage=function(){$scope.myform.startPage.showStart=!1,$scope.myform.form_fields.length>0&&($scope.selected._id=$scope.myform.form_fields[0]._id)},$scope.submitForm=function(){var _timeElapsed=TimeCounter.stopClock();$scope.loading=!0;var form=_.cloneDeep($scope.myform);form.timeElapsed=_timeElapsed,form.percentageComplete=$filter("formValidity")($scope.myform)/$scope.myform.visible_form_fields.length*100,delete form.visible_form_fields,setTimeout(function(){$scope.submitPromise=$http.post("/forms/"+$scope.myform._id,form).success(function(data,status,headers){$scope.myform.submitted=!0,$scope.loading=!1}).error(function(error){$scope.loading=!1,$scope.error=error.message})},500)},$scope.reloadForm()}]}}]),angular.module("forms").service("CurrentForm",function(){var _form={};this.getForm=function(){return _form},this.setForm=function(form){_form=form}}),angular.module("forms").service("FormFields",[function(){this.types=[{name:"textfield",value:"Short Text"},{name:"email",value:"Email"},{name:"radio",value:"Multiple Choice"},{name:"dropdown",value:"Dropdown"},{name:"date",value:"Date"},{name:"textarea",value:"Paragraph Text"},{name:"yes_no",value:"Yes/No"},{name:"legal",value:"Legal"},{name:"rating",value:"Rating"},{name:"link",value:"Link"},{name:"number",value:"Numbers"},{name:"statement",value:"Statement"}]}]),angular.module("forms").factory("Forms",["$resource",function($resource){return $resource("/forms/:formId",{formId:"@_id"},{query:{method:"GET",isArray:!0},get:{method:"GET",transformResponse:function(data,header){var form=angular.fromJson(data);return form.visible_form_fields=_.filter(form.form_fields,function(field){return field.deletePreserved===!1}),form}},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").factory("Submissions",["$resource",function($resource){return $resource("forms/:formID/submissions/:submissionId",{submissionId:"@_id",formId:"@_id"},{query:{method:"GET",isArray:!0},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").service("TimeCounter",[function(){var _startTime,_endTime,that=this;this.timeSpent=0,this.restartClock=function(){_startTime=Date.now(),_endTime=_startTime},this.stopClock=function(){return _startTime?(_endTime=Date.now(),that.timeSpent=Math.abs(_endTime.valueOf()-_startTime.valueOf())/1e3,that.timeSpent):new Error("Clock has not been started")},this.clockStarted=function(){return!!this._startTime}}]),angular.module("users").config(["$httpProvider",function($httpProvider){$httpProvider.interceptors.push(["$q","$location",function($q,$location){return{responseError:function(response){return"/users/me"!==$location.path()&&response.config&&"/users/me"!==response.config.url&&(console.log("intercepted rejection of ",response.config.url,response.status),401===response.status?($location.nextAfterLogin=$location.path(),$location.path("/signin")):403===response.status&&$location.path("/access_denied")),$q.reject(response)}}}])}]),angular.module("users").config(["$stateProvider",function($stateProvider){var checkLoggedin=function($q,$timeout,$state,User,Auth){var deferred=$q.defer();return console.log(Auth.ensureHasCurrentUser(User)),Auth.currentUser&&Auth.currentUser.email?$timeout(deferred.resolve):Auth.currentUser=User.getCurrent(function(){Auth.login(),$timeout(deferred.resolve())},function(){Auth.logout(),$timeout(deferred.reject()),$state.go("sigin",{reload:!0})}),deferred.promise};checkLoggedin.$inject=["$q","$timeout","$state","User","Auth"];var checkSignupDisabled=function($window,$timeout,$q){console.log($window.signupDisabled);var deferred=$q.defer();return $timeout(deferred.reject()),deferred.promise};checkSignupDisabled.$inject=["$window","$timeout","$q"],$stateProvider.state("profile",{resolve:{loggedin:checkLoggedin},url:"/settings/profile",templateUrl:"modules/users/views/settings/edit-profile.client.view.html"}).state("password",{resolve:{loggedin:checkLoggedin},url:"/settings/password",templateUrl:"modules/users/views/settings/change-password.client.view.html"}).state("accounts",{resolve:{loggedin:checkLoggedin},url:"/settings/accounts",templateUrl:"modules/users/views/settings/social-accounts.client.view.html"}).state("signup",{resolve:{isDisabled:checkSignupDisabled},url:"/signup",templateUrl:"modules/users/views/authentication/signup.client.view.html"}).state("signup-success",{resolve:{isDisabled:checkSignupDisabled},url:"/signup-success",templateUrl:"modules/users/views/authentication/signup-success.client.view.html"}).state("signin",{url:"/signin",templateUrl:"modules/users/views/authentication/signin.client.view.html"}).state("access_denied",{url:"/access_denied",templateUrl:"modules/users/views/authentication/access-denied.client.view.html"}).state("resendVerifyEmail",{url:"/verify",templateUrl:"modules/users/views/verify/resend-verify-email.client.view.html"}).state("verify",{url:"/verify/:token",templateUrl:"modules/users/views/verify/verify-account.client.view.html"}).state("forgot",{url:"/password/forgot",templateUrl:"modules/users/views/password/forgot-password.client.view.html"}).state("reset-invalid",{url:"/password/reset/invalid",templateUrl:"modules/users/views/password/reset-password-invalid.client.view.html"}).state("reset-success",{url:"/password/reset/success",templateUrl:"modules/users/views/password/reset-password-success.client.view.html"}).state("reset",{url:"/password/reset/:token",templateUrl:"modules/users/views/password/reset-password.client.view.html"})}]),angular.module("users").controller("AuthenticationController",["$scope","$location","$state","$rootScope","User","Auth",function($scope,$location,$state,$rootScope,User,Auth){$scope=$rootScope,$scope.credentials={},$scope.error="",$scope.signin=function(){$scope.credentials.email=$scope.credentials.username,User.login($scope.credentials).then(function(response){Auth.login(response),$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),"home"!==$state.previous.name&&"verify"!==$state.previous.name&&""!==$state.previous.name?$state.go($state.previous.name):$state.go("listForms")},function(error){$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user,$scope.error=error,console.log("loginError: "+error)})},$scope.signup=function(){console.log($scope.credentials),User.signup($scope.credentials).then(function(response){console.log("signup-success"),$state.go("signup-success")},function(error){console.log("Error: "),console.log(error),error?($scope.error=error,console.log(error)):console.log("No response received")})}}]),angular.module("users").controller("PasswordController",["$scope","$stateParams","$state","User",function($scope,$stateParams,$state,User){$scope.error="",$scope.askForPasswordReset=function(){User.askForPasswordReset($scope.credentials).then(function(response){$scope.success=response.message,$scope.credentials=null},function(error){$scope.error=error,$scope.credentials=null})},$scope.resetUserPassword=function(){$scope.success=$scope.error=null,User.resetPassword($scope.passwordDetails,$stateParams.token).then(function(response){$scope.success=response.message,$scope.passwordDetails=null,$state.go("reset-success")},function(error){$scope.error=error.message||error,$scope.passwordDetails=null})}}]),angular.module("users").controller("SettingsController",["$scope","$rootScope","$http","$state","Users",function($scope,$rootScope,$http,$state,Users){$scope.user=$rootScope.user,$scope.hasConnectedAdditionalSocialAccounts=function(provider){for(var i in $scope.user.additionalProvidersData)return!0;return!1},$scope.isConnectedSocialAccount=function(provider){return $scope.user.provider===provider||$scope.user.additionalProvidersData&&$scope.user.additionalProvidersData[provider]},$scope.removeUserSocialAccount=function(provider){$scope.success=$scope.error=null,$http["delete"]("/users/accounts",{params:{provider:provider}}).success(function(response){$scope.success=!0,$scope.user=response}).error(function(response){$scope.error=response.message})},$scope.updateUserProfile=function(isValid){if(isValid){$scope.success=$scope.error=null;var user=new Users($scope.user);user.$update(function(response){$scope.success=!0,$scope.user=response},function(response){$scope.error=response.data.message})}else $scope.submitted=!0},$scope.changeUserPassword=function(){$scope.success=$scope.error=null,$http.post("/users/password",$scope.passwordDetails).success(function(response){$scope.success=!0,$scope.passwordDetails=null}).error(function(response){$scope.error=response.message})}}]),angular.module("users").controller("VerifyController",["$scope","$state","$rootScope","User","Auth","$stateParams",function($scope,$state,$rootScope,User,Auth,$stateParams){$scope.isResetSent=!1,$scope.credentials={},$scope.error="",$scope.resendVerifyEmail=function(){User.resendVerifyEmail($scope.credentials.email).then(function(response){console.log(response),$scope.success=response.message,$scope.credentials=null,$scope.isResetSent=!0},function(error){$scope.error=error,$scope.credentials.email=null,$scope.isResetSent=!1})},$scope.validateVerifyToken=function(){$stateParams.token&&(console.log($stateParams.token),User.validateVerifyToken($stateParams.token).then(function(response){console.log("Success: "+response.message),$scope.success=response.message,$scope.isResetSent=!0,$scope.credentials.email=null},function(error){console.log("Error: "+error.message),$scope.isResetSent=!1,$scope.error=error,$scope.credentials.email=null}))}}]),angular.module("users").factory("Auth",["$window",function($window){var userState={isLoggedIn:!1},service={_currentUser:null,get currentUser(){return this._currentUser},ensureHasCurrentUser:function(User){return service._currentUser&&service._currentUser.username?service._currentUser:$window.user?(service._currentUser=$window.user,service._currentUser):void User.getCurrent().then(function(user){return service._currentUser=user,userState.isLoggedIn=!0,$window.user=service._currentUser,service._currentUser},function(response){return userState.isLoggedIn=!1,service._currentUser=null,$window.user=null,console.log("User.getCurrent() err",response),null})},isAuthenticated:function(){return!!service._currentUser},getUserState:function(){return userState},login:function(new_user){userState.isLoggedIn=!0,service._currentUser=new_user},logout:function(){$window.user=null,userState.isLoggedIn=!1,service._currentUser=null}};return service}]),angular.module("users").service("Authorizer",["APP_PERMISSIONS","USER_ROLES",function(APP_PERMISSIONS,USER_ROLES){return function(user){return{canAccess:function(permissions){var i,len,permission;for(angular.isArray(permissions)||(permissions=[permissions]),i=0,len=permissions.length;len>i;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}]),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var validTokenRe=/^([A-Za-z0-9]{48})$/g;if(!validTokenRe.test(token))throw new Error("Error token: "+token+" is not a valid verification token");var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file diff --git a/public/modules/core/controllers/header.client.controller.js b/public/modules/core/controllers/header.client.controller.js index 120b43e3..b6c28eb1 100755 --- a/public/modules/core/controllers/header.client.controller.js +++ b/public/modules/core/controllers/header.client.controller.js @@ -1,7 +1,9 @@ 'use strict'; -angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User', - function ($rootScope, $scope, Menus, $state, Auth, User) { +angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User', '$window' + function ($rootScope, $scope, Menus, $state, Auth, User, $window) { + $rootScope.signupDisabled = $window.signupDisabled; + $scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User); $scope.authentication = $rootScope.authentication = Auth; diff --git a/public/modules/core/views/header.client.view.html b/public/modules/core/views/header.client.view.html index 6fe702be..f792353e 100755 --- a/public/modules/core/views/header.client.view.html +++ b/public/modules/core/views/header.client.view.html @@ -27,7 +27,7 @@
-   or  - Sign up + + + +   or  + Sign up +
- \ No newline at end of file + From ca0ebe8c658af4380cf850a1319926426c4aa1fe Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Tue, 10 May 2016 00:41:10 -0700 Subject: [PATCH 4/8] got signup disabled to work --- app/views/layout.server.view.html | 2 +- public/dist/application.js | 24 ++++++++++++------- public/dist/application.min.js | 8 +++---- .../controllers/header.client.controller.js | 2 +- .../core/views/header.client.view.html | 2 +- .../users/config/users.client.routes.js | 5 ++-- .../authentication/signin.client.view.html | 2 +- scripts/setup.js | 9 ++----- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/app/views/layout.server.view.html b/app/views/layout.server.view.html index 16e8532f..eb4691ba 100755 --- a/app/views/layout.server.view.html +++ b/app/views/layout.server.view.html @@ -79,7 +79,7 @@ diff --git a/public/dist/application.js b/public/dist/application.js index c825a76a..e2d91e2b 100644 --- a/public/dist/application.js +++ b/public/dist/application.js @@ -1,7 +1,7 @@ angular.module('NodeForm.templates', []).run(['$templateCache', function($templateCache) { "use strict"; $templateCache.put("../public/modules/core/views/header.client.view.html", - "
"); + "
"); $templateCache.put("../public/modules/core/views/home.client.view.html", "

TellForm

Craft beautiful forms in seconds.

Craft beautiful forms.

TellForm is an opensource alternative to TypeForm that can create stunning forms from PDFs or from scratch

TellForm is an opensource alternative to TypeForm that can create stunning forms from PDFs or from scratch

Create your next ______.

Tell a story with a form.

"); $templateCache.put("../public/modules/forms/views/admin-form.client.view.html", @@ -293,7 +293,7 @@ angular.module('NodeForm.templates', []).run(['$templateCache', function($templa $templateCache.put("../public/modules/users/views/authentication/access-denied.client.view.html", "

You need to be logged in to access this page

Login
"); $templateCache.put("../public/modules/users/views/authentication/signin.client.view.html", - "

Sign into your account

Error:
  or  Sign up
"); + "

Sign into your account

Error:
  or  Sign up
"); $templateCache.put("../public/modules/users/views/authentication/signup-success.client.view.html", "

Signup Successful

You've successfully registered an account at TellForm.

But your account is not activated yet



Before you continue, make sure to check your email for our verification. If you don't receive it within 24h drop us a line at hi@TellForm.com

"); $templateCache.put("../public/modules/users/views/authentication/signup.client.view.html", @@ -458,8 +458,10 @@ angular.module('core').config(['$stateProvider', '$urlRouterProvider', 'use strict'; -angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User', - function ($rootScope, $scope, Menus, $state, Auth, User) { +angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User', '$window', + function ($rootScope, $scope, Menus, $state, Auth, User, $window) { + $rootScope.signupDisabled = $window.signupDisabled; + $scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User); $scope.authentication = $rootScope.authentication = Auth; @@ -2181,7 +2183,7 @@ angular.module('users').config(['$stateProvider', var checkLoggedin = function($q, $timeout, $state, User, Auth) { var deferred = $q.defer(); - console.log(Auth.ensureHasCurrentUser(User)); + //console.log(Auth.ensureHasCurrentUser(User)); if (Auth.currentUser && Auth.currentUser.email) { $timeout(deferred.resolve); @@ -2194,7 +2196,7 @@ angular.module('users').config(['$stateProvider', function() { Auth.logout(); $timeout(deferred.reject()); - $state.go('sigin', {reload: true}); + $state.go('signin', {reload: true}); }); } @@ -2203,11 +2205,15 @@ angular.module('users').config(['$stateProvider', checkLoggedin.$inject = ["$q", "$timeout", "$state", "User", "Auth"]; var checkSignupDisabled = function($window, $timeout, $q) { - console.log($window.signupDisabled); var deferred = $q.defer(); - $timeout(deferred.reject()); + console.log($window.signupDisabled); + if($window.signupDisabled) { + $timeout(deferred.reject()); + }else{ + console.log('resolved'); + $timeout(deferred.resolve()); + } return deferred.promise; - //return !$window.signupDisabled; }; checkSignupDisabled.$inject = ["$window", "$timeout", "$q"]; diff --git a/public/dist/application.min.js b/public/dist/application.min.js index 37b88696..7a620f0b 100644 --- a/public/dist/application.min.js +++ b/public/dist/application.min.js @@ -1,4 +1,4 @@ -function removeDateFieldsFunc(o){function eachObject(v,k){"lastModified"!==k&&"created"!==k||delete clone[i][k]}for(var clone=_.clone(o),i=0;i'),$templateCache.put("../public/modules/core/views/home.client.view.html",'

Craft beautiful forms in seconds.

Create your next ______.

Tell a story with a form.

'),$templateCache.put("../public/modules/forms/views/admin-form.client.view.html",'
'),$templateCache.put("../public/modules/forms/views/list-forms.client.view.html",'

Create a new form
Name
Language

'),$templateCache.put("../public/modules/forms/views/submit-form.client.view.html","
"),$templateCache.put("../public/modules/forms/views/adminTabs/analyze.html",""),$templateCache.put("../public/modules/forms/views/adminTabs/configure.html",""),$templateCache.put("../public/modules/forms/views/adminTabs/create.html",""),$templateCache.put("../public/modules/forms/views/adminTabs/design.html",'
Background Color
Question Text Color
Answer Text Color
Button Background Color
Button Text Color
'),$templateCache.put("../public/modules/forms/views/directiveViews/cgBusy/update-form-message-TypeA.html",'
{{$message}}
'),$templateCache.put("../public/modules/forms/views/directiveViews/cgBusy/update-form-message-TypeB.html",'
{{$message}}
'),$templateCache.put("../public/modules/forms/views/directiveViews/entryPage/startPage.html",'

{{pageData.introTitle}}

{{pageData.introParagraph}}

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/date.html",'

{{field.title}} optional

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/dropdown.html",'
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/file.html",'
{{field.title}} (* required)
{{field.file.originalname}}
Upload your File
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/hidden.html",''),$templateCache.put("../public/modules/forms/views/directiveViews/field/legal.html",'
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/radio.html",'

{{field.title}} optional


'),$templateCache.put("../public/modules/forms/views/directiveViews/field/rating.html",'

{{field.title}} optional

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/statement.html",'

{{field.title}}

{{field.description}}


'),$templateCache.put("../public/modules/forms/views/directiveViews/field/textarea.html",'

{{field.title}} optional

press ENTER
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/textfield.html",'

{{field.title}} (optional)

press ENTER
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/yes_no.html",'

{{field.title}} *(required)

{{field.description}}


'),$templateCache.put("../public/modules/forms/views/directiveViews/form/configure-form.client.view.html",'
Save Submissions as PDFs?
Upload Your PDF Template
{{myform.pdf.name}}
Upload your PDF
Autogenerate Form?
Use Oscarhost API?
Oscarhost API Username
Oscarhost API Password
Oscarhost API URL
Oscarhost API Update Type
Form Name
Form Status
Language
* required
Display Form Footer?
Display Start Page?
'), -$templateCache.put("../public/modules/forms/views/directiveViews/form/edit-form.client.view.html",'

Edit Start Page


Intro Title:
Intro Paragraph:
\n
\n\n

\n
\n
Options:
\n
\n
\n \n\n \n \n \n
\n
\n \n
\n
\n
\n\n

\n\n
\n
Required:
\n
\n \n\n \n
\n
\n\n
\n
Disabled:
\n
\n \n\n \n
\n
\n\n
\n \n\n
\n
\n

\n Click on Fields to add them here\n

\n
\n
\n\n
\n \n
\n\n \n \n\n \n
\n
\n\n'),$templateCache.put("../public/modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html",'
#{{value.title}}OscarEMR User ProfilePercentage CompleteTime ElapsedDeviceLocationIP AddressDate Submitted (UTC)Generated PDF
{{$index+1}}{{field.fieldValue}}User Profile #{{row.oscarDemoNum}}{{row.percentageComplete}}%{{row.timeElapsed}}{{row.device.name}}, {{row.device.type}}{{row.geoLocation.city}}, {{row.geoLocation.country}}{{row.ipAddr}}{{row.created | date:\'yyyy-MM-dd HH:mm:ss\'}}Generated PDF
'),$templateCache.put("../public/modules/forms/views/directiveViews/form/submit-form.client.view.html",'
press ENTER
'),$templateCache.put("../public/modules/users/views/authentication/access-denied.client.view.html",'

You need to be logged in to access this page

Login
'),$templateCache.put("../public/modules/users/views/authentication/signin.client.view.html",'

Sign into your account

'),$templateCache.put("../public/modules/users/views/authentication/signup-success.client.view.html",''),$templateCache.put("../public/modules/users/views/authentication/signup.client.view.html",''),$templateCache.put("../public/modules/users/views/password/forgot-password.client.view.html",'

Restore your password

Enter your account email.

'),$templateCache.put("../public/modules/users/views/password/reset-password-invalid.client.view.html",'

Password reset is invalid

Ask for a new password reset
'),$templateCache.put("../public/modules/users/views/password/reset-password-success.client.view.html",'

Password successfully reset

Continue to home page
'),$templateCache.put("../public/modules/users/views/password/reset-password.client.view.html",'

Reset your password

'),$templateCache.put("../public/modules/users/views/settings/change-password.client.view.html",'

Change your password

'),$templateCache.put("../public/modules/users/views/settings/edit-profile.client.view.html",'

Edit your profile

'), -$templateCache.put("../public/modules/users/views/settings/social-accounts.client.view.html",'

Connected social accounts:

Connect other social accounts:

'),$templateCache.put("../public/modules/users/views/verify/resend-verify-email.client.view.html",'

Resend your account verification email

Enter your account email.

{{error}}

Verification Email has been Sent

A verification email has been sent to {{username}}.
But your account is still not activated yet

Check your email and click on the activation link to activate your account. If you have any questions drop us a line at hi@TellForm.com

'),$templateCache.put("../public/modules/users/views/verify/verify-account.client.view.html",'

Account successfuly activated

Continue to login page

Verification link is invalid or has expired

Resend your verification email Signin to your account
')}]);var ApplicationConfiguration=function(){var applicationModuleName="NodeForm",applicationModuleVendorDependencies=["duScroll","ui.select","cgBusy","ngSanitize","vButton","ngResource","NodeForm.templates","ui.router","ui.bootstrap","ui.utils"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","$state","$stateParams",function($rootScope,Auth,$state,$stateParams){$rootScope.$state=$state,$rootScope.$stateParams=$stateParams,$rootScope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState){$state.previous=fromState,"home"===toState.name||"signin"===toState.name||"resendVerifyEmail"===toState.name||"verify"===toState.name||"signup"===toState.name||"signup-success"===toState.name?Auth.isAuthenticated()&&(event.preventDefault(),$state.go("listForms")):"access_denied"===toState.name||Auth.isAuthenticated()||"submitForm"===toState.name||(event.preventDefault(),$state.go("listForms"))})}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","User","Authorizer","$state","$stateParams",function($rootScope,Auth,User,Authorizer,$state,$stateParams){$rootScope.$on("$stateChangeStart",function(event,next){var authenticator,permissions,user;permissions=next&&next.data&&next.data.permissions?next.data.permissions:null,Auth.ensureHasCurrentUser(User),user=Auth.currentUser,user&&(authenticator=new Authorizer(user),null!=permissions&&(authenticator.canAccess(permissions)||(event.preventDefault(),$state.go("access_denied"))))})}]),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.router.tabs","colorpicker.module","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/forms")}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User",function($rootScope,$scope,Menus,$state,Auth,User){$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["english","french","spanish"],$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("listForms")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").controller("HomeController",["$rootScope","$scope","User","$state",function($rootScope,$scope,User,$state){$scope=$rootScope}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field&&"statement"!==field.fieldType&&"rating"!==field.fieldType?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",["$delegate",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate}])}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/views/list-forms.client.view.html"}).state("submitForm",{url:"/forms/:formId",templateUrl:"modules/forms/views/submit-form.client.view.html",data:{hideNav:!0},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"SubmitFormController",controllerAs:"ctrl"}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/views/admin-form.client.view.html",data:{permissions:["editForm"]},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"AdminFormController"}).state("viewForm.configure",{url:"/configure",templateUrl:"modules/forms/views/adminTabs/configure.html"}).state("viewForm.design",{url:"/design",templateUrl:"modules/forms/views/adminTabs/design.html"}).state("viewForm.analyze",{url:"/analyze",templateUrl:"modules/forms/views/adminTabs/analyze.html"}).state("viewForm.create",{url:"/create",templateUrl:"modules/forms/views/adminTabs/create.html"})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$uibModal","myForm",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$uibModal,myForm){$scope=$rootScope,$scope.animationsEnabled=!0,$scope.myform=myForm,$rootScope.saveInProgress=!1,CurrentForm.setForm($scope.myform),$scope.tabData=[{heading:"Create",route:"viewForm.create"},{heading:"Design",route:"viewForm.design"},{heading:"Configure",route:"viewForm.configure"},{heading:"Analyze",route:"viewForm.analyze"}],$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.openDeleteModal=function(){$scope.deleteModal=$uibModal.open({animation:$scope.animationsEnabled,templateUrl:"myModalContent.html",controller:"AdminFormController",resolve:{myForm:function(){return $scope.myform}}}),$scope.deleteModal.result.then(function(selectedItem){$scope.selected=selectedItem},function(){console.log("Modal dismissed at: "+new Date)})},$scope.cancelDeleteModal=function(){$scope.deleteModal&&$scope.deleteModal.dismiss("cancel")},$scope.removeCurrentForm=function(){if($scope.deleteModal&&$scope.deleteModal.opened){$scope.deleteModal.close();var form_id=$scope.myform._id;if(!form_id)throw new Error("Error - removeCurrentForm(): $scope.myform._id does not exist");$http["delete"]("/forms/"+form_id).success(function(data,status,headers){console.log("form deleted successfully"),$state.go("listForms",{},{reload:!0})}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}},$scope.update=$rootScope.update=function(updateImmediately,cb){var continueUpdate=!0;if(updateImmediately||(continueUpdate=!$rootScope.saveInProgress),continueUpdate){var err=null;updateImmediately||($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),err=response.data})["finally"](function(){return updateImmediately||($rootScope.saveInProgress=!1),"function"==typeof cb?cb(err):void 0})}}}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$scope.forms={},$scope.showCreateModal=!1,$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$scope.showCreateModal||($scope.showCreateModal=!0)},$scope.closeCreateModal=function(){$scope.showCreateModal&&($scope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicateForm=function(form_index){var form=_.cloneDeep($scope.myforms[form_index]);delete form._id,$http.post("/forms",{form:form}).success(function(data,status,headers){$scope.myforms.splice(form_index+1,0,data)}).error(function(errorResponse){console.error(errorResponse),null===errorResponse&&($scope.error=errorResponse.data.message)})},$scope.createNewForm=function(){var form={};form.title=$scope.forms.createForm.title.$modelValue,form.language=$scope.forms.createForm.language.$modelValue,$scope.forms.createForm.$valid&&$scope.forms.createForm.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("new form created"),$scope.goToWithId("viewForm.create",data._id+"")}).error(function(errorResponse){console.error(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeForm=function(form_index){if(form_index>=$scope.myforms.length||0>form_index)throw new Error("Error: form_index in removeForm() must be between 0 and "+$scope.myforms.length-1);$http["delete"]("/forms/"+$scope.myforms[form_index]._id).success(function(data,status,headers){console.log("form deleted successfully"),$scope.myforms.splice(form_index,1)}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}}]),angular.module("forms").controller("SubmitFormController",["$scope","$rootScope","$state","myForm","Auth",function($scope,$rootScope,$state,myForm,Auth){$scope.authentication=Auth,$scope.myform=myForm,$scope.myform.isLive?$scope.hideNav=$rootScope.hideNav=!0:$scope.authentication.isAuthenticated()?$scope.hideNav=$rootScope.hideNav=!1:($scope.hideNav=$rootScope.hideNav=!0,$state.go("access_denied"))}]),_.mixin({removeDateFields:removeDateFieldsFunc}),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFields Started",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFields Finished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!0,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine(),$formCtrl.$setUntouched())})};$scope.$watch(function(newValue,oldValue){console.log("introParagraphStartPage.$dirty: "+$scope.editForm.introParagraphStartPage.$dirty),console.log("introParagraphStartPage.$touched: "+$scope.editForm.introParagraphStartPage.$touched),$rootScope.finishedRender&&$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&(console.log("Form saving started"),debounceSave(),console.log("introParagraphStartPage.$dirty AFTER: "+$scope.editForm.introParagraphStartPage.$dirty))}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){newValue=angular.copy(newValue),oldValue=angular.copy(oldValue),newValue.form_fields=_.removeDateFields(newValue.form_fields),oldValue.form_fields=_.removeDateFields(oldValue.form_fields);var changedFields=!_.isEqual(oldValue.form_fields,newValue.form_fields)||!_.isEqual(oldValue.startPage,newValue.startPage),changedFieldMap=!1;oldValue.hasOwnProperty("plugins.oscarhost.settings.fieldMap")&&(changedFieldMap=!!oldValue.plugins.oscarhost.settings.fieldMap&&!_.isEqual(oldValue.plugins.oscarhost.settings.fieldMap,newValue.plugins.oscarhost.settings.fieldMap)),(newValue||oldValue)&&oldValue&&(0===oldValue.form_fields.length&&($rootScope.finishedRender=!0),$rootScope.finishedRender&&(changedFields&&!$formCtrl.$dirty||changedFieldMap)&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","CurrentForm",function($rootScope,$http,Upload,CurrentForm){return{templateUrl:"modules/forms/views/directiveViews/form/configure-form.client.view.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:["$scope",function($scope){console.log($scope.myform),CurrentForm.getForm().plugins?CurrentForm.getForm().plugins.oscarhost.baseUrl&&($scope.oscarhostAPI=!0):$scope.oscarhostAPI=!1,$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages,this._current_upload=null,$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update,this._unbindedPdfFields=$scope.pdfFields,$scope.cancelUpload=function(){this._current_upload.abort(),$scope.pdfLoading=!1,$scope.removePDF()},$scope.removePDF=function(){$scope.myform.pdf=null,$scope.myform.isGenerated=!1,$scope.myform.autofillPDFs=!1,console.log("form.pdf: "+$scope.myform.pdf+" REMOVED")},$scope.uploadPDF=function(file){file&&(console.log(file),Upload.upload({url:"/upload/pdf",data:{user:$scope.user,file:file}}).then(function(resp){var data=resp.data;$scope.log="file "+data.originalname+" uploaded as "+data.filename+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()},function(resp){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(resp.status)},function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total,10);$scope.log="progress: "+progressPercentage+"% "+evt.config.data.file.name+"\n"+$scope.log,console.log($scope.log),$scope.pdfLoading=!0}))}}]}}]),angular.module("forms").directive("editFormDirective",["$rootScope","FormFields",function($rootScope,FormFields){return{templateUrl:"modules/forms/views/directiveViews/form/edit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:["$scope",function($scope){for(var field_ids=_($scope.myform.form_fields).pluck("_id"),i=0;i0){$scope.myform.plugins.oscarhost.settings.fieldMap||($scope.myform.plugins.oscarhost.settings.fieldMap={});var oscarhostFields=$scope.myform.plugins.oscarhost.settings.validFields,currentFields=_($scope.myform.plugins.oscarhost.settings.fieldMap).invert().keys().value();return $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id)&&(currentFields=_(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id])),_(oscarhostFields).difference(currentFields).value()}return[]},$scope.dropzone={handle:" .handle",containment:".dropzoneContainer",cursor:"grabbing"},$scope.addNewField=function(modifyForm,fieldType){$scope.addField.lastAddedID++;for(var fieldTitle,i=0;i<$scope.addField.types.length;i++)if($scope.addField.types[i].name===fieldType){$scope.addField.types[i].lastAddedID++,fieldTitle=$scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;break}var newField={title:fieldTitle,fieldType:fieldType,fieldValue:"",required:!0,disabled:!1,deletePreserved:!1};return modifyForm&&$scope.myform.form_fields.push(newField),newField},$scope.deleteField=function(field_index){var currFieldId=$scope.myform.form_fields[field_index]._id;$scope.myform.hasOwnProperty("plugins.oscarhost.baseUrl")&&delete $scope.myform.plugins.oscarhost.settings.fieldMap[currFieldId],$scope.myform.form_fields.splice(field_index,1)},$scope.duplicateField=function(field_index){var currField=_.cloneDeep($scope.myform.form_fields[field_index]);currField._id="cloned"+_.uniqueId(),currField.title+=" copy",$scope.myform.form_fields.splice(field_index+1,0,currField)},$scope.addButton=function(){var newButton={};newButton.bgColor="#ddd",newButton.color="#ffffff",newButton.text="Button",newButton._id=Math.floor(1e5*Math.random()),$scope.myform.startPage.buttons.push(newButton)},$scope.deleteButton=function(button){for(var currID,i=0;i<$scope.myform.startPage.buttons.length;i++)if(currID=$scope.myform.startPage.buttons[i]._id,console.log(currID),currID===button._id){$scope.myform.startPage.buttons.splice(i,1);break}},$scope.addOption=function(field_index){var currField=$scope.myform.form_fields[field_index];if(console.log(field_index),console.log(currField),"checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType){currField.fieldOptions||($scope.myform.form_fields[field_index].fieldOptions=[]);var lastOptionID=0;currField.fieldOptions[currField.fieldOptions.length-1]&&(lastOptionID=currField.fieldOptions[currField.fieldOptions.length-1].option_id);var newOption={option_id:Math.floor(1e5*Math.random()),option_title:"Option "+lastOptionID,option_value:"Option "+lastOptionID};$scope.myform.form_fields[field_index].fieldOptions.push(newOption)}},$scope.deleteOption=function(field_index,option){var currField=$scope.myform.form_fields[field_index];if("checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType)for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:["$scope",function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}]}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope","$templateCache",function($http,$compile,$rootScope,$templateCache){var getTemplateUrl=function(fieldType){var type=fieldType,templateUrl="modules/forms/views/directiveViews/field/",supported_fields=["textfield","textarea","date","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0&&(templateUrl=templateUrl+type+".html"),$templateCache.get("../public/"+templateUrl)};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&",design:"=",index:"=",forms:"="},link:function(scope,element){$rootScope.chooseDefaultOption=scope.chooseDefaultOption=function(type){"yes_no"===type?scope.field.fieldValue="true":"rating"===type?scope.field.fieldValue=0:"radio"===scope.field.fieldType?(console.log(scope.field),scope.field.fieldValue=scope.field.fieldOptions[0].option_value,console.log(scope.field.fieldValue)):"legal"===type&&(scope.field.fieldValue="true",$rootScope.nextField())},scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType&&(scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0});var fieldType=scope.field.fieldType;if("number"===scope.field.fieldType||"textfield"===scope.field.fieldType||"email"===scope.field.fieldType||"link"===scope.field.fieldType){switch(scope.field.fieldType){case"textfield":scope.field.input_type="text";break;case"email":scope.field.input_type="email",scope.field.placeholder="joesmith@example.com";break;case"number":scope.field.input_type="text",scope.field.validateRegex=/^\d+$/;break;default:scope.field.input_type="url",scope.field.placeholder="http://example.com"}fieldType="textfield"}var template=getTemplateUrl(fieldType);element.html(template).show(),$compile(element.contents())(scope)}}}]),angular.module("forms").directive("onEnterKey",["$rootScope",function($rootScope){return{restrict:"A",link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode;13===keyCode&&($rootScope.$apply(function(){$rootScope.$eval($attrs.onEnterKey)}),event.preventDefault())})}}}]),angular.module("forms").directive("onFinishRender",["$rootScope","$timeout",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")||element.attr("data-ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$first&&!scope.$last?scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Started")}):scope.$last&&scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Finished")})}}}}]),angular.module("forms").directive("submitFormDirective",["$http","TimeCounter","$filter","$rootScope","Auth",function($http,TimeCounter,$filter,$rootScope,Auth){return{templateUrl:"modules/forms/views/directiveViews/form/submit-form.client.view.html",restrict:"E",scope:{ -myform:"="},controller:["$document","$window","$scope",function($document,$window,$scope){$scope.authentication=$rootScope.authentication,$scope.noscroll=!1,$scope.forms={},$scope.form_fields_count=$scope.myform.visible_form_fields.filter(function(field){return"statement"!==field.fieldType&&"rating"!==field.fieldType}).length,$scope.reloadForm=function(){$scope.myform.submitted=!1,$scope.myform.form_fields=_.chain($scope.myform.visible_form_fields).map(function(field){return field.fieldValue="",field}).value(),$scope.loading=!1,$scope.error="",$scope.selected={_id:"",index:0},$scope.setActiveField($scope.myform.visible_form_fields[0]._id,0,!1),TimeCounter.restartClock()},$window.onscroll=function(){$scope.scrollPos=document.body.scrollTop||document.documentElement.scrollTop||0;var elemBox=document.getElementsByClassName("activeField")[0].getBoundingClientRect();$scope.fieldTop=elemBox.top,$scope.fieldBottom=elemBox.bottom;var field_id,field_index;$scope.noscroll||($scope.selected.index===$scope.myform.form_fields.length-1&&$scope.fieldBottom<200?(field_index=$scope.selected.index+1,field_id="submit_field",$scope.setActiveField(field_id,field_index,!1)):$scope.selected.index===$scope.myform.form_fields.length?$scope.fieldTop>200&&(field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)):$scope.fieldBottom<0?(field_index=$scope.selected.index+1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)):0!==$scope.selected.index&&$scope.fieldTop>0&&(field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)),$scope.$apply())},$scope.setActiveField=$rootScope.setActiveField=function(field_id,field_index,animateScroll){null!==$scope.selected&&$scope.selected._id!==field_id&&($scope.selected._id=field_id,$scope.selected.index=field_index,animateScroll&&($scope.noscroll=!0,setTimeout(function(){$document.scrollToElement(angular.element(".activeField"),-10,200).then(function(){$scope.noscroll=!1,document.querySelectorAll(".activeField .focusOn")[0].focus()})},20)))},$rootScope.nextField=$scope.nextField=function(){if($scope.selected.index<$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id=$scope.myform.form_fields[selected_index]._id;$rootScope.setActiveField(selected_id,selected_index,!0)}else if($scope.selected.index===$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id="submit_field";$rootScope.setActiveField(selected_id,selected_index,!0)}},$rootScope.prevField=$scope.prevField=function(){if($scope.selected.index>0){var selected_index=$scope.selected.index-1,selected_id=$scope.myform.form_fields[selected_index]._id;$scope.setActiveField(selected_id,selected_index,!0)}},$scope.exitStartPage=function(){$scope.myform.startPage.showStart=!1,$scope.myform.form_fields.length>0&&($scope.selected._id=$scope.myform.form_fields[0]._id)},$scope.submitForm=function(){var _timeElapsed=TimeCounter.stopClock();$scope.loading=!0;var form=_.cloneDeep($scope.myform);form.timeElapsed=_timeElapsed,form.percentageComplete=$filter("formValidity")($scope.myform)/$scope.myform.visible_form_fields.length*100,delete form.visible_form_fields,setTimeout(function(){$scope.submitPromise=$http.post("/forms/"+$scope.myform._id,form).success(function(data,status,headers){$scope.myform.submitted=!0,$scope.loading=!1}).error(function(error){$scope.loading=!1,$scope.error=error.message})},500)},$scope.reloadForm()}]}}]),angular.module("forms").service("CurrentForm",function(){var _form={};this.getForm=function(){return _form},this.setForm=function(form){_form=form}}),angular.module("forms").service("FormFields",[function(){this.types=[{name:"textfield",value:"Short Text"},{name:"email",value:"Email"},{name:"radio",value:"Multiple Choice"},{name:"dropdown",value:"Dropdown"},{name:"date",value:"Date"},{name:"textarea",value:"Paragraph Text"},{name:"yes_no",value:"Yes/No"},{name:"legal",value:"Legal"},{name:"rating",value:"Rating"},{name:"link",value:"Link"},{name:"number",value:"Numbers"},{name:"statement",value:"Statement"}]}]),angular.module("forms").factory("Forms",["$resource",function($resource){return $resource("/forms/:formId",{formId:"@_id"},{query:{method:"GET",isArray:!0},get:{method:"GET",transformResponse:function(data,header){var form=angular.fromJson(data);return form.visible_form_fields=_.filter(form.form_fields,function(field){return field.deletePreserved===!1}),form}},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").factory("Submissions",["$resource",function($resource){return $resource("forms/:formID/submissions/:submissionId",{submissionId:"@_id",formId:"@_id"},{query:{method:"GET",isArray:!0},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").service("TimeCounter",[function(){var _startTime,_endTime,that=this;this.timeSpent=0,this.restartClock=function(){_startTime=Date.now(),_endTime=_startTime},this.stopClock=function(){return _startTime?(_endTime=Date.now(),that.timeSpent=Math.abs(_endTime.valueOf()-_startTime.valueOf())/1e3,that.timeSpent):new Error("Clock has not been started")},this.clockStarted=function(){return!!this._startTime}}]),angular.module("users").config(["$httpProvider",function($httpProvider){$httpProvider.interceptors.push(["$q","$location",function($q,$location){return{responseError:function(response){return"/users/me"!==$location.path()&&response.config&&"/users/me"!==response.config.url&&(console.log("intercepted rejection of ",response.config.url,response.status),401===response.status?($location.nextAfterLogin=$location.path(),$location.path("/signin")):403===response.status&&$location.path("/access_denied")),$q.reject(response)}}}])}]),angular.module("users").config(["$stateProvider",function($stateProvider){var checkLoggedin=function($q,$timeout,$state,User,Auth){var deferred=$q.defer();return console.log(Auth.ensureHasCurrentUser(User)),Auth.currentUser&&Auth.currentUser.email?$timeout(deferred.resolve):Auth.currentUser=User.getCurrent(function(){Auth.login(),$timeout(deferred.resolve())},function(){Auth.logout(),$timeout(deferred.reject()),$state.go("sigin",{reload:!0})}),deferred.promise};checkLoggedin.$inject=["$q","$timeout","$state","User","Auth"];var checkSignupDisabled=function($window,$timeout,$q){console.log($window.signupDisabled);var deferred=$q.defer();return $timeout(deferred.reject()),deferred.promise};checkSignupDisabled.$inject=["$window","$timeout","$q"],$stateProvider.state("profile",{resolve:{loggedin:checkLoggedin},url:"/settings/profile",templateUrl:"modules/users/views/settings/edit-profile.client.view.html"}).state("password",{resolve:{loggedin:checkLoggedin},url:"/settings/password",templateUrl:"modules/users/views/settings/change-password.client.view.html"}).state("accounts",{resolve:{loggedin:checkLoggedin},url:"/settings/accounts",templateUrl:"modules/users/views/settings/social-accounts.client.view.html"}).state("signup",{resolve:{isDisabled:checkSignupDisabled},url:"/signup",templateUrl:"modules/users/views/authentication/signup.client.view.html"}).state("signup-success",{resolve:{isDisabled:checkSignupDisabled},url:"/signup-success",templateUrl:"modules/users/views/authentication/signup-success.client.view.html"}).state("signin",{url:"/signin",templateUrl:"modules/users/views/authentication/signin.client.view.html"}).state("access_denied",{url:"/access_denied",templateUrl:"modules/users/views/authentication/access-denied.client.view.html"}).state("resendVerifyEmail",{url:"/verify",templateUrl:"modules/users/views/verify/resend-verify-email.client.view.html"}).state("verify",{url:"/verify/:token",templateUrl:"modules/users/views/verify/verify-account.client.view.html"}).state("forgot",{url:"/password/forgot",templateUrl:"modules/users/views/password/forgot-password.client.view.html"}).state("reset-invalid",{url:"/password/reset/invalid",templateUrl:"modules/users/views/password/reset-password-invalid.client.view.html"}).state("reset-success",{url:"/password/reset/success",templateUrl:"modules/users/views/password/reset-password-success.client.view.html"}).state("reset",{url:"/password/reset/:token",templateUrl:"modules/users/views/password/reset-password.client.view.html"})}]),angular.module("users").controller("AuthenticationController",["$scope","$location","$state","$rootScope","User","Auth",function($scope,$location,$state,$rootScope,User,Auth){$scope=$rootScope,$scope.credentials={},$scope.error="",$scope.signin=function(){$scope.credentials.email=$scope.credentials.username,User.login($scope.credentials).then(function(response){Auth.login(response),$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),"home"!==$state.previous.name&&"verify"!==$state.previous.name&&""!==$state.previous.name?$state.go($state.previous.name):$state.go("listForms")},function(error){$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user,$scope.error=error,console.log("loginError: "+error)})},$scope.signup=function(){console.log($scope.credentials),User.signup($scope.credentials).then(function(response){console.log("signup-success"),$state.go("signup-success")},function(error){console.log("Error: "),console.log(error),error?($scope.error=error,console.log(error)):console.log("No response received")})}}]),angular.module("users").controller("PasswordController",["$scope","$stateParams","$state","User",function($scope,$stateParams,$state,User){$scope.error="",$scope.askForPasswordReset=function(){User.askForPasswordReset($scope.credentials).then(function(response){$scope.success=response.message,$scope.credentials=null},function(error){$scope.error=error,$scope.credentials=null})},$scope.resetUserPassword=function(){$scope.success=$scope.error=null,User.resetPassword($scope.passwordDetails,$stateParams.token).then(function(response){$scope.success=response.message,$scope.passwordDetails=null,$state.go("reset-success")},function(error){$scope.error=error.message||error,$scope.passwordDetails=null})}}]),angular.module("users").controller("SettingsController",["$scope","$rootScope","$http","$state","Users",function($scope,$rootScope,$http,$state,Users){$scope.user=$rootScope.user,$scope.hasConnectedAdditionalSocialAccounts=function(provider){for(var i in $scope.user.additionalProvidersData)return!0;return!1},$scope.isConnectedSocialAccount=function(provider){return $scope.user.provider===provider||$scope.user.additionalProvidersData&&$scope.user.additionalProvidersData[provider]},$scope.removeUserSocialAccount=function(provider){$scope.success=$scope.error=null,$http["delete"]("/users/accounts",{params:{provider:provider}}).success(function(response){$scope.success=!0,$scope.user=response}).error(function(response){$scope.error=response.message})},$scope.updateUserProfile=function(isValid){if(isValid){$scope.success=$scope.error=null;var user=new Users($scope.user);user.$update(function(response){$scope.success=!0,$scope.user=response},function(response){$scope.error=response.data.message})}else $scope.submitted=!0},$scope.changeUserPassword=function(){$scope.success=$scope.error=null,$http.post("/users/password",$scope.passwordDetails).success(function(response){$scope.success=!0,$scope.passwordDetails=null}).error(function(response){$scope.error=response.message})}}]),angular.module("users").controller("VerifyController",["$scope","$state","$rootScope","User","Auth","$stateParams",function($scope,$state,$rootScope,User,Auth,$stateParams){$scope.isResetSent=!1,$scope.credentials={},$scope.error="",$scope.resendVerifyEmail=function(){User.resendVerifyEmail($scope.credentials.email).then(function(response){console.log(response),$scope.success=response.message,$scope.credentials=null,$scope.isResetSent=!0},function(error){$scope.error=error,$scope.credentials.email=null,$scope.isResetSent=!1})},$scope.validateVerifyToken=function(){$stateParams.token&&(console.log($stateParams.token),User.validateVerifyToken($stateParams.token).then(function(response){console.log("Success: "+response.message),$scope.success=response.message,$scope.isResetSent=!0,$scope.credentials.email=null},function(error){console.log("Error: "+error.message),$scope.isResetSent=!1,$scope.error=error,$scope.credentials.email=null}))}}]),angular.module("users").factory("Auth",["$window",function($window){var userState={isLoggedIn:!1},service={_currentUser:null,get currentUser(){return this._currentUser},ensureHasCurrentUser:function(User){return service._currentUser&&service._currentUser.username?service._currentUser:$window.user?(service._currentUser=$window.user,service._currentUser):void User.getCurrent().then(function(user){return service._currentUser=user,userState.isLoggedIn=!0,$window.user=service._currentUser,service._currentUser},function(response){return userState.isLoggedIn=!1,service._currentUser=null,$window.user=null,console.log("User.getCurrent() err",response),null})},isAuthenticated:function(){return!!service._currentUser},getUserState:function(){return userState},login:function(new_user){userState.isLoggedIn=!0,service._currentUser=new_user},logout:function(){$window.user=null,userState.isLoggedIn=!1,service._currentUser=null}};return service}]),angular.module("users").service("Authorizer",["APP_PERMISSIONS","USER_ROLES",function(APP_PERMISSIONS,USER_ROLES){return function(user){return{canAccess:function(permissions){var i,len,permission;for(angular.isArray(permissions)||(permissions=[permissions]),i=0,len=permissions.length;len>i;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}]),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var validTokenRe=/^([A-Za-z0-9]{48})$/g;if(!validTokenRe.test(token))throw new Error("Error token: "+token+" is not a valid verification token");var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file +function removeDateFieldsFunc(o){function eachObject(v,k){"lastModified"!==k&&"created"!==k||delete clone[i][k]}for(var clone=_.clone(o),i=0;i'),$templateCache.put("../public/modules/core/views/home.client.view.html",'

Craft beautiful forms in seconds.

Create your next ______.

Tell a story with a form.

'),$templateCache.put("../public/modules/forms/views/admin-form.client.view.html",'
'),$templateCache.put("../public/modules/forms/views/list-forms.client.view.html",'

Create a new form
Name
Language

'),$templateCache.put("../public/modules/forms/views/submit-form.client.view.html","
"),$templateCache.put("../public/modules/forms/views/adminTabs/analyze.html",""),$templateCache.put("../public/modules/forms/views/adminTabs/configure.html",""),$templateCache.put("../public/modules/forms/views/adminTabs/create.html",""),$templateCache.put("../public/modules/forms/views/adminTabs/design.html",'
Background Color
Question Text Color
Answer Text Color
Button Background Color
Button Text Color
'),$templateCache.put("../public/modules/forms/views/directiveViews/cgBusy/update-form-message-TypeA.html",'
{{$message}}
'),$templateCache.put("../public/modules/forms/views/directiveViews/cgBusy/update-form-message-TypeB.html",'
{{$message}}
'),$templateCache.put("../public/modules/forms/views/directiveViews/entryPage/startPage.html",'

{{pageData.introTitle}}

{{pageData.introParagraph}}

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/date.html",'

{{field.title}} optional

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/dropdown.html",'
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/file.html",'
{{field.title}} (* required)
{{field.file.originalname}}
Upload your File
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/hidden.html",''),$templateCache.put("../public/modules/forms/views/directiveViews/field/legal.html",'
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/radio.html",'

{{field.title}} optional


'),$templateCache.put("../public/modules/forms/views/directiveViews/field/rating.html",'

{{field.title}} optional

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/statement.html",'

{{field.title}}

{{field.description}}


'),$templateCache.put("../public/modules/forms/views/directiveViews/field/textarea.html",'

{{field.title}} optional

press ENTER
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/textfield.html",'

{{field.title}} (optional)

press ENTER
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/yes_no.html",'

{{field.title}} *(required)

{{field.description}}


'),$templateCache.put("../public/modules/forms/views/directiveViews/form/configure-form.client.view.html",'
Save Submissions as PDFs?
Upload Your PDF Template
{{myform.pdf.name}}
Upload your PDF
Autogenerate Form?
Use Oscarhost API?
Oscarhost API Username
Oscarhost API Password
Oscarhost API URL
Oscarhost API Update Type
Form Name
Form Status
Language
* required
Display Form Footer?
Display Start Page?
'), +$templateCache.put("../public/modules/forms/views/directiveViews/form/edit-form.client.view.html",'

Edit Start Page


Intro Title:
Intro Paragraph:
\n
\n\n

\n
\n
Options:
\n
\n
\n \n\n \n \n \n
\n
\n \n
\n
\n
\n\n

\n\n
\n
Required:
\n
\n \n\n \n
\n
\n\n
\n
Disabled:
\n
\n \n\n \n
\n
\n\n
\n \n\n
\n
\n

\n Click on Fields to add them here\n

\n
\n
\n\n
\n \n
\n\n \n \n\n \n
\n
\n\n'),$templateCache.put("../public/modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html",'
#{{value.title}}OscarEMR User ProfilePercentage CompleteTime ElapsedDeviceLocationIP AddressDate Submitted (UTC)Generated PDF
{{$index+1}}{{field.fieldValue}}User Profile #{{row.oscarDemoNum}}{{row.percentageComplete}}%{{row.timeElapsed}}{{row.device.name}}, {{row.device.type}}{{row.geoLocation.city}}, {{row.geoLocation.country}}{{row.ipAddr}}{{row.created | date:\'yyyy-MM-dd HH:mm:ss\'}}Generated PDF
'),$templateCache.put("../public/modules/forms/views/directiveViews/form/submit-form.client.view.html",'
press ENTER
'),$templateCache.put("../public/modules/users/views/authentication/access-denied.client.view.html",'

You need to be logged in to access this page

Login
'),$templateCache.put("../public/modules/users/views/authentication/signin.client.view.html",'

Sign into your account

'),$templateCache.put("../public/modules/users/views/authentication/signup-success.client.view.html",''),$templateCache.put("../public/modules/users/views/authentication/signup.client.view.html",''),$templateCache.put("../public/modules/users/views/password/forgot-password.client.view.html",'

Restore your password

Enter your account email.

'),$templateCache.put("../public/modules/users/views/password/reset-password-invalid.client.view.html",'

Password reset is invalid

Ask for a new password reset
'),$templateCache.put("../public/modules/users/views/password/reset-password-success.client.view.html",'

Password successfully reset

Continue to home page
'),$templateCache.put("../public/modules/users/views/password/reset-password.client.view.html",'

Reset your password

'),$templateCache.put("../public/modules/users/views/settings/change-password.client.view.html",'

Change your password

'),$templateCache.put("../public/modules/users/views/settings/edit-profile.client.view.html",'

Edit your profile

'), +$templateCache.put("../public/modules/users/views/settings/social-accounts.client.view.html",'

Connected social accounts:

Connect other social accounts:

'),$templateCache.put("../public/modules/users/views/verify/resend-verify-email.client.view.html",'

Resend your account verification email

Enter your account email.

{{error}}

Verification Email has been Sent

A verification email has been sent to {{username}}.
But your account is still not activated yet

Check your email and click on the activation link to activate your account. If you have any questions drop us a line at hi@TellForm.com

'),$templateCache.put("../public/modules/users/views/verify/verify-account.client.view.html",'

Account successfuly activated

Continue to login page

Verification link is invalid or has expired

Resend your verification email Signin to your account
')}]);var ApplicationConfiguration=function(){var applicationModuleName="NodeForm",applicationModuleVendorDependencies=["duScroll","ui.select","cgBusy","ngSanitize","vButton","ngResource","NodeForm.templates","ui.router","ui.bootstrap","ui.utils"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","$state","$stateParams",function($rootScope,Auth,$state,$stateParams){$rootScope.$state=$state,$rootScope.$stateParams=$stateParams,$rootScope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState){$state.previous=fromState,"home"===toState.name||"signin"===toState.name||"resendVerifyEmail"===toState.name||"verify"===toState.name||"signup"===toState.name||"signup-success"===toState.name?Auth.isAuthenticated()&&(event.preventDefault(),$state.go("listForms")):"access_denied"===toState.name||Auth.isAuthenticated()||"submitForm"===toState.name||(event.preventDefault(),$state.go("listForms"))})}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","User","Authorizer","$state","$stateParams",function($rootScope,Auth,User,Authorizer,$state,$stateParams){$rootScope.$on("$stateChangeStart",function(event,next){var authenticator,permissions,user;permissions=next&&next.data&&next.data.permissions?next.data.permissions:null,Auth.ensureHasCurrentUser(User),user=Auth.currentUser,user&&(authenticator=new Authorizer(user),null!=permissions&&(authenticator.canAccess(permissions)||(event.preventDefault(),$state.go("access_denied"))))})}]),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.router.tabs","colorpicker.module","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/forms")}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User","$window",function($rootScope,$scope,Menus,$state,Auth,User,$window){$rootScope.signupDisabled=$window.signupDisabled,$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["english","french","spanish"],$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("listForms")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").controller("HomeController",["$rootScope","$scope","User","$state",function($rootScope,$scope,User,$state){$scope=$rootScope}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field&&"statement"!==field.fieldType&&"rating"!==field.fieldType?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",["$delegate",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate}])}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/views/list-forms.client.view.html"}).state("submitForm",{url:"/forms/:formId",templateUrl:"modules/forms/views/submit-form.client.view.html",data:{hideNav:!0},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"SubmitFormController",controllerAs:"ctrl"}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/views/admin-form.client.view.html",data:{permissions:["editForm"]},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"AdminFormController"}).state("viewForm.configure",{url:"/configure",templateUrl:"modules/forms/views/adminTabs/configure.html"}).state("viewForm.design",{url:"/design",templateUrl:"modules/forms/views/adminTabs/design.html"}).state("viewForm.analyze",{url:"/analyze",templateUrl:"modules/forms/views/adminTabs/analyze.html"}).state("viewForm.create",{url:"/create",templateUrl:"modules/forms/views/adminTabs/create.html"})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$uibModal","myForm",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$uibModal,myForm){$scope=$rootScope,$scope.animationsEnabled=!0,$scope.myform=myForm,$rootScope.saveInProgress=!1,CurrentForm.setForm($scope.myform),$scope.tabData=[{heading:"Create",route:"viewForm.create"},{heading:"Design",route:"viewForm.design"},{heading:"Configure",route:"viewForm.configure"},{heading:"Analyze",route:"viewForm.analyze"}],$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.openDeleteModal=function(){$scope.deleteModal=$uibModal.open({animation:$scope.animationsEnabled,templateUrl:"myModalContent.html",controller:"AdminFormController",resolve:{myForm:function(){return $scope.myform}}}),$scope.deleteModal.result.then(function(selectedItem){$scope.selected=selectedItem},function(){console.log("Modal dismissed at: "+new Date)})},$scope.cancelDeleteModal=function(){$scope.deleteModal&&$scope.deleteModal.dismiss("cancel")},$scope.removeCurrentForm=function(){if($scope.deleteModal&&$scope.deleteModal.opened){$scope.deleteModal.close();var form_id=$scope.myform._id;if(!form_id)throw new Error("Error - removeCurrentForm(): $scope.myform._id does not exist");$http["delete"]("/forms/"+form_id).success(function(data,status,headers){console.log("form deleted successfully"),$state.go("listForms",{},{reload:!0})}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}},$scope.update=$rootScope.update=function(updateImmediately,cb){var continueUpdate=!0;if(updateImmediately||(continueUpdate=!$rootScope.saveInProgress),continueUpdate){var err=null;updateImmediately||($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),err=response.data})["finally"](function(){return updateImmediately||($rootScope.saveInProgress=!1),"function"==typeof cb?cb(err):void 0})}}}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$scope.forms={},$scope.showCreateModal=!1,$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$scope.showCreateModal||($scope.showCreateModal=!0)},$scope.closeCreateModal=function(){$scope.showCreateModal&&($scope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicateForm=function(form_index){var form=_.cloneDeep($scope.myforms[form_index]);delete form._id,$http.post("/forms",{form:form}).success(function(data,status,headers){$scope.myforms.splice(form_index+1,0,data)}).error(function(errorResponse){console.error(errorResponse),null===errorResponse&&($scope.error=errorResponse.data.message)})},$scope.createNewForm=function(){var form={};form.title=$scope.forms.createForm.title.$modelValue,form.language=$scope.forms.createForm.language.$modelValue,$scope.forms.createForm.$valid&&$scope.forms.createForm.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("new form created"),$scope.goToWithId("viewForm.create",data._id+"")}).error(function(errorResponse){console.error(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeForm=function(form_index){if(form_index>=$scope.myforms.length||0>form_index)throw new Error("Error: form_index in removeForm() must be between 0 and "+$scope.myforms.length-1);$http["delete"]("/forms/"+$scope.myforms[form_index]._id).success(function(data,status,headers){console.log("form deleted successfully"),$scope.myforms.splice(form_index,1)}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}}]),angular.module("forms").controller("SubmitFormController",["$scope","$rootScope","$state","myForm","Auth",function($scope,$rootScope,$state,myForm,Auth){$scope.authentication=Auth,$scope.myform=myForm,$scope.myform.isLive?$scope.hideNav=$rootScope.hideNav=!0:$scope.authentication.isAuthenticated()?$scope.hideNav=$rootScope.hideNav=!1:($scope.hideNav=$rootScope.hideNav=!0,$state.go("access_denied"))}]),_.mixin({removeDateFields:removeDateFieldsFunc}),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFields Started",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFields Finished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!0,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine(),$formCtrl.$setUntouched())})};$scope.$watch(function(newValue,oldValue){console.log("introParagraphStartPage.$dirty: "+$scope.editForm.introParagraphStartPage.$dirty),console.log("introParagraphStartPage.$touched: "+$scope.editForm.introParagraphStartPage.$touched),$rootScope.finishedRender&&$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&(console.log("Form saving started"),debounceSave(),console.log("introParagraphStartPage.$dirty AFTER: "+$scope.editForm.introParagraphStartPage.$dirty))}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){newValue=angular.copy(newValue),oldValue=angular.copy(oldValue),newValue.form_fields=_.removeDateFields(newValue.form_fields),oldValue.form_fields=_.removeDateFields(oldValue.form_fields);var changedFields=!_.isEqual(oldValue.form_fields,newValue.form_fields)||!_.isEqual(oldValue.startPage,newValue.startPage),changedFieldMap=!1;oldValue.hasOwnProperty("plugins.oscarhost.settings.fieldMap")&&(changedFieldMap=!!oldValue.plugins.oscarhost.settings.fieldMap&&!_.isEqual(oldValue.plugins.oscarhost.settings.fieldMap,newValue.plugins.oscarhost.settings.fieldMap)),(newValue||oldValue)&&oldValue&&(0===oldValue.form_fields.length&&($rootScope.finishedRender=!0),$rootScope.finishedRender&&(changedFields&&!$formCtrl.$dirty||changedFieldMap)&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","CurrentForm",function($rootScope,$http,Upload,CurrentForm){return{templateUrl:"modules/forms/views/directiveViews/form/configure-form.client.view.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:["$scope",function($scope){console.log($scope.myform),CurrentForm.getForm().plugins?CurrentForm.getForm().plugins.oscarhost.baseUrl&&($scope.oscarhostAPI=!0):$scope.oscarhostAPI=!1,$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages,this._current_upload=null,$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update,this._unbindedPdfFields=$scope.pdfFields,$scope.cancelUpload=function(){this._current_upload.abort(),$scope.pdfLoading=!1,$scope.removePDF()},$scope.removePDF=function(){$scope.myform.pdf=null,$scope.myform.isGenerated=!1,$scope.myform.autofillPDFs=!1,console.log("form.pdf: "+$scope.myform.pdf+" REMOVED")},$scope.uploadPDF=function(file){file&&(console.log(file),Upload.upload({url:"/upload/pdf",data:{user:$scope.user,file:file}}).then(function(resp){var data=resp.data;$scope.log="file "+data.originalname+" uploaded as "+data.filename+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()},function(resp){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(resp.status)},function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total,10);$scope.log="progress: "+progressPercentage+"% "+evt.config.data.file.name+"\n"+$scope.log,console.log($scope.log),$scope.pdfLoading=!0}))}}]}}]),angular.module("forms").directive("editFormDirective",["$rootScope","FormFields",function($rootScope,FormFields){return{templateUrl:"modules/forms/views/directiveViews/form/edit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:["$scope",function($scope){for(var field_ids=_($scope.myform.form_fields).pluck("_id"),i=0;i0){$scope.myform.plugins.oscarhost.settings.fieldMap||($scope.myform.plugins.oscarhost.settings.fieldMap={});var oscarhostFields=$scope.myform.plugins.oscarhost.settings.validFields,currentFields=_($scope.myform.plugins.oscarhost.settings.fieldMap).invert().keys().value();return $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id)&&(currentFields=_(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id])),_(oscarhostFields).difference(currentFields).value()}return[]},$scope.dropzone={handle:" .handle",containment:".dropzoneContainer",cursor:"grabbing"},$scope.addNewField=function(modifyForm,fieldType){$scope.addField.lastAddedID++;for(var fieldTitle,i=0;i<$scope.addField.types.length;i++)if($scope.addField.types[i].name===fieldType){$scope.addField.types[i].lastAddedID++,fieldTitle=$scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;break}var newField={title:fieldTitle,fieldType:fieldType,fieldValue:"",required:!0,disabled:!1,deletePreserved:!1};return modifyForm&&$scope.myform.form_fields.push(newField),newField},$scope.deleteField=function(field_index){var currFieldId=$scope.myform.form_fields[field_index]._id;$scope.myform.hasOwnProperty("plugins.oscarhost.baseUrl")&&delete $scope.myform.plugins.oscarhost.settings.fieldMap[currFieldId],$scope.myform.form_fields.splice(field_index,1)},$scope.duplicateField=function(field_index){var currField=_.cloneDeep($scope.myform.form_fields[field_index]);currField._id="cloned"+_.uniqueId(),currField.title+=" copy",$scope.myform.form_fields.splice(field_index+1,0,currField)},$scope.addButton=function(){var newButton={};newButton.bgColor="#ddd",newButton.color="#ffffff",newButton.text="Button",newButton._id=Math.floor(1e5*Math.random()),$scope.myform.startPage.buttons.push(newButton)},$scope.deleteButton=function(button){for(var currID,i=0;i<$scope.myform.startPage.buttons.length;i++)if(currID=$scope.myform.startPage.buttons[i]._id,console.log(currID),currID===button._id){$scope.myform.startPage.buttons.splice(i,1);break}},$scope.addOption=function(field_index){var currField=$scope.myform.form_fields[field_index];if(console.log(field_index),console.log(currField),"checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType){currField.fieldOptions||($scope.myform.form_fields[field_index].fieldOptions=[]);var lastOptionID=0;currField.fieldOptions[currField.fieldOptions.length-1]&&(lastOptionID=currField.fieldOptions[currField.fieldOptions.length-1].option_id);var newOption={option_id:Math.floor(1e5*Math.random()),option_title:"Option "+lastOptionID,option_value:"Option "+lastOptionID};$scope.myform.form_fields[field_index].fieldOptions.push(newOption)}},$scope.deleteOption=function(field_index,option){var currField=$scope.myform.form_fields[field_index];if("checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType)for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:["$scope",function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}]}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope","$templateCache",function($http,$compile,$rootScope,$templateCache){var getTemplateUrl=function(fieldType){var type=fieldType,templateUrl="modules/forms/views/directiveViews/field/",supported_fields=["textfield","textarea","date","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0&&(templateUrl=templateUrl+type+".html"),$templateCache.get("../public/"+templateUrl)};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&",design:"=",index:"=",forms:"="},link:function(scope,element){$rootScope.chooseDefaultOption=scope.chooseDefaultOption=function(type){"yes_no"===type?scope.field.fieldValue="true":"rating"===type?scope.field.fieldValue=0:"radio"===scope.field.fieldType?(console.log(scope.field),scope.field.fieldValue=scope.field.fieldOptions[0].option_value,console.log(scope.field.fieldValue)):"legal"===type&&(scope.field.fieldValue="true",$rootScope.nextField())},scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType&&(scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0});var fieldType=scope.field.fieldType;if("number"===scope.field.fieldType||"textfield"===scope.field.fieldType||"email"===scope.field.fieldType||"link"===scope.field.fieldType){switch(scope.field.fieldType){case"textfield":scope.field.input_type="text";break;case"email":scope.field.input_type="email",scope.field.placeholder="joesmith@example.com";break;case"number":scope.field.input_type="text",scope.field.validateRegex=/^\d+$/;break;default:scope.field.input_type="url",scope.field.placeholder="http://example.com"}fieldType="textfield"}var template=getTemplateUrl(fieldType);element.html(template).show(),$compile(element.contents())(scope)}}}]),angular.module("forms").directive("onEnterKey",["$rootScope",function($rootScope){return{restrict:"A",link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode;13===keyCode&&($rootScope.$apply(function(){$rootScope.$eval($attrs.onEnterKey)}),event.preventDefault())})}}}]),angular.module("forms").directive("onFinishRender",["$rootScope","$timeout",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")||element.attr("data-ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$first&&!scope.$last?scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Started")}):scope.$last&&scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Finished")})}}}}]),angular.module("forms").directive("submitFormDirective",["$http","TimeCounter","$filter","$rootScope","Auth",function($http,TimeCounter,$filter,$rootScope,Auth){return{templateUrl:"modules/forms/views/directiveViews/form/submit-form.client.view.html", +restrict:"E",scope:{myform:"="},controller:["$document","$window","$scope",function($document,$window,$scope){$scope.authentication=$rootScope.authentication,$scope.noscroll=!1,$scope.forms={},$scope.form_fields_count=$scope.myform.visible_form_fields.filter(function(field){return"statement"!==field.fieldType&&"rating"!==field.fieldType}).length,$scope.reloadForm=function(){$scope.myform.submitted=!1,$scope.myform.form_fields=_.chain($scope.myform.visible_form_fields).map(function(field){return field.fieldValue="",field}).value(),$scope.loading=!1,$scope.error="",$scope.selected={_id:"",index:0},$scope.setActiveField($scope.myform.visible_form_fields[0]._id,0,!1),TimeCounter.restartClock()},$window.onscroll=function(){$scope.scrollPos=document.body.scrollTop||document.documentElement.scrollTop||0;var elemBox=document.getElementsByClassName("activeField")[0].getBoundingClientRect();$scope.fieldTop=elemBox.top,$scope.fieldBottom=elemBox.bottom;var field_id,field_index;$scope.noscroll||($scope.selected.index===$scope.myform.form_fields.length-1&&$scope.fieldBottom<200?(field_index=$scope.selected.index+1,field_id="submit_field",$scope.setActiveField(field_id,field_index,!1)):$scope.selected.index===$scope.myform.form_fields.length?$scope.fieldTop>200&&(field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)):$scope.fieldBottom<0?(field_index=$scope.selected.index+1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)):0!==$scope.selected.index&&$scope.fieldTop>0&&(field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)),$scope.$apply())},$scope.setActiveField=$rootScope.setActiveField=function(field_id,field_index,animateScroll){null!==$scope.selected&&$scope.selected._id!==field_id&&($scope.selected._id=field_id,$scope.selected.index=field_index,animateScroll&&($scope.noscroll=!0,setTimeout(function(){$document.scrollToElement(angular.element(".activeField"),-10,200).then(function(){$scope.noscroll=!1,document.querySelectorAll(".activeField .focusOn")[0].focus()})},20)))},$rootScope.nextField=$scope.nextField=function(){if($scope.selected.index<$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id=$scope.myform.form_fields[selected_index]._id;$rootScope.setActiveField(selected_id,selected_index,!0)}else if($scope.selected.index===$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id="submit_field";$rootScope.setActiveField(selected_id,selected_index,!0)}},$rootScope.prevField=$scope.prevField=function(){if($scope.selected.index>0){var selected_index=$scope.selected.index-1,selected_id=$scope.myform.form_fields[selected_index]._id;$scope.setActiveField(selected_id,selected_index,!0)}},$scope.exitStartPage=function(){$scope.myform.startPage.showStart=!1,$scope.myform.form_fields.length>0&&($scope.selected._id=$scope.myform.form_fields[0]._id)},$scope.submitForm=function(){var _timeElapsed=TimeCounter.stopClock();$scope.loading=!0;var form=_.cloneDeep($scope.myform);form.timeElapsed=_timeElapsed,form.percentageComplete=$filter("formValidity")($scope.myform)/$scope.myform.visible_form_fields.length*100,delete form.visible_form_fields,setTimeout(function(){$scope.submitPromise=$http.post("/forms/"+$scope.myform._id,form).success(function(data,status,headers){$scope.myform.submitted=!0,$scope.loading=!1}).error(function(error){$scope.loading=!1,$scope.error=error.message})},500)},$scope.reloadForm()}]}}]),angular.module("forms").service("CurrentForm",function(){var _form={};this.getForm=function(){return _form},this.setForm=function(form){_form=form}}),angular.module("forms").service("FormFields",[function(){this.types=[{name:"textfield",value:"Short Text"},{name:"email",value:"Email"},{name:"radio",value:"Multiple Choice"},{name:"dropdown",value:"Dropdown"},{name:"date",value:"Date"},{name:"textarea",value:"Paragraph Text"},{name:"yes_no",value:"Yes/No"},{name:"legal",value:"Legal"},{name:"rating",value:"Rating"},{name:"link",value:"Link"},{name:"number",value:"Numbers"},{name:"statement",value:"Statement"}]}]),angular.module("forms").factory("Forms",["$resource",function($resource){return $resource("/forms/:formId",{formId:"@_id"},{query:{method:"GET",isArray:!0},get:{method:"GET",transformResponse:function(data,header){var form=angular.fromJson(data);return form.visible_form_fields=_.filter(form.form_fields,function(field){return field.deletePreserved===!1}),form}},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").factory("Submissions",["$resource",function($resource){return $resource("forms/:formID/submissions/:submissionId",{submissionId:"@_id",formId:"@_id"},{query:{method:"GET",isArray:!0},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").service("TimeCounter",[function(){var _startTime,_endTime,that=this;this.timeSpent=0,this.restartClock=function(){_startTime=Date.now(),_endTime=_startTime},this.stopClock=function(){return _startTime?(_endTime=Date.now(),that.timeSpent=Math.abs(_endTime.valueOf()-_startTime.valueOf())/1e3,that.timeSpent):new Error("Clock has not been started")},this.clockStarted=function(){return!!this._startTime}}]),angular.module("users").config(["$httpProvider",function($httpProvider){$httpProvider.interceptors.push(["$q","$location",function($q,$location){return{responseError:function(response){return"/users/me"!==$location.path()&&response.config&&"/users/me"!==response.config.url&&(console.log("intercepted rejection of ",response.config.url,response.status),401===response.status?($location.nextAfterLogin=$location.path(),$location.path("/signin")):403===response.status&&$location.path("/access_denied")),$q.reject(response)}}}])}]),angular.module("users").config(["$stateProvider",function($stateProvider){var checkLoggedin=function($q,$timeout,$state,User,Auth){var deferred=$q.defer();return Auth.currentUser&&Auth.currentUser.email?$timeout(deferred.resolve):Auth.currentUser=User.getCurrent(function(){Auth.login(),$timeout(deferred.resolve())},function(){Auth.logout(),$timeout(deferred.reject()),$state.go("signin",{reload:!0})}),deferred.promise};checkLoggedin.$inject=["$q","$timeout","$state","User","Auth"];var checkSignupDisabled=function($window,$timeout,$q){var deferred=$q.defer();return console.log($window.signupDisabled),$window.signupDisabled?$timeout(deferred.reject()):(console.log("resolved"),$timeout(deferred.resolve())),deferred.promise};checkSignupDisabled.$inject=["$window","$timeout","$q"],$stateProvider.state("profile",{resolve:{loggedin:checkLoggedin},url:"/settings/profile",templateUrl:"modules/users/views/settings/edit-profile.client.view.html"}).state("password",{resolve:{loggedin:checkLoggedin},url:"/settings/password",templateUrl:"modules/users/views/settings/change-password.client.view.html"}).state("accounts",{resolve:{loggedin:checkLoggedin},url:"/settings/accounts",templateUrl:"modules/users/views/settings/social-accounts.client.view.html"}).state("signup",{resolve:{isDisabled:checkSignupDisabled},url:"/signup",templateUrl:"modules/users/views/authentication/signup.client.view.html"}).state("signup-success",{resolve:{isDisabled:checkSignupDisabled},url:"/signup-success",templateUrl:"modules/users/views/authentication/signup-success.client.view.html"}).state("signin",{url:"/signin",templateUrl:"modules/users/views/authentication/signin.client.view.html"}).state("access_denied",{url:"/access_denied",templateUrl:"modules/users/views/authentication/access-denied.client.view.html"}).state("resendVerifyEmail",{url:"/verify",templateUrl:"modules/users/views/verify/resend-verify-email.client.view.html"}).state("verify",{url:"/verify/:token",templateUrl:"modules/users/views/verify/verify-account.client.view.html"}).state("forgot",{url:"/password/forgot",templateUrl:"modules/users/views/password/forgot-password.client.view.html"}).state("reset-invalid",{url:"/password/reset/invalid",templateUrl:"modules/users/views/password/reset-password-invalid.client.view.html"}).state("reset-success",{url:"/password/reset/success",templateUrl:"modules/users/views/password/reset-password-success.client.view.html"}).state("reset",{url:"/password/reset/:token",templateUrl:"modules/users/views/password/reset-password.client.view.html"})}]),angular.module("users").controller("AuthenticationController",["$scope","$location","$state","$rootScope","User","Auth",function($scope,$location,$state,$rootScope,User,Auth){$scope=$rootScope,$scope.credentials={},$scope.error="",$scope.signin=function(){$scope.credentials.email=$scope.credentials.username,User.login($scope.credentials).then(function(response){Auth.login(response),$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),"home"!==$state.previous.name&&"verify"!==$state.previous.name&&""!==$state.previous.name?$state.go($state.previous.name):$state.go("listForms")},function(error){$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user,$scope.error=error,console.log("loginError: "+error)})},$scope.signup=function(){console.log($scope.credentials),User.signup($scope.credentials).then(function(response){console.log("signup-success"),$state.go("signup-success")},function(error){console.log("Error: "),console.log(error),error?($scope.error=error,console.log(error)):console.log("No response received")})}}]),angular.module("users").controller("PasswordController",["$scope","$stateParams","$state","User",function($scope,$stateParams,$state,User){$scope.error="",$scope.askForPasswordReset=function(){User.askForPasswordReset($scope.credentials).then(function(response){$scope.success=response.message,$scope.credentials=null},function(error){$scope.error=error,$scope.credentials=null})},$scope.resetUserPassword=function(){$scope.success=$scope.error=null,User.resetPassword($scope.passwordDetails,$stateParams.token).then(function(response){$scope.success=response.message,$scope.passwordDetails=null,$state.go("reset-success")},function(error){$scope.error=error.message||error,$scope.passwordDetails=null})}}]),angular.module("users").controller("SettingsController",["$scope","$rootScope","$http","$state","Users",function($scope,$rootScope,$http,$state,Users){$scope.user=$rootScope.user,$scope.hasConnectedAdditionalSocialAccounts=function(provider){for(var i in $scope.user.additionalProvidersData)return!0;return!1},$scope.isConnectedSocialAccount=function(provider){return $scope.user.provider===provider||$scope.user.additionalProvidersData&&$scope.user.additionalProvidersData[provider]},$scope.removeUserSocialAccount=function(provider){$scope.success=$scope.error=null,$http["delete"]("/users/accounts",{params:{provider:provider}}).success(function(response){$scope.success=!0,$scope.user=response}).error(function(response){$scope.error=response.message})},$scope.updateUserProfile=function(isValid){if(isValid){$scope.success=$scope.error=null;var user=new Users($scope.user);user.$update(function(response){$scope.success=!0,$scope.user=response},function(response){$scope.error=response.data.message})}else $scope.submitted=!0},$scope.changeUserPassword=function(){$scope.success=$scope.error=null,$http.post("/users/password",$scope.passwordDetails).success(function(response){$scope.success=!0,$scope.passwordDetails=null}).error(function(response){$scope.error=response.message})}}]),angular.module("users").controller("VerifyController",["$scope","$state","$rootScope","User","Auth","$stateParams",function($scope,$state,$rootScope,User,Auth,$stateParams){$scope.isResetSent=!1,$scope.credentials={},$scope.error="",$scope.resendVerifyEmail=function(){User.resendVerifyEmail($scope.credentials.email).then(function(response){console.log(response),$scope.success=response.message,$scope.credentials=null,$scope.isResetSent=!0},function(error){$scope.error=error,$scope.credentials.email=null,$scope.isResetSent=!1})},$scope.validateVerifyToken=function(){$stateParams.token&&(console.log($stateParams.token),User.validateVerifyToken($stateParams.token).then(function(response){console.log("Success: "+response.message),$scope.success=response.message,$scope.isResetSent=!0,$scope.credentials.email=null},function(error){console.log("Error: "+error.message),$scope.isResetSent=!1,$scope.error=error,$scope.credentials.email=null}))}}]),angular.module("users").factory("Auth",["$window",function($window){var userState={isLoggedIn:!1},service={_currentUser:null,get currentUser(){return this._currentUser},ensureHasCurrentUser:function(User){return service._currentUser&&service._currentUser.username?service._currentUser:$window.user?(service._currentUser=$window.user,service._currentUser):void User.getCurrent().then(function(user){return service._currentUser=user,userState.isLoggedIn=!0,$window.user=service._currentUser,service._currentUser},function(response){return userState.isLoggedIn=!1,service._currentUser=null,$window.user=null,console.log("User.getCurrent() err",response),null})},isAuthenticated:function(){return!!service._currentUser},getUserState:function(){return userState},login:function(new_user){userState.isLoggedIn=!0,service._currentUser=new_user},logout:function(){$window.user=null,userState.isLoggedIn=!1,service._currentUser=null}};return service}]),angular.module("users").service("Authorizer",["APP_PERMISSIONS","USER_ROLES",function(APP_PERMISSIONS,USER_ROLES){return function(user){return{canAccess:function(permissions){var i,len,permission;for(angular.isArray(permissions)||(permissions=[permissions]),i=0,len=permissions.length;len>i;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}]),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var validTokenRe=/^([A-Za-z0-9]{48})$/g;if(!validTokenRe.test(token))throw new Error("Error token: "+token+" is not a valid verification token");var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file diff --git a/public/modules/core/controllers/header.client.controller.js b/public/modules/core/controllers/header.client.controller.js index b6c28eb1..6ea8b7ca 100755 --- a/public/modules/core/controllers/header.client.controller.js +++ b/public/modules/core/controllers/header.client.controller.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User', '$window' +angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User', '$window', function ($rootScope, $scope, Menus, $state, Auth, User, $window) { $rootScope.signupDisabled = $window.signupDisabled; diff --git a/public/modules/core/views/header.client.view.html b/public/modules/core/views/header.client.view.html index f792353e..c1a1505b 100755 --- a/public/modules/core/views/header.client.view.html +++ b/public/modules/core/views/header.client.view.html @@ -27,7 +27,7 @@