diff --git a/README.md b/README.md index 5626b20b..d3555d2f 100755 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ TellForm Current stable release: v1.2.1 -[![Build Status](https://travis-ci.org/whitef0x0/nodeforms.svg?branch=master)](https://travis-ci.org/whitef0x0/nodeforms) -[![Dependencies Status](https://david-dm.org/whitef0x0/NodeForms.svg)](https://david-dm.org/whitef0x0/nodeforms) +[![Build Status](https://travis-ci.org/whitef0x0/tellform.svg?branch=master)](https://travis-ci.org/whitef0x0/tellform) +[![Dependencies Status](https://david-dm.org/whitef0x0/tellform.svg)](https://david-dm.org/whitef0x0/tellform) [![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy) @@ -45,6 +45,11 @@ $ npm install $ bower install ``` +Setup environment. +```bash +$ grunt build +``` + To run development version: ```bash $ grunt default @@ -81,6 +86,11 @@ $ grunt test:client Currently the live example uses heroku github deployments. The Docker file is out of date and does not work. If someone wishes to get it working feel free to submit a pull request. +To calculate your code coverage with Istanbul, run the coverage task +```bash +$ grunt coverage +``` + ## Running in a secure environment To run your application in a secure manner you'll need to use OpenSSL and generate a set of self-signed certificates. Unix-based users can use the following command: ```bash diff --git a/app.json b/app.json index cbe9de9d..2ebf5a54 100644 --- a/app.json +++ b/app.json @@ -1,7 +1,7 @@ { "name": "TellForm", "description": "Beautiful, opensource web forms", - "repository": "https://github.com/whitef0x0/nodeforms", + "repository": "https://github.com/whitef0x0/tellform", "logo": "https://node-js-sample.herokuapp.com/node.svg", "keywords": ["node", "express", "static", "mean"] } \ No newline at end of file diff --git a/app/tests/user.server.routes.test.js b/app/tests/user.server.routes.test.js index 7ff8d42e..16ea2c11 100644 --- a/app/tests/user.server.routes.test.js +++ b/app/tests/user.server.routes.test.js @@ -41,7 +41,7 @@ describe('User CRUD tests', function() { password: 'password' }; - Create a new user + //Create a new user _User = { firstName: 'Full', lastName: 'Name', diff --git a/app/views/layout.server.view.html b/app/views/layout.server.view.html index 0d408be4..904577b4 100755 --- a/app/views/layout.server.view.html +++ b/app/views/layout.server.view.html @@ -68,9 +68,7 @@
- {% block content %}{% endblock %} -
diff --git a/bower.json b/bower.json index 3d86a647..b1d0aec0 100755 --- a/bower.json +++ b/bower.json @@ -2,7 +2,7 @@ "name": "TellForm", "description": "Opensource alternative to TypeForm", "version": "1.2.1", - "homepage": "https://github.com/whitef0x0/NodeForms", + "homepage": "https://github.com/whitef0x0/tellform", "authors": [ "David Baldwynn (http://baldwynn.me)" ], @@ -11,17 +11,16 @@ "appPath": "public/modules", "dependencies": { "bootstrap": "~3", - "angular": "~1.3.20", - "angular-resource": "~1.4.4", - "angular-animate": "~1.3.20", - "angular-mocks": "~1.3.20", + "angular": "~1.4.7", + "angular-resource": "~1.4.7", + "angular-animate": "~1.4.7", + "angular-mocks": "~1.4.7", "angular-bootstrap": "~0.12.0", "angular-ui-utils": "~0.1.1", "angular-ui-router": "~0.2.11", "angular-strap": "~2.3.1", "restangular": "~1.5.1", - "fontawesome": "~4.3.0", - "ng-file-upload": "~9.1.2", + "ng-file-upload": "~10.0.2", "angular-raven": "~0.5.11", "angular-ui-date": "~0.0.8", "lodash": "~3.10.0", @@ -35,7 +34,8 @@ "angular-ui-router-tabs": "~1.7.0" }, "resolutions": { - "angular": "~1.3.20", - "angular-bootstrap": "^0.14.0" + "angular-bootstrap": "^0.14.0", + "angular": "~1.4.7", + "angular-animate": "~1.4.7" } } diff --git a/config/env/all.js b/config/env/all.js index e37850c8..c24e28a0 100755 --- a/config/env/all.js +++ b/config/env/all.js @@ -3,8 +3,8 @@ module.exports = { app: { title: 'TellForm', - description: 'Generate Forms from PDFs', - keywords: 'typeform, pdfs, forms, generator, form generator', + description: 'Opensource form builder alternative to TypeForm', + keywords: 'typeform, pdfs, forms, opensource, formbuilder, google forms, nodejs', }, port: process.env.PORT || 3000, templateEngine: 'swig', @@ -39,7 +39,7 @@ module.exports = { maxAge: null, // To set the cookie in a specific domain uncomment the following // setting: - // domain: 'forms.polydaic.com' + // domain: 'tellform.com' }, /* @@ -64,29 +64,13 @@ module.exports = { } }, assets: { - // lib: { - // css: [ - // 'public/lib/bootstrap/dist/css/bootstrap.css', - // 'public/lib/bootstrap/dist/css/bootstrap-theme.css', - // ], - // js: [ - // 'public/lib/angular/angular.js', - // 'public/lib/angular-permission/dist/angular-permission.js', - // 'public/lib/angular-resource/angular-resource.js', - // 'public/lib/angular-animate/angular-animate.js', - // 'public/lib/angular-ui-router/release/angular-ui-router.js', - // 'public/lib/angular-ui-utils/ui-utils.js', - // 'public/lib/angular-bootstrap/ui-bootstrap-tpls.js', - // 'public/lib/ng-file-upload/ng-file-upload-all.js', - // 'public/lib/angular-cookies/angular-cookies.js', - // ] - // }, css: [ 'public/modules/**/css/*.css' ], js: [ 'public/config.js', 'public/application.js', + 'public/populate_template_cache.js', 'public/modules/*/*.js', 'public/modules/*/*[!tests]*/*.js' ], diff --git a/config/env/production-dev.js b/config/env/production-dev.js index 0638e3a1..f94ce80c 100644 --- a/config/env/production-dev.js +++ b/config/env/production-dev.js @@ -22,20 +22,6 @@ module.exports = { domain: 'dev.tellform.com' }, assets: { - // lib: { - // css: [ - // 'public/lib/bootstrap/dist/css/bootstrap.min.css', - // 'public/lib/bootstrap/dist/css/bootstrap-theme.min.css', - // ], - // js: [ - // 'public/lib/angular/angular.min.js', - // 'public/lib/angular-resource/angular-resource.min.js', - // 'public/lib/angular-animate/angular-animate.min.js', - // 'public/lib/angular-ui-router/release/angular-ui-router.min.js', - // 'public/lib/angular-ui-utils/ui-utils.min.js', - // 'public/lib/angular-bootstrap/ui-bootstrap-tpls.min.js' - // ] - // }, css: 'public/dist/application.min.css', js: 'public/dist/application.min.js' }, @@ -65,7 +51,7 @@ module.exports = { callbackURL: '/auth/github/callback' }, mailer: { - from: process.env.MAILER_FROM || 'no-reply@kioskform-dev.herokuapp.com', + from: process.env.MAILER_FROM || 'no-reply@dev.tellform.com', options: { service: process.env.MAILER_SERVICE_PROVIDER || '', auth: { diff --git a/config/env/production.js b/config/env/production.js index 294564e1..133ec149 100755 --- a/config/env/production.js +++ b/config/env/production.js @@ -22,20 +22,6 @@ module.exports = { domain: 'tellform.com' }, assets: { - // lib: { - // css: [ - // 'public/lib/bootstrap/dist/css/bootstrap.min.css', - // 'public/lib/bootstrap/dist/css/bootstrap-theme.min.css', - // ], - // js: [ - // 'public/lib/angular/angular.min.js', - // 'public/lib/angular-resource/angular-resource.min.js', - // 'public/lib/angular-animate/angular-animate.min.js', - // 'public/lib/angular-ui-router/release/angular-ui-router.min.js', - // 'public/lib/angular-ui-utils/ui-utils.min.js', - // 'public/lib/angular-bootstrap/ui-bootstrap-tpls.min.js' - // ] - // }, css: 'public/dist/application.min.css', js: 'public/dist/application.min.js' }, diff --git a/config/env/secure.js b/config/env/secure.js index 0c426dee..5f4c9b8e 100755 --- a/config/env/secure.js +++ b/config/env/secure.js @@ -36,20 +36,6 @@ module.exports = { domain: 'forms.polydaic.com' }, assets: { - // lib: { - // css: [ - // 'public/lib/bootstrap/dist/css/bootstrap.min.css', - // 'public/lib/bootstrap/dist/css/bootstrap-theme.min.css', - // ], - // js: [ - // 'public/lib/angular/angular.min.js', - // 'public/lib/angular-resource/angular-resource.min.js', - // 'public/lib/angular-animate/angular-animate.min.js', - // 'public/lib/angular-ui-router/release/angular-ui-router.min.js', - // 'public/lib/angular-ui-utils/ui-utils.min.js', - // 'public/lib/angular-bootstrap/ui-bootstrap-tpls.min.js' - // ] - // }, css: 'public/dist/application.min.css', js: 'public/dist/application.min.js' }, diff --git a/gruntfile.js b/gruntfile.js index 064aef32..e590812c 100755 --- a/gruntfile.js +++ b/gruntfile.js @@ -8,7 +8,9 @@ module.exports = function(grunt) { clientViews: ['public/modules/**/views/**/*.html'], clientJS: ['public/js/*.js', 'public/modules/**/*.js'], clientCSS: ['public/modules/**/*.css'], - mochaTests: ['app/tests/**/*.js'] + serverTests: ['app/tests/**/*.js'], + clientTests: ['public/modules/**/tests/*.js'], + allTests: ['public/modules/**/tests/*.js', 'app/tests/**/*.js'], }; // Project Configuration @@ -32,6 +34,7 @@ module.exports = function(grunt) { }, clientViews: { files: watchFiles.clientViews, + tasks: ['html2js:main'], options: { livereload: true, spawn: false @@ -54,7 +57,7 @@ module.exports = function(grunt) { } }, mochaTests: { - files: watchFiles.mochaTests, + files: watchFiles.serverTests, tasks: ['test:server'], } }, @@ -166,6 +169,80 @@ module.exports = function(grunt) { } } }, + mocha_istanbul: { + coverage: { + src: watchFiles.allTests, // a folder works nicely + options: { + mask: '*.test.js' + } + }, + coverageClient: { + src: watchFiles.clientTests, // specifying file patterns works as well + options: { + coverageFolder: 'coverageClient', + mask: '*.test.js', + } + }, + coverageServer: { + src: watchFiles.serverTests, + options: { + coverageFolder: 'coverageServer', + mask: '*.test.js', + } + }, + coveralls: { + src: watchFiles.allTests, // multiple folders also works + options: { + coverage:true, // this will make the grunt.event.on('coverage') event listener to be triggered + check: { + lines: 75, + statements: 75 + }, + root: './lib', // define where the cover task should consider the root of libraries that are covered by tests + reportFormats: ['cobertura','lcovonly'] + } + } + }, + istanbul_check_coverage: { + default: { + options: { + coverageFolder: 'coverage*', // will check both coverage folders and merge the coverage results + check: { + lines: 80, + statements: 80 + } + } + } + }, + html2js: { + options: { + base: 'NodeForm', + 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/populate_template_cache.js' + } + } + }); + + grunt.event.on('coverage', function(lcov, done){ + require('coveralls').handleInput(lcov, function(err){ + if (err) { + return done(err); + } + done(); + }); }); // Load NPM tasks @@ -182,26 +259,33 @@ module.exports = function(grunt) { grunt.config.set('applicationJavaScriptFiles', config.assets.js); grunt.config.set('applicationCSSFiles', config.assets.css); }); - grunt.loadNpmTasks('grunt-html2js'); + grunt.loadNpmTasks('grunt-html2js'); + grunt.loadNpmTasks('grunt-mocha-istanbul'); + + // Code coverage tasks. + grunt.registerTask('coveralls', ['mocha_istanbul:coveralls']); + grunt.registerTask('coverage', ['mocha_istanbul:coverage']); + grunt.registerTask('coverage:client', ['mocha_istanbul:coverageClient']); + grunt.registerTask('coverage:server', ['mocha_istanbul:coverageServer']); // Default task(s). - grunt.registerTask('default', ['lint', 'concurrent:default']); + grunt.registerTask('default', ['lint', 'html2js:main', 'concurrent:default']); // Debug task. - grunt.registerTask('debug', ['lint', 'concurrent:debug']); + grunt.registerTask('debug', ['lint', 'html2js:main', 'concurrent:debug']); // Secure task(s). - grunt.registerTask('secure', ['env:secure', 'lint', 'concurrent:default']); + grunt.registerTask('secure', ['env:secure', 'lint', 'html2js:main', 'concurrent:default']); // Lint task(s). grunt.registerTask('lint', ['newer:jshint', 'newer:csslint']); // Build task(s). - grunt.registerTask('build', ['lint', 'loadConfig', 'uglify', 'cssmin', 'ngAnnotate' ]); + grunt.registerTask('build', ['lint', 'loadConfig', 'uglify', 'cssmin', 'ngAnnotate', 'html2js:main']); // Test task. grunt.registerTask('test', ['test:server', 'test:client']); - grunt.registerTask('test:server', ['env:test', 'mochaTest']); - grunt.registerTask('test:client', ['env:test', 'karma:unit']); + grunt.registerTask('test:server', ['html2js:main', 'env:test', 'mochaTest']); + grunt.registerTask('test:client', ['html2js:main', 'env:test', 'karma:unit']); }; diff --git a/karma.conf.js b/karma.conf.js index 2527f598..0893326b 100755 --- a/karma.conf.js +++ b/karma.conf.js @@ -21,11 +21,12 @@ module.exports = function(config) { // Possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' reporters: ['mocha', 'html', 'progress'], + preprocessors: { - 'public/modules/*/views/**/*.html': ['ng-html2js'], + 'public/modules/*/views/**/**.html': ['ng-html2js'], 'public/modules/*/views/*.html': ['ng-html2js'], - 'public/modules/*/*.js': ['coverage'], - 'public/modules/*/*[!tests]*/*.js': ['coverage'], + //'public/modules/*/*.js': ['coverage'], + //'public/modules/*/*[!tests]*/*.js': ['coverage'], }, ngHtml2JsPreprocessor: { @@ -43,10 +44,10 @@ module.exports = function(config) { //Make sure we capture console.log output client: { - captureConsole: true, - mocha: { - bail: true - } + captureConsole: true, + mocha: { + bail: true + } }, // Level of logging @@ -67,7 +68,7 @@ module.exports = function(config) { browsers: ['PhantomJS'], // If browser does not capture in given timeout [ms], kill it - captureTimeout: 60000, + captureTimeout: 3000, // Continuous Integration mode // If true, it capture browsers, run tests and exit diff --git a/package.json b/package.json index 5339bdf1..1feefc0b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "TellForm", "description": "Opensource alternative to TypeForm", "version": "1.2.1", - "homepage": "https://github.com/whitef0x0/NodeForms", + "homepage": "https://github.com/whitef0x0/tellform", "authors": [ "David Baldwynn (http://baldwynn.me)" ], @@ -50,7 +50,6 @@ "grunt-contrib-watch": "~0.6.1", "grunt-env": "~0.4.1", "grunt-karma": "~0.12.1", - "grunt-mocha-test": "~0.12.1", "grunt-newer": "~1.1.1", "grunt-ng-annotate": "~1.0.1", "grunt-node-inspector": "~0.4.1", @@ -62,7 +61,6 @@ "main-bower-files": "~2.9.0", "math": "0.0.3", "method-override": "~2.3.0", - "mocha": ">=1.20.0", "mongoose": "~3.8.8", "mongoose-utilities": "~0.1.1", "morgan": "~1.6.1", @@ -90,19 +88,23 @@ "express-device": "~0.4.2" }, "devDependencies": { - "node-mandrill": "^1.0.1", + "grunt-mocha-istanbul": "^3.0.1", + "grunt-mocha-test": "~0.12.1", + "istanbul": "^0.4.0", + "karma": "~0.13.14", "karma-chrome-launcher": "~0.2.1", - "karma-jasmine-html-reporter": "^0.1.8", - "karma-mocha-reporter": "^1.1.1", - "karma-ng-html2js-preprocessor": "^0.2.0", "karma-coverage": "~0.2.0", "karma-firefox-launcher": "~0.1.3", "karma-jasmine": "^0.2.3", + "karma-jasmine-html-reporter": "^0.1.8", + "karma-mocha-reporter": "^1.1.1", + "karma-ng-html2js-preprocessor": "^0.2.0", "karma-phantomjs-launcher": "~0.1.2", + "mailosaur": "^1.0.1", + "mocha": ">=1.20.0", + "node-mandrill": "^1.0.1", "should": "~7.1.1", "supertest": "~1.1.0", - "supertest-session": "^1.0.0", - "mailosaur": "^1.0.1", - "karma": "~0.13.14" + "supertest-session": "^1.0.0" } } diff --git a/public/config.js b/public/config.js index 1de2fbec..d2c6e07e 100755 --- a/public/config.js +++ b/public/config.js @@ -4,7 +4,7 @@ var ApplicationConfiguration = (function() { // Init module configuration options var applicationModuleName = 'NodeForm'; - var applicationModuleVendorDependencies = ['ngResource', 'ngAnimate', 'ui.router', 'ui.bootstrap', 'ui.utils', 'ngRaven', 'cgBusy']; + var applicationModuleVendorDependencies = ['ngResource', 'NodeForm.templates', 'ngAnimate', 'ui.router', 'ui.bootstrap', 'ui.utils', 'ngRaven', 'cgBusy']; // Add a new vertical module var registerModule = function(moduleName, dependencies) { diff --git a/public/dist/application.js b/public/dist/application.js index 4859c8fb..1dfa89cd 100644 --- a/public/dist/application.js +++ b/public/dist/application.js @@ -1,28 +1,5 @@ 'use strict'; -// Init the application configuration module for AngularJS application -var ApplicationConfiguration = (function() { - // Init module configuration options - var applicationModuleName = 'NodeForm'; - var applicationModuleVendorDependencies = ['ngResource', 'ngAnimate', 'ui.router', 'ui.bootstrap', 'ui.utils', 'ngRaven', 'cgBusy']; - - // Add a new vertical module - var registerModule = function(moduleName, dependencies) { - // Create angular module - angular.module(moduleName, dependencies || []); - - // Add the module to the AngularJS configuration file - angular.module(applicationModuleName).requires.push(moduleName); - }; - - return { - applicationModuleName: applicationModuleName, - applicationModuleVendorDependencies: applicationModuleVendorDependencies, - registerModule: registerModule - }; -})(); -'use strict'; - //Start by defining the main module and adding the module dependencies angular.module(ApplicationConfiguration.applicationModuleName, ApplicationConfiguration.applicationModuleVendorDependencies); @@ -110,6 +87,63 @@ angular.element(document).ready(function() { }); 'use strict'; +// Init the application configuration module for AngularJS application +var ApplicationConfiguration = (function() { + // Init module configuration options + var applicationModuleName = 'TellForm'; + var applicationModuleVendorDependencies = ['ngResource', 'TellForm.templates', 'ngAnimate', 'ui.router', 'ui.bootstrap', 'ui.utils', 'ngRaven', 'cgBusy']; + + // Add a new vertical module + var registerModule = function(moduleName, dependencies) { + // Create angular module + angular.module(moduleName, dependencies || []); + + // Add the module to the AngularJS configuration file + angular.module(applicationModuleName).requires.push(moduleName); + }; + + return { + applicationModuleName: applicationModuleName, + applicationModuleVendorDependencies: applicationModuleVendorDependencies, + registerModule: registerModule + }; +})(); +angular.module('TellForm.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.

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

"); + $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

Created on
"); + $templateCache.put("../public/modules/forms/views/submit-form.client.view.html", + "
"); +}]); + +'use strict'; + // Use Application configuration module to register a new module ApplicationConfiguration.registerModule('core', ['users']); @@ -441,7 +475,6 @@ angular.module('forms').config(['$stateProvider', resolve: { Forms: 'Forms', myForm: ["Forms", "$stateParams", function (Forms, $stateParams) { - console.log('getting form'); return Forms.get({formId: $stateParams.formId}).$promise; }], }, @@ -471,6 +504,7 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope $scope.animationsEnabled = true; $scope.myform = myForm; $rootScope.saveInProgress = false; + CurrentForm.setForm($scope.myform); $scope.tabData = [ @@ -491,20 +525,6 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope route: 'viewForm.analyze', } ]; - - // Find a specific Form - $scope.findOne = function(){ - Forms.get({ - formId: $stateParams.formId - }, function(form){ - CurrentForm.setForm(form); - $scope.myform = form; - $scope.myform._id = $stateParams.formId; - }, function(err){ - console.error('Could not fetch form'); - console.error(err); - }); - }; $scope.setForm = function(form){ $scope.myform = form; @@ -520,19 +540,19 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope */ $scope.openDeleteModal = function(){ $scope.deleteModal = $uibModal.open({ - animation: $scope.animationsEnabled, - templateUrl: 'myModalContent.html', - controller: 'AdminFormController', - resolve: { - myForm: function () { - return $scope.myform; - } - } + animation: $scope.animationsEnabled, + templateUrl: 'myModalContent.html', + controller: 'AdminFormController', + resolve: { + myForm: function(){ + return $scope.myform; + } + } }); $scope.deleteModal.result.then(function (selectedItem) { - $scope.selected = selectedItem; + $scope.selected = selectedItem; }, function () { - console.log('Modal dismissed at: ' + new Date()); + console.log('Modal dismissed at: ' + new Date()); }); }; @@ -540,12 +560,6 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope $scope.cancelDeleteModal = function(){ if($scope.deleteModal){ $scope.deleteModal.dismiss('cancel'); - $scope.deleteModal.result(function(selectedItem){ - this.selected = selectedItem; - }, function(type){ - this.canceled = true; - }); - } }; @@ -697,10 +711,10 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope ]); 'use strict'; -// Forms controller -angular.module('forms').controller('SubmitFormController', ['$scope', '$rootScope', '$state', 'myForm', - function($scope, $rootScope, $state, myForm) { - $scope.authentication = $rootScope.authentication; +// SubmitForm controller +angular.module('forms').controller('SubmitFormController', ['$scope', '$rootScope', '$state', 'myForm', 'Auth', + function($scope, $rootScope, $state, myForm, Auth) { + $scope.authentication = Auth; $scope.myform = myForm; if(!$scope.myform.isLive){ @@ -791,7 +805,6 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun console.log('Form saving started'); debounceSave(); console.log('introParagraphStartPage.$dirty AFTER: '+$scope.editForm.introParagraphStartPage.$dirty); - } }); @@ -805,8 +818,13 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun oldValue.form_fields = _.removeDateFields(oldValue.form_fields); var changedFields = !_.isEqual(oldValue.form_fields,newValue.form_fields) || !_.isEqual(oldValue.startPage, newValue.startPage); + var changedFieldMap = false; - var changedFieldMap = !!oldValue.plugins.oscarhost.settings.fieldMap && !_.isEqual(oldValue.plugins.oscarhost.settings.fieldMap,newValue.plugins.oscarhost.settings.fieldMap); + if(oldValue.hasOwnProperty('plugins.oscarhost.settings.fieldMap')){ + changedFieldMap = !!oldValue.plugins.oscarhost.settings.fieldMap && !_.isEqual(oldValue.plugins.oscarhost.settings.fieldMap,newValue.plugins.oscarhost.settings.fieldMap); + } + + //If our form is undefined, don't save form if( (!newValue && !oldValue) || !oldValue ){ return; } @@ -824,7 +842,7 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun // console.log(newValue.form_fields); if(oldValue.form_fields.length === 0) { - $rootScope.finishedRender = true + $rootScope.finishedRender = true; } //Save form ONLY IF rendering is finished, form_fields have been changed AND currently not save in progress @@ -1069,24 +1087,23 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField ** startPage Button Methods */ - // add new Button to the startPage/EndPage + // add new Button to the startPage $scope.addButton = function(){ var newButton = {}; newButton.bgColor = '#ddd'; newButton.color = '#ffffff'; newButton.text = 'Button'; - newButton._id = _.uniqueId(); + newButton._id = Math.floor(100000*Math.random()); $scope.myform.startPage.buttons.push(newButton); }; - // delete particular Button + // delete particular Button from startPage $scope.deleteButton = function(button){ - // var hashKey = _.chain(button.$$hashKey).words().last().parseInt().value(); var currID; for(var i = 0; i < $scope.myform.startPage.buttons.length; i++){ - // var currHashKey = _.chain($scope.myform.startPage.buttons[i].$$hashKey).words().last().parseInt().value(); + currID = $scope.myform.startPage.buttons[i]._id; console.log(currID); @@ -1103,33 +1120,44 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormField */ // add new option to the field - $scope.addOption = function (field){ - if(!field.fieldOptions) field.fieldOptions = []; + $scope.addOption = function(field_index){ + var currField = $scope.myform.form_fields[field_index]; - var lastOptionID = 0; + if(currField.fieldType === 'checkbox' || currField.fieldType === 'dropdown' || currField.fieldType === 'radio'){ + if(!currField.fieldOptions) currField.fieldOptions = []; - if(field.fieldOptions[field.fieldOptions.length-1]){ - lastOptionID = field.fieldOptions[field.fieldOptions.length-1].option_id; + var lastOptionID = 0; + + if(currField.fieldOptions[currField.fieldOptions.length-1]){ + lastOptionID = currField.fieldOptions[currField.fieldOptions.length-1].option_id; + } + + // new option's id + var option_id = lastOptionID + 1; + + var newOption = { + 'option_id' : Math.floor(100000*Math.random()), + "option_title" : 'Option '+lastOptionID, + 'option_value' : 'Option ' +lastOptionID, + }; + + // put new option into fieldOptions array + $scope.myform.form_fields[field_index].fieldOptions.push(newOption); } - - // new option's id - var option_id = lastOptionID + 1; - - var newOption = { - 'option_id' : option_id, - 'option_value' : 'Option ' + option_id, - }; - - // put new option into fieldOptions array - field.fieldOptions.push(newOption); }; // delete particular option - $scope.deleteOption = function (field, option){ - for(var i = 0; i < field.fieldOptions.length; i++){ - if(field.fieldOptions[i].option_id === option.option_id){ - field.fieldOptions.splice(i, 1); - break; + $scope.deleteOption = function (field_index, option){ + var currField = $scope.myform.form_fields[field_index]; + + if(currField.fieldType === 'checkbox' || currField.fieldType === 'dropdown' || currField.fieldType === 'radio'){ + for(var i = 0; i < currField.fieldOptions.length; i++){ + if(currField.fieldOptions[i].option_id === option.option_id){ + + $scope.myform.form_fields[field_index].fieldOptions.splice(i, 1); + break; + + } } } }; @@ -1427,7 +1455,6 @@ angular.module('forms').directive('submitFormDirective', ['$http', 'TimeCounter' TimeCounter.startClock(); - /* ** Field Controls */ @@ -1493,8 +1520,6 @@ angular.module('forms').directive('submitFormDirective', ['$http', 'TimeCounter' form.percentageComplete = $filter('formValidity')($scope.myform)/$scope.myform.visible_form_fields.length*100; delete form.visible_form_fields; - $scope.authentication = Auth; - $scope.submitPromise = $http.post('/forms/'+$scope.myform._id, form) .success(function(data, status, headers){ console.log('form submitted successfully'); diff --git a/public/dist/application.min.css b/public/dist/application.min.css index d1370b1e..0a3a7335 100644 --- a/public/dist/application.min.css +++ b/public/dist/application.min.css @@ -1,4 +1,4 @@ .image-background,.opacity-background{position:fixed;width:100%;height:100%;top:0;left:0}body{overflow-x:hidden}.navbar-inverse{background-color:#fafafa;border:0}.navbar .navbar-brand{font-size:1.6em;font-weight:900;color:#ff8383}.navbar .navbar-brand:hover,.navbar .navbar-brand:visited{color:#FA787E}.navbar li.dropdown a.dropdown-toggle:hover>*{color:#000}.navbar li.dropdown.open a.dropdown-toggle:hover>*{color:#fff}.navbar .navbar-brand span{text-decoration:underline}.admin-form .panel-heading a:hover,.current-fields .tool-panel>.panel-default .panel-heading a:hover,.undecorated-link:hover{text-decoration:none}.nav.navbar-nav.navbar-right li{padding-right:20px}.navbar li.dropdown a.dropdown-toggle>*,.navbar-inverse .navbar-nav>li>a{color:#838383}.navbar li.dropdown.open a.dropdown-toggle>*,.navbar-inverse .navbar-nav .active>a,.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{background-color:#838383;color:#fff!important}.navbar-inverse .navbar-toggle{background-color:#ddd;border:none}.navbar-inverse .navbar-collapse{border:none}.content{margin-top:70px}.ng-cloak,.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.browsehappy.jumbotron.hide,body.ng-cloak{display:block}section.hero-section{width:100%}section.hero-section .jumbotron{background-color:transparent;color:#fff}.image-background{z-index:-98;background-image:url(http://yourplaceandmine.ie/wp-content/uploads/2014/09/Daingean-meeting-048_13-1080x675.jpg);background-repeat:no-repeat;background-position:0 50%;background-size:cover}.opacity-background{background-color:rgba(0,0,0,.5);z-index:-97}section.hero-section .jumbotron .signup-btn{background-color:#FA787E;border:none;font-size:2em;padding:.3em .9em;color:#fff;background-color:rgba(250,120,126,.65) #FA787E}.row-height{display:table;table-layout:fixed;height:100%;width:100%}.col-height{display:table-cell;float:none;height:100%}.col-top{vertical-align:top}.col-middle{vertical-align:middle}.col-bottom{vertical-align:bottom}@media (min-width:480px){.row-xs-height{display:table;table-layout:fixed;height:100%;width:100%}.col-xs-height{display:table-cell;float:none;height:100%}.col-xs-top{vertical-align:top}.col-xs-middle{vertical-align:middle}.col-xs-bottom{vertical-align:bottom}}@media (min-width:768px){.row-sm-height{display:table;table-layout:fixed;height:100%;width:100%}.col-sm-height{display:table-cell;float:none;height:100%}.col-sm-top{vertical-align:top}.col-sm-middle{vertical-align:middle}.col-sm-bottom{vertical-align:bottom}}@media (min-width:992px){.row-md-height{display:table;table-layout:fixed;height:100%;width:100%}.col-md-height{display:table-cell;float:none;height:100%}.col-md-top{vertical-align:top}.col-md-middle{vertical-align:middle}.col-md-bottom{vertical-align:bottom}}@media (min-width:1200px){.row-lg-height{display:table;table-layout:fixed;height:100%;width:100%}.col-lg-height{display:table-cell;float:none;height:100%}.col-lg-top{vertical-align:top}.col-lg-middle{vertical-align:middle}.col-lg-bottom{vertical-align:bottom}}/*! * "Fork me on GitHub" CSS ribbon v0.1.1 | MIT License * https://github.com/simonwhitaker/github-fork-ribbon-css -*/.github-fork-ribbon{position:absolute;padding:2px 0;background-color:#a00;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0)),to(rgba(0,0,0,.15)));background-image:-webkit-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-moz-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-ms-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-o-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:linear-gradient(to bottom,rgba(0,0,0,0),rgba(0,0,0,.15));-webkit-box-shadow:0 2px 3px 0 rgba(0,0,0,.5);-moz-box-shadow:0 2px 3px 0 rgba(0,0,0,.5);box-shadow:0 2px 3px 0 rgba(0,0,0,.5);font:700 13px "Helvetica Neue",Helvetica,Arial,sans-serif;z-index:9999;pointer-events:auto}.github-fork-ribbon a,.github-fork-ribbon a:hover{color:#fff;text-decoration:none;text-shadow:0 -1px rgba(0,0,0,.5);text-align:center;width:200px;line-height:20px;display:inline-block;padding:2px 0;border-width:1px 0;border-style:dotted;border-color:#fff;border-color:rgba(255,255,255,.7)}.github-fork-ribbon-wrapper{width:150px;height:150px;position:absolute;overflow:hidden;top:0;z-index:9998;pointer-events:none}.github-fork-ribbon-wrapper.fixed{position:fixed}.github-fork-ribbon-wrapper.left{left:0}.github-fork-ribbon-wrapper.right{right:0}.github-fork-ribbon-wrapper.left-bottom{position:fixed;top:inherit;bottom:0;left:0}.github-fork-ribbon-wrapper.right-bottom{position:fixed;top:inherit;bottom:0;right:0}.github-fork-ribbon-wrapper.right .github-fork-ribbon{top:42px;right:-43px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.github-fork-ribbon-wrapper.left .github-fork-ribbon{top:42px;left:-43px;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.github-fork-ribbon-wrapper.left-bottom .github-fork-ribbon{top:80px;left:-43px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.github-fork-ribbon-wrapper.right-bottom .github-fork-ribbon{top:80px;right:-43px;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.custom-select{position:relative;display:block;padding:0}.custom-select select{width:100%;margin:0;background:0 0;border:1px solid transparent;border-radius:0;outline:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;appearance:none;-webkit-appearance:none;font-size:1em;font-family:helvetica,sans-serif;font-weight:700;color:#444;padding:.6em 1.9em .5em .8em;line-height:1.3}.custom-select option,.modal-header{font-weight:400}.custom-select::after{content:"";position:absolute;width:9px;height:8px;top:50%;right:1em;margin-top:-4px;background-image:url(http://filamentgroup.com/files/select-arrow.png);background-repeat:no-repeat;background-size:100%;z-index:2;pointer-events:none}.custom-select:hover{border:1px solid #888}.custom-select select:focus{outline:0;box-shadow:0 0 1px 3px rgba(180,222,250,1);background-color:transparent;color:#222;border:1px solid #aaa}.custom-select::after,x:-o-prefocus{display:none}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.custom-select select::-ms-expand{display:none}.custom-select select:focus::-ms-value{background:0 0;color:#222}}@-moz-document url-prefix(){.custom-select{overflow:hidden}.custom-select select{width:120%;width:-moz-calc(100% + 3em);width:calc(100% + em)}}.custom-select select:-moz-focusring{color:transparent;text-shadow:0 0 0 #000}.panel-default.startPage{border-style:dashed;border-color:#a9a9a9;border-width:3px}.busy-updating-wrapper{text-align:center;font-size:20px;position:fixed;bottom:0;right:55px;z-index:1}.busy-submitting-wrapper{position:fixed;top:50%;left:0;right:0;bottom:0}section.public-form{margin-top:-70px}section.content p.breakwords{word-break:break-all}.btn{border:1px solid #c6c6c6}.btn[type=submit]{font-size:1.5em;padding:.35em 1.2em}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;font-size:18px}.input-block{display:block;width:100%}.modal-footer input[type=text]{min-height:34px;padding:7px 8px;font-size:13px;color:#333;vertical-align:middle;background-color:#fff;background-repeat:no-repeat;background-position:right 8px center;border:1px solid #ccc;border-radius:3px;outline:0;box-shadow:inset 0 1px 2px rgba(0,0,0,.075)}.modal-body>.modal-body-alert{color:#796620;background-color:#f8eec7;border-color:#f2e09a;margin:-16px -15px 15px;padding:10px 15px;border-style:solid;border-width:1px 0}div.form-submitted>.field.row{padding-bottom:10%;padding-top:2%}div.form-submitted>.field.row>div{font-size:1.7em}form .accordion-edit{width:inherit}.ui-datepicker.ui-widget{z-index:99!important}form .row.field{padding:1em 0 3em;width:inherit}form .row.field>.field-title{margin-top:.5em;font-size:1.2em;padding-bottom:1.8em;width:inherit}form .row.field>.field-input{font-size:1.4em;color:#777}form.submission-form .row.field.statement>.field-title{font-size:1.7em}form.submission-form .row.field.statement>.field-input{font-size:1em;color:#ddd}form.submission-form .select.radio>.field-input input,form.submission-form .select>.field-input input{width:20%}form.submission-form .field.row.radio .btn.activeBtn{background-color:rgba(0,0,0,.7)!important;color:#fff}form.submission-form .field.row.radio .btn{margin-right:1.2em}form.submission-form .select>.field-input .btn{text-align:left;margin-bottom:.7em}form.submission-form .select>.field-input .btn>span{font-size:1.1em}form .field-input>textarea{padding:.45em .9em;width:100%;line-height:160%;border:3px dashed #ddd}form .field-input>input.hasDatepicker{padding:.45em .9em;width:50%;line-height:160%;border:3px dashed #ddd}form .field-input>input.text-field-input{padding:.45em .9em;width:100%;line-height:160%;border:2px dashed #ddd!important}form .field-input>input.text-field-input:focus{border:0}form .required-error{color:#ddd;font-size:.8em}form .row.field.dropdown>.field-input{height:34px;overflow:hidden}form .row.field.dropdown>.field-input>select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}.config-form{max-width:100%}.config-form>.row{padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}div.config-form .row.field{padding-top:1.5em}div.config-form>.row>.container:nth-of-type(odd){border-right:1px #ddd solid}div.config-form.design>.row>.container:nth-of-type(odd){border-right:none}div.config-form .row>.field-input{padding-left:.1em}div.config-form .row>.field-input label{padding-left:1.3em;display:block}.admin-form>.page-header{padding-bottom:0;margin-bottom:40px}.admin-form>.page-header h1{margin-bottom:0;margin-top:0}.admin-form>.page-header>.col-xs-3{padding-top:1.4em}.admin-form .form-controls .row{padding:5px}.admin-form .page-header{border:none}.admin-form .tab-content{padding-top:3em}.admin-form .panel-heading{background-color:#f1f1f1}.admin-form .panel-heading:hover{background-color:#fff;cursor:pointer}.current-fields .panel-body .row.description textarea,.current-fields .panel-body .row.question input[type=text]{width:100%}.current-fields .panel-body .row.options input[type=text]{width:80%}.current-fields .tool-panel>.panel-default:hover{border-color:#9d9d9d;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading{background-color:#fff;color:#9d9d9d!important}.current-fields .tool-panel>.panel-default .panel-heading:hover{background-color:#eee;color:#000!important;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading a{color:inherit}.submissions-table .table-outer.row{margin-top:1.5em;margin-bottom:2em;margin-left:0!important;margin-right:0!important}.submissions-table .table-outer .col-xs-12{padding-left:0!important;border:1px solid #ddd;overflow-x:scroll;border-radius:3px}.submissions-table .table>thead>tr>th{min-width:8em}.submissions-table .table>tbody>tr.selected{background-color:#efefef}.admin-form .add-field{background-color:#ddd;padding:0 2%;border-radius:3px}.admin-form .add-field .col-xs-6{padding:.25em .4em}.admin-form .add-field .col-xs-6 .panel-heading{border-width:1px;border-style:solid;border-color:#bbb;border-radius:4px}.admin-form .oscar-field-select{margin:10px 0}.view-form-btn.span{padding-right:.6em}.status-light.status-light-off{color:#BE0000}.status-light.status-light-on{color:#3C0}section>section.public-form{padding:0 10% 10%}.form-item{text-align:center;border-bottom:6px inset #ccc;background-color:#eee;width:180px;position:relative;height:215px;margin-bottom:45px}.form-item.create-new input[type=text]{width:inherit;color:#000;border:none}.form-item.create-new{background-color:#838383;color:#fff}.form-item.create-new.new-form{background-color:#ff8383;z-index:11}.form-item.create-new.new-form:hover{background-color:#ff6464}.form-item.new-form input[type=text]{margin-top:.2em;width:inherit;color:#000;border:none;padding:.3em .6em}.form-item.new-form .custom-select{margin-top:.2em}.form-item.new-form .custom-select select{background-color:#fff}.form-item.new-form .details-row{margin-top:1em}.form-item.new-form .details-row.submit{margin-top:1.7em}.form-item.new-form .details-row.submit .btn{font-size:.95em}.form-item.new-form .title-row{margin-top:1em;top:0}.overlay{position:fixed;top:0;left:0;height:100%;width:100%;background-color:rgba(0,0,0,.5);z-index:10}.overlay.submitform{background-color:rgba(256,256,256,.8)}.field-directive{z-index:9;padding:10% 10% 10% 0;border:25px solid transparent;position:relative}.activeField{z-index:11;position:relative;display:inline-block;background-color:transparent;border-radius:7px;width:100%;border:25px solid transparent}.form-item.create-new:hover,.form-item:hover{border-bottom:8px inset #ccc;background-color:#d9d9d9}.form-item.create-new:hover{background-color:#515151}.form-item>.row.footer{position:absolute;bottom:0;left:30%}.form-item .title-row{position:relative;top:15px;padding-top:3em;padding-bottom:3.65em}.form-item .title-row h4{font-size:1.3em}.form-item.create-new .title-row{padding:0}.form-item.create-new .title-row h4{font-size:7em}.form-item .details-row{margin-top:3.2em}.form-item .details-row small{font-size:.6em}.form-item.create-new .details-row small{font-size:.95em}.row.auth form .field-input select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}@media (min-width:992px){.nav-users{position:fixed}}.remove-account-container{display:inline-block;position:relative}.btn-remove-account{top:10px;right:10px;position:absolute}section.auth{margin-top:5em}section.auth>h3{font-size:3em;font-weight:500;color:#777}section.auth.signup-view>h3{font-size:4.4em;padding-bottom:.5em} \ No newline at end of file +*/.github-fork-ribbon{position:absolute;padding:2px 0;background-color:#a00;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0)),to(rgba(0,0,0,.15)));background-image:-webkit-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-moz-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-ms-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-o-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:linear-gradient(to bottom,rgba(0,0,0,0),rgba(0,0,0,.15));-webkit-box-shadow:0 2px 3px 0 rgba(0,0,0,.5);-moz-box-shadow:0 2px 3px 0 rgba(0,0,0,.5);box-shadow:0 2px 3px 0 rgba(0,0,0,.5);font:700 13px "Helvetica Neue",Helvetica,Arial,sans-serif;z-index:9999;pointer-events:auto}.github-fork-ribbon a,.github-fork-ribbon a:hover{color:#fff;text-decoration:none;text-shadow:0 -1px rgba(0,0,0,.5);text-align:center;width:200px;line-height:20px;display:inline-block;padding:2px 0;border-width:1px 0;border-style:dotted;border-color:#fff;border-color:rgba(255,255,255,.7)}.github-fork-ribbon-wrapper{width:150px;height:150px;position:absolute;overflow:hidden;top:0;z-index:9998;pointer-events:none}.github-fork-ribbon-wrapper.fixed{position:fixed}.github-fork-ribbon-wrapper.left{left:0}.github-fork-ribbon-wrapper.right{right:0}.github-fork-ribbon-wrapper.left-bottom{position:fixed;top:inherit;bottom:0;left:0}.github-fork-ribbon-wrapper.right-bottom{position:fixed;top:inherit;bottom:0;right:0}.github-fork-ribbon-wrapper.right .github-fork-ribbon{top:42px;right:-43px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.github-fork-ribbon-wrapper.left .github-fork-ribbon{top:42px;left:-43px;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.github-fork-ribbon-wrapper.left-bottom .github-fork-ribbon{top:80px;left:-43px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.github-fork-ribbon-wrapper.right-bottom .github-fork-ribbon{top:80px;right:-43px;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.custom-select{position:relative;display:block;padding:0}.custom-select select{width:100%;margin:0;background:0 0;border:1px solid transparent;border-radius:0;outline:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;appearance:none;-webkit-appearance:none;font-size:1em;font-family:helvetica,sans-serif;font-weight:700;color:#444;padding:.6em 1.9em .5em .8em;line-height:1.3}.custom-select option,.modal-header{font-weight:400}.custom-select::after{content:"";position:absolute;width:9px;height:8px;top:50%;right:1em;margin-top:-4px;background-image:url(http://filamentgroup.com/files/select-arrow.png);background-repeat:no-repeat;background-size:100%;z-index:2;pointer-events:none}.custom-select:hover{border:1px solid #888}.custom-select select:focus{outline:0;box-shadow:0 0 1px 3px rgba(180,222,250,1);background-color:transparent;color:#222;border:1px solid #aaa}.custom-select::after,x:-o-prefocus{display:none}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.custom-select select::-ms-expand{display:none}.custom-select select:focus::-ms-value{background:0 0;color:#222}}@-moz-document url-prefix(){.custom-select{overflow:hidden}.custom-select select{width:120%;width:-moz-calc(100% + 3em);width:calc(100% + em)}}.custom-select select:-moz-focusring{color:transparent;text-shadow:0 0 0 #000}.panel-default.startPage{border-style:dashed;border-color:#a9a9a9;border-width:3px}.busy-updating-wrapper{text-align:center;font-size:20px;position:fixed;bottom:0;right:55px;z-index:1}.busy-submitting-wrapper{position:fixed;top:50%;left:0;right:0;bottom:0}section.public-form{margin-top:-70px}section.content p.breakwords{word-break:break-all}.btn{border:1px solid #c6c6c6}.btn[type=submit]{font-size:1.5em;padding:.35em 1.2em}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;font-size:18px}.input-block{display:block;width:100%}.modal-footer input[type=text]{min-height:34px;padding:7px 8px;font-size:13px;color:#333;vertical-align:middle;background-color:#fff;background-repeat:no-repeat;background-position:right 8px center;border:1px solid #ccc;border-radius:3px;outline:0;box-shadow:inset 0 1px 2px rgba(0,0,0,.075)}.modal-body>.modal-body-alert{color:#796620;background-color:#f8eec7;border-color:#f2e09a;margin:-16px -15px 15px;padding:10px 15px;border-style:solid;border-width:1px 0}div.form-submitted>.field.row{padding-bottom:10%;padding-top:2%}div.form-submitted>.field.row>div{font-size:1.7em}form .accordion-edit{width:inherit}.ui-datepicker.ui-widget{z-index:99!important}form .row.field{padding:1em 0 3em;width:inherit}form .row.field>.field-title{margin-top:.5em;font-size:1.2em;padding-bottom:1.8em;width:inherit}form .row.field>.field-input{font-size:1.4em;color:#777}form.submission-form .row.field.statement>.field-title{font-size:1.7em}form.submission-form .row.field.statement>.field-input{font-size:1em;color:#ddd}form.submission-form .select.radio>.field-input input,form.submission-form .select>.field-input input{width:20%}form.submission-form .field.row.radio .btn.activeBtn{background-color:rgba(0,0,0,.7)!important;color:#fff}form.submission-form .field.row.radio .btn{margin-right:1.2em}form.submission-form .select>.field-input .btn{text-align:left;margin-bottom:.7em}form.submission-form .select>.field-input .btn>span{font-size:1.1em}form .field-input>textarea{padding:.45em .9em;width:100%;line-height:160%;border:3px dashed #ddd}form .field-input>input.hasDatepicker{padding:.45em .9em;width:50%;line-height:160%;border:3px dashed #ddd}form .field-input>input.text-field-input{padding:.45em .9em;width:100%;line-height:160%;border:2px dashed #ddd!important}form .field-input>input.text-field-input:focus{border:0}form .required-error{color:#ddd;font-size:.8em}form .row.field.dropdown>.field-input{height:34px;overflow:hidden}form .row.field.dropdown>.field-input>select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}.config-form{max-width:100%}.config-form>.row{padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}div.config-form .row.field{padding-top:1.5em}div.config-form>.row>.container:nth-of-type(odd){border-right:1px #ddd solid}div.config-form.design>.row>.container:nth-of-type(odd){border-right:none}div.config-form .row>.field-input{padding-left:.1em}div.config-form .row>.field-input label{padding-left:1.3em;display:block}.admin-form>.page-header{padding-bottom:0;margin-bottom:40px}.admin-form>.page-header h1{margin-bottom:0;margin-top:0}.admin-form>.page-header>.col-xs-3{padding-top:1.4em}.admin-form .form-controls .row{padding:5px}.admin-form .page-header{border:none}.admin-form .tab-content{padding-top:3em}.admin-form .panel-heading{background-color:#f1f1f1}.admin-form .panel-heading:hover{background-color:#fff;cursor:pointer}.current-fields .panel-body .row.description textarea,.current-fields .panel-body .row.question input[type=text]{width:100%}.current-fields .panel-body .row.options input[type=text]{width:80%}.current-fields .tool-panel>.panel-default:hover{border-color:#9d9d9d;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading{background-color:#fff;color:#9d9d9d!important}.current-fields .tool-panel>.panel-default .panel-heading:hover{background-color:#eee;color:#000!important;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading a{color:inherit}.submissions-table .table-outer.row{margin-top:1.5em;margin-bottom:2em;margin-left:0!important;margin-right:0!important}.submissions-table .table-outer .col-xs-12{padding-left:0!important;border:1px solid #ddd;overflow-x:scroll;border-radius:3px}.submissions-table .table>thead>tr>th{min-width:8em}.submissions-table .table>tbody>tr.selected{background-color:#efefef}.admin-form .add-field{background-color:#ddd;padding:0 2%;border-radius:3px}.admin-form .add-field .col-xs-6{padding:.25em .4em}.admin-form .add-field .col-xs-6 .panel-heading{border-width:1px;border-style:solid;border-color:#bbb;border-radius:4px}.admin-form .oscar-field-select{margin:10px 0}.view-form-btn.span{padding-right:.6em}.status-light.status-light-off{color:#BE0000}.status-light.status-light-on{color:#3C0}section>section.public-form{padding:0 10% 10%}.form-item{text-align:center;border-bottom:6px inset #ccc;background-color:#eee;width:180px;position:relative;height:215px;margin-bottom:45px}.form-item.create-new input[type=text]{width:inherit;color:#000;border:none}.form-item.create-new{background-color:#838383;color:#fff}.form-item.create-new.new-form{background-color:#ff8383;z-index:11}.form-item.create-new.new-form:hover{background-color:#ff6464}.form-item.new-form input[type=text]{margin-top:.2em;width:inherit;color:#000;border:none;padding:.3em .6em}.form-item.new-form .custom-select{margin-top:.2em}.form-item.new-form .custom-select select{background-color:#fff}.form-item.new-form .details-row{margin-top:1em}.form-item.new-form .details-row.submit{margin-top:1.7em}.form-item.new-form .details-row.submit .btn{font-size:.95em}.form-item.new-form .title-row{margin-top:1em;top:0}.overlay{position:fixed;top:0;left:0;height:100%;width:100%;background-color:rgba(0,0,0,.5);z-index:10}.overlay.submitform{background-color:rgba(256,256,256,.8)}.activeField,.activeField input{background-color:transparent}.field-directive{z-index:9;padding:10% 10% 10% 0;border:25px solid transparent;position:relative}.activeField{z-index:11;position:relative;display:inline-block;border-radius:7px;width:100%;border:25px solid transparent}.form-item.create-new:hover,.form-item:hover{border-bottom:8px inset #ccc;background-color:#d9d9d9}.form-item.create-new:hover{background-color:#515151}.form-item>.row.footer{position:absolute;bottom:0;left:30%}.form-item .title-row{position:relative;top:15px;padding-top:3em;padding-bottom:3.65em}.form-item .title-row h4{font-size:1.3em}.form-item.create-new .title-row{padding:0}.form-item.create-new .title-row h4{font-size:7em}.form-item .details-row{margin-top:3.2em}.form-item .details-row small{font-size:.6em}.form-item.create-new .details-row small{font-size:.95em}.row.auth form .field-input select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}@media (min-width:992px){.nav-users{position:fixed}}.remove-account-container{display:inline-block;position:relative}.btn-remove-account{top:10px;right:10px;position:absolute}section.auth{margin-top:5em}section.auth>h3{font-size:3em;font-weight:500;color:#777}section.auth.signup-view>h3{font-size:4.4em;padding-bottom:.5em} \ No newline at end of file diff --git a/public/dist/application.min.js b/public/dist/application.min.js index df7b3fa9..344224b3 100644 --- a/public/dist/application.min.js +++ b/public/dist/application.min.js @@ -1,2 +1,2 @@ -"use strict";var ApplicationConfiguration=function(){var applicationModuleName="NodeForm",applicationModuleVendorDependencies=["ngResource","ngAnimate","ui.router","ui.bootstrap","ui.utils","ngRaven","cgBusy"],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,console.log("toState: "+toState.name),"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||(console.log("go to home"),event.preventDefault(),$state.go("home"))})}]),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),console.log("access denied: "+!authenticator.canAccess(permissions)),null===permissions||authenticator.canAccess(permissions)||(event.preventDefault(),console.log("access denied"),$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("/"),$stateProvider.state("home",{url:"/",templateUrl:"modules/core/views/home.client.view.html"})}]),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("home")},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?"rating"===field.fieldType||"statement"===field.fieldType?!0:!!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",data:{permissions:["editForm"]}}).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"}).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 console.log("getting form"),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.findOne=function(){Forms.get({formId:$stateParams.formId},function(form){CurrentForm.setForm(form),$scope.myform=form,$scope.myform._id=$stateParams.formId},function(err){console.error("Could not fetch form"),console.error(err)})},$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",function($scope,$rootScope,$state,myForm){$scope.authentication=$rootScope.authentication,$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:function(o){for(var clone=_.clone(o),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.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=_.uniqueId(),$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){field.fieldOptions||(field.fieldOptions=[]);var lastOptionID=0;field.fieldOptions[field.fieldOptions.length-1]&&(lastOptionID=field.fieldOptions[field.fieldOptions.length-1].option_id);var option_id=lastOptionID+1,newOption={option_id:option_id,option_value:"Option "+option_id};field.fieldOptions.push(newOption)},$scope.deleteOption=function(field,option){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",function($http,$compile,$rootScope){var getTemplateUrl=function(field){var type=field.fieldType,templateUrl="modules/forms/views/directiveViews/field/",supported_fields=["textfield","email","textarea","checkbox","date","link","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0&&(templateUrl=templateUrl+type+".html"),templateUrl};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&",design:"=",index:"="},link:function(scope,element){scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType&&(scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0});var templateUrl=getTemplateUrl(scope.field);$http.get(templateUrl).success(function(data){element.html(data).show(),$compile(element.contents())(scope)})}}}]),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:["$scope",function($scope){$scope.authentication=$rootScope.authentication,angular.element(document).ready(function(){$scope.error="",$scope.selected={_id:"",index:null},$scope.submitted=!1,TimeCounter.startClock(),$rootScope.setActiveField=function(field_id,field_index){null===$scope.selected&&($scope.selected={_id:"",index:0}),console.log("field_id: "+field_id),console.log("field_index: "+field_index),console.log($scope.selected),$scope.selected._id=field_id,$scope.selected.index=field_index,setTimeout(function(){$("html, body").animate({scrollTop:$(".activeField").offset().top},200)},10)},$scope.nextField=function(){$scope.selected.index<$scope.myform.form_fields.length-1&&($scope.selected.index++,$scope.selected._id=$scope.myform.form_fields[$scope.selected.index]._id,$rootScope.setActiveField($scope.selected._id,$scope.selected.index))},$scope.prevField=function(){$scope.selected.index>0&&($scope.selected.index=$scope.selected.index-1,$scope.selected._id=$scope.myform.form_fields[$scope.selected.index]._id,$rootScope.setActiveField($scope.selected._id,$scope.selected.index))},$scope.hideOverlay=function(){$scope.selected={_id:"",index:null}},$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(),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,$scope.authentication=Auth,$scope.submitPromise=$http.post("/forms/"+$scope.myform._id,form).success(function(data,status,headers){console.log("form submitted successfully"),$scope.myform.submitted=!0}).error(function(error){console.log(error),$scope.error=error.message})},$scope.reloadForm=function(){TimeCounter.stopClock(),TimeCounter.startClock(),$scope.myform.submitted=!1,$scope.myform.form_fields=_.chain($scope.myform.form_fields).map(function(field){return field.fieldValue="",field}).value()}})}]}}]),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:"checkbox",value:"Checkbox"},{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 console.log(form),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.startClock=function(){_startTime=Date.now()},this.stopClock=function(){return _endTime=Date.now(),that.timeSpent=Math.abs(_endTime.valueOf()-_startTime.valueOf())/1e3,that.timeSpent}}]),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(){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(){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?(console.log("Using local current user."),service._currentUser):$window.user?(console.log("Using cached current user."),service._currentUser=$window.user,service._currentUser):(console.log("Fetching current user from the server."),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 +"use strict";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,console.log("toState: "+toState.name),"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||(console.log("go to home"),event.preventDefault(),$state.go("home"))})}]),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),console.log("access denied: "+!authenticator.canAccess(permissions)),null===permissions||authenticator.canAccess(permissions)||(event.preventDefault(),console.log("access denied"),$state.go("access_denied")))})}]),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])});var ApplicationConfiguration=function(){var applicationModuleName="TellForm",applicationModuleVendorDependencies=["ngResource","TellForm.templates","ngAnimate","ui.router","ui.bootstrap","ui.utils","ngRaven","cgBusy"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();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("/"),$stateProvider.state("home",{url:"/",templateUrl:"modules/core/views/home.client.view.html"})}]),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("home")},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?"rating"===field.fieldType||"statement"===field.fieldType?!0:!!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",data:{permissions:["editForm"]}}).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"}).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:function(o){for(var clone=_.clone(o),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.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("checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType){currField.fieldOptions||(currField.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",function($http,$compile,$rootScope){var getTemplateUrl=function(field){var type=field.fieldType,templateUrl="modules/forms/views/directiveViews/field/",supported_fields=["textfield","email","textarea","checkbox","date","link","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0&&(templateUrl=templateUrl+type+".html"),templateUrl};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&",design:"=",index:"="},link:function(scope,element){scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType&&(scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0});var templateUrl=getTemplateUrl(scope.field);$http.get(templateUrl).success(function(data){element.html(data).show(),$compile(element.contents())(scope)})}}}]),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:["$scope",function($scope){$scope.authentication=$rootScope.authentication,angular.element(document).ready(function(){$scope.error="",$scope.selected={_id:"",index:null},$scope.submitted=!1,TimeCounter.startClock(),$rootScope.setActiveField=function(field_id,field_index){null===$scope.selected&&($scope.selected={_id:"",index:0}),console.log("field_id: "+field_id),console.log("field_index: "+field_index),console.log($scope.selected),$scope.selected._id=field_id,$scope.selected.index=field_index,setTimeout(function(){$("html, body").animate({scrollTop:$(".activeField").offset().top},200)},10)},$scope.nextField=function(){$scope.selected.index<$scope.myform.form_fields.length-1&&($scope.selected.index++,$scope.selected._id=$scope.myform.form_fields[$scope.selected.index]._id,$rootScope.setActiveField($scope.selected._id,$scope.selected.index))},$scope.prevField=function(){$scope.selected.index>0&&($scope.selected.index=$scope.selected.index-1,$scope.selected._id=$scope.myform.form_fields[$scope.selected.index]._id,$rootScope.setActiveField($scope.selected._id,$scope.selected.index))},$scope.hideOverlay=function(){$scope.selected={_id:"",index:null}},$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(),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,$scope.authentication=Auth,$scope.submitPromise=$http.post("/forms/"+$scope.myform._id,form).success(function(data,status,headers){console.log("form submitted successfully"),$scope.myform.submitted=!0}).error(function(error){console.log(error),$scope.error=error.message})},$scope.reloadForm=function(){TimeCounter.stopClock(),TimeCounter.startClock(),$scope.myform.submitted=!1,$scope.myform.form_fields=_.chain($scope.myform.form_fields).map(function(field){return field.fieldValue="",field}).value()}})}]}}]),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:"checkbox",value:"Checkbox"},{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 console.log(form),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.startClock=function(){_startTime=Date.now()},this.stopClock=function(){return _endTime=Date.now(),that.timeSpent=Math.abs(_endTime.valueOf()-_startTime.valueOf())/1e3,that.timeSpent}}]),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(){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(){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?(console.log("Using local current user."),service._currentUser):$window.user?(console.log("Using cached current user."),service._currentUser=$window.user,service._currentUser):(console.log("Fetching current user from the server."),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/views/home.client.view.html b/public/modules/core/views/home.client.view.html index 2d2da1c0..f1f68ae6 100755 --- a/public/modules/core/views/home.client.view.html +++ b/public/modules/core/views/home.client.view.html @@ -10,7 +10,7 @@

- TellForms + TellForm

@@ -32,6 +32,29 @@
+ + +
+
+
+

+ Create your next ______. +

+ +

+ Tell a story with a form. +

+ + + +
+
"); + $templateCache.put("../public/modules/core/views/home.client.view.html", + "

TellForms

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.

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

"); + $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

Created on
"); + $templateCache.put("../public/modules/forms/views/submit-form.client.view.html", + "
"); +}]); diff --git a/public/modules/users/tests/unit/services/user.client.service.test.js b/public/modules/users/tests/unit/services/user.client.service.test.js index ab1e9e90..2d28e4ba 100644 --- a/public/modules/users/tests/unit/services/user.client.service.test.js +++ b/public/modules/users/tests/unit/services/user.client.service.test.js @@ -126,7 +126,7 @@ $httpBackend.expect('GET', '/auth/verify/'+sampleVerifyToken).respond(200); //Run Service Logic to Test - expect(function(){ User.validateVerifyToken(sampleVerifyToken) }).not.toThrow(); + expect(function(){ User.validateVerifyToken(sampleVerifyToken); }).not.toThrow(); $httpBackend.flush(); }); diff --git a/public/populate_template_cache.js b/public/populate_template_cache.js new file mode 100644 index 00000000..879c3da9 --- /dev/null +++ b/public/populate_template_cache.js @@ -0,0 +1,324 @@ +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.

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

"); + $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

Created on
"); + $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", + "

Change how your Form Looks

Change how your Form Looks

Background Color
Question Font Color
Answer Font 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/checkbox.html", + "
0\" ng-click=\"setActiveField(field._id, index)\">
{{field.title}} (* required)
"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/date.html", + "

{{field.title}} *(required)

"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/dropdown.html", + "
0\">

{{field.title}} *(required)


"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/email.html", + "

{{field.title}} *(required)

"); + $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", + "

{{field.title}} *(required)


{{field.description}}


"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/link.html", + "

{{field.title}} *(required)

"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/natural.html", + "

{{field.title}} *(required)


"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/number.html", + "

{{field.title}} *(required)

"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/password.html", + "

{{field.title}} *(required)

"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/radio.html", + "
0\">

{{field.title}} *(required)


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

{{field.title}} *(required)

"); + $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}} *(required)

"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/textfield.html", + "

{{field.title}} *(required)

"); + $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", + "

PDF Generation/EMR

PDF Generation/EMR

Save Submissions as PDFs?
Upload Your PDF Template
{{myform.pdf.originalname}}
Upload your PDF
Autogenerate Form?
Use Oscarhost API?
Oscarhost API Username
Oscarhost API Password
Oscarhost API URL
Oscarhost API Update Type


Advanced Settings

Advanced Settings

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", + "

Click to Add New Field

Add New Field

Add Field

Start Page

Preview Start Page

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" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + "
\n" + + " \n" + + " \n" + + " \n" + + "
\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", + "

{{ myform.title }} (private preview)



{{myform | formValidity}} out of {{myform.visible_form_fields.length}} answered

"); + $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
"); + $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", + "

Signup with your email

Couldn't submit form due to errors:

"); + $templateCache.put("../public/modules/users/views/password/forgot-password.client.view.html", + "

Restore your password

Enter your account email.

{{error}}
{{success}}
"); + $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

{{error}}
{{success}}
"); + $templateCache.put("../public/modules/users/views/settings/change-password.client.view.html", + "

Change your password


Password Changed Successfully
"); + $templateCache.put("../public/modules/users/views/settings/edit-profile.client.view.html", + "

Edit your profile

Profile Saved Successfully
Couldn't Save Your Profile.
Error:
First Name
Last Name

Language
Email (also your username)
"); + $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
"); +}]);