added clientside unit-tests for form and user
This commit is contained in:
parent
b7e5b47a18
commit
9981cd8e8d
@ -6,3 +6,12 @@ env:
|
||||
- NODE_ENV=travis
|
||||
services:
|
||||
- mongodb
|
||||
# before_install:
|
||||
# - npm install -g grunt-cli
|
||||
# - npm install -g bower
|
||||
# install:
|
||||
# - npm install
|
||||
# - bower install --config.interactive=false
|
||||
# before_scripts:
|
||||
# - grunt build
|
||||
|
||||
|
@ -28,6 +28,7 @@ var FormFieldSchema = new Schema({
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
//DAVID: TODO: SEMI-URGENT: Need to come up with a schema for field options
|
||||
fieldOptions: [{
|
||||
type: Schema.Types.Mixed
|
||||
}],
|
||||
@ -50,7 +51,6 @@ var FormFieldSchema = new Schema({
|
||||
validate: [validateFormFieldType, 'Invalid field type']
|
||||
},
|
||||
fieldValue: Schema.Types.Mixed
|
||||
|
||||
});
|
||||
|
||||
FormFieldSchema.static('validTypes', function(){
|
||||
|
@ -1,64 +0,0 @@
|
||||
// 'use strict';
|
||||
|
||||
// /**
|
||||
// * Module dependencies.
|
||||
// */
|
||||
// var should = require('should'),
|
||||
// mongoose = require('mongoose'),
|
||||
// User = mongoose.model('User'),
|
||||
// Article = mongoose.model('Article');
|
||||
|
||||
// /**
|
||||
// * Globals
|
||||
// */
|
||||
// var user, article;
|
||||
|
||||
// /**
|
||||
// * Unit tests
|
||||
// */
|
||||
// describe('Article Model Unit Tests:', function() {
|
||||
// beforeEach(function(done) {
|
||||
// user = new User({
|
||||
// firstName: 'Full',
|
||||
// lastName: 'Name',
|
||||
// displayName: 'Full Name',
|
||||
// email: 'test@test.com',
|
||||
// username: 'username',
|
||||
// password: 'password'
|
||||
// });
|
||||
|
||||
// user.save(function() {
|
||||
// article = new Article({
|
||||
// title: 'Article Title',
|
||||
// content: 'Article Content',
|
||||
// user: user
|
||||
// });
|
||||
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('Method Save', function() {
|
||||
// it('should be able to save without problems', function(done) {
|
||||
// return article.save(function(err) {
|
||||
// should.not.exist(err);
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should be able to show an error when try to save without title', function(done) {
|
||||
// article.title = '';
|
||||
|
||||
// return article.save(function(err) {
|
||||
// should.exist(err);
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// afterEach(function(done) {
|
||||
// Article.remove().exec(function() {
|
||||
// User.remove().exec(done);
|
||||
// });
|
||||
// });
|
||||
// });
|
@ -1,280 +0,0 @@
|
||||
// 'use strict';
|
||||
|
||||
// var should = require('should'),
|
||||
// request = require('supertest'),
|
||||
// app = require('../../server'),
|
||||
// mongoose = require('mongoose'),
|
||||
// User = mongoose.model('User'),
|
||||
// Article = mongoose.model('Article'),
|
||||
// agent = request.agent(app);
|
||||
|
||||
// /**
|
||||
// * Globals
|
||||
// */
|
||||
// var credentials, user, article;
|
||||
|
||||
// /**
|
||||
// * Article routes tests
|
||||
// */
|
||||
// describe('Article CRUD tests', function() {
|
||||
// beforeEach(function(done) {
|
||||
// // Create user credentials
|
||||
// credentials = {
|
||||
// username: 'username',
|
||||
// password: 'password'
|
||||
// };
|
||||
|
||||
// // Create a new user
|
||||
// user = new User({
|
||||
// firstName: 'Full',
|
||||
// lastName: 'Name',
|
||||
// displayName: 'Full Name',
|
||||
// email: 'test@test.com',
|
||||
// username: credentials.username,
|
||||
// password: credentials.password,
|
||||
// provider: 'local'
|
||||
// });
|
||||
|
||||
// // Save a user to the test db and create new article
|
||||
// user.save(function() {
|
||||
// article = {
|
||||
// title: 'Article Title',
|
||||
// content: 'Article Content'
|
||||
// };
|
||||
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should be able to save an article if logged in', function(done) {
|
||||
// agent.post('/auth/signin')
|
||||
// .send(credentials)
|
||||
// .expect(200)
|
||||
// .end(function(signinErr, signinRes) {
|
||||
// // Handle signin error
|
||||
// if (signinErr) done(signinErr);
|
||||
|
||||
// // Get the userId
|
||||
// var userId = user.id;
|
||||
|
||||
// // Save a new article
|
||||
// agent.post('/articles')
|
||||
// .send(article)
|
||||
// .expect(200)
|
||||
// .end(function(articleSaveErr, articleSaveRes) {
|
||||
// // Handle article save error
|
||||
// if (articleSaveErr) done(articleSaveErr);
|
||||
|
||||
// // Get a list of articles
|
||||
// agent.get('/articles')
|
||||
// .end(function(articlesGetErr, articlesGetRes) {
|
||||
// // Handle article save error
|
||||
// if (articlesGetErr) done(articlesGetErr);
|
||||
|
||||
// // Get articles list
|
||||
// var articles = articlesGetRes.body;
|
||||
|
||||
// // Set assertions
|
||||
// (articles[0].user._id).should.equal(userId);
|
||||
// (articles[0].title).should.match('Article Title');
|
||||
|
||||
// // Call the assertion callback
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should not be able to save an article if not logged in', function(done) {
|
||||
// agent.post('/articles')
|
||||
// .send(article)
|
||||
// .expect(401)
|
||||
// .end(function(articleSaveErr, articleSaveRes) {
|
||||
// // Call the assertion callback
|
||||
// done(articleSaveErr);
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should not be able to save an article if no title is provided', function(done) {
|
||||
// // Invalidate title field
|
||||
// article.title = '';
|
||||
|
||||
// agent.post('/auth/signin')
|
||||
// .send(credentials)
|
||||
// .expect(200)
|
||||
// .end(function(signinErr, signinRes) {
|
||||
// // Handle signin error
|
||||
// if (signinErr) done(signinErr);
|
||||
|
||||
// // Get the userId
|
||||
// var userId = user.id;
|
||||
|
||||
// // Save a new article
|
||||
// agent.post('/articles')
|
||||
// .send(article)
|
||||
// .expect(400)
|
||||
// .end(function(articleSaveErr, articleSaveRes) {
|
||||
// // Set message assertion
|
||||
// (articleSaveRes.body.message).should.match('Title cannot be blank');
|
||||
|
||||
// // Handle article save error
|
||||
// done(articleSaveErr);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should be able to update an article if signed in', function(done) {
|
||||
// agent.post('/auth/signin')
|
||||
// .send(credentials)
|
||||
// .expect(200)
|
||||
// .end(function(signinErr, signinRes) {
|
||||
// // Handle signin error
|
||||
// if (signinErr) done(signinErr);
|
||||
|
||||
// // Get the userId
|
||||
// var userId = user.id;
|
||||
|
||||
// // Save a new article
|
||||
// agent.post('/articles')
|
||||
// .send(article)
|
||||
// .expect(200)
|
||||
// .end(function(articleSaveErr, articleSaveRes) {
|
||||
// // Handle article save error
|
||||
// if (articleSaveErr) done(articleSaveErr);
|
||||
|
||||
// // Update article title
|
||||
// article.title = 'WHY YOU GOTTA BE SO MEAN?';
|
||||
|
||||
// // Update an existing article
|
||||
// agent.put('/articles/' + articleSaveRes.body._id)
|
||||
// .send(article)
|
||||
// .expect(200)
|
||||
// .end(function(articleUpdateErr, articleUpdateRes) {
|
||||
// // Handle article update error
|
||||
// if (articleUpdateErr) done(articleUpdateErr);
|
||||
|
||||
// // Set assertions
|
||||
// (articleUpdateRes.body._id).should.equal(articleSaveRes.body._id);
|
||||
// (articleUpdateRes.body.title).should.match('WHY YOU GOTTA BE SO MEAN?');
|
||||
|
||||
// // Call the assertion callback
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should be able to get a list of articles if not signed in', function(done) {
|
||||
// // Create new article model instance
|
||||
// var articleObj = new Article(article);
|
||||
|
||||
// // Save the article
|
||||
// articleObj.save(function() {
|
||||
// // Request articles
|
||||
// request(app).get('/articles')
|
||||
// .end(function(req, res) {
|
||||
// // Set assertion
|
||||
// res.body.should.be.an.Array.with.lengthOf(1);
|
||||
|
||||
// // Call the assertion callback
|
||||
// done();
|
||||
// });
|
||||
|
||||
// });
|
||||
// });
|
||||
|
||||
|
||||
// it('should be able to get a single article if not signed in', function(done) {
|
||||
// // Create new article model instance
|
||||
// var articleObj = new Article(article);
|
||||
|
||||
// // Save the article
|
||||
// articleObj.save(function() {
|
||||
// request(app).get('/articles/' + articleObj._id)
|
||||
// .end(function(req, res) {
|
||||
// // Set assertion
|
||||
// res.body.should.be.an.Object.with.property('title', article.title);
|
||||
|
||||
// // Call the assertion callback
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should return proper error for single article which doesnt exist, if not signed in', function(done) {
|
||||
// request(app).get('/articles/test')
|
||||
// .end(function(req, res) {
|
||||
// // Set assertion
|
||||
// res.body.should.be.an.Object.with.property('message', 'Article is invalid');
|
||||
|
||||
// // Call the assertion callback
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should be able to delete an article if signed in', function(done) {
|
||||
// agent.post('/auth/signin')
|
||||
// .send(credentials)
|
||||
// .expect(200)
|
||||
// .end(function(signinErr, signinRes) {
|
||||
// // Handle signin error
|
||||
// if (signinErr) done(signinErr);
|
||||
|
||||
// // Get the userId
|
||||
// var userId = user.id;
|
||||
|
||||
// // Save a new article
|
||||
// agent.post('/articles')
|
||||
// .send(article)
|
||||
// .expect(200)
|
||||
// .end(function(articleSaveErr, articleSaveRes) {
|
||||
// // Handle article save error
|
||||
// if (articleSaveErr) done(articleSaveErr);
|
||||
|
||||
// // Delete an existing article
|
||||
// agent.delete('/articles/' + articleSaveRes.body._id)
|
||||
// .send(article)
|
||||
// .expect(200)
|
||||
// .end(function(articleDeleteErr, articleDeleteRes) {
|
||||
// // Handle article error error
|
||||
// if (articleDeleteErr) done(articleDeleteErr);
|
||||
|
||||
// // Set assertions
|
||||
// (articleDeleteRes.body._id).should.equal(articleSaveRes.body._id);
|
||||
|
||||
// // Call the assertion callback
|
||||
// done();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should not be able to delete an article if not signed in', function(done) {
|
||||
// // Set article user
|
||||
// article.user = user;
|
||||
|
||||
// // Create new article model instance
|
||||
// var articleObj = new Article(article);
|
||||
|
||||
// // Save the article
|
||||
// articleObj.save(function() {
|
||||
// // Try deleting article
|
||||
// request(app).delete('/articles/' + articleObj._id)
|
||||
// .expect(401)
|
||||
// .end(function(articleDeleteErr, articleDeleteRes) {
|
||||
// // Set message assertion
|
||||
// (articleDeleteRes.body.message).should.match('User is not logged in');
|
||||
|
||||
// // Handle article error error
|
||||
// done(articleDeleteErr);
|
||||
// });
|
||||
|
||||
// });
|
||||
// });
|
||||
|
||||
// afterEach(function(done) {
|
||||
// User.remove().exec(function() {
|
||||
// Article.remove().exec(done);
|
||||
// });
|
||||
// });
|
||||
// });
|
@ -16,7 +16,7 @@ var should = require('should'),
|
||||
/**
|
||||
* Globals
|
||||
*/
|
||||
var credentials, user, _Form;
|
||||
var credentials, user, _Form, userSession;
|
||||
|
||||
/**
|
||||
* Form routes tests
|
||||
@ -496,6 +496,7 @@ describe('Form CRUD tests', function() {
|
||||
User.remove().exec(function() {
|
||||
Form.remove().exec(function() {
|
||||
userSession.destroy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "MedForm",
|
||||
"name": "NodeForm",
|
||||
"description": "PDF generated form builder",
|
||||
"version": "1.0.3",
|
||||
"homepage": "https://github.com/whitef0x0/medform",
|
||||
"homepage": "https://github.com/whitef0x0/NodeForm",
|
||||
"authors": [
|
||||
"David Baldwynn <polydaic@gmail.com> (http://baldwynn.me)"
|
||||
],
|
||||
|
12
config/env/all.js
vendored
12
config/env/all.js
vendored
@ -92,12 +92,16 @@ module.exports = {
|
||||
],
|
||||
views: [
|
||||
'public/modules/*/views/*.html',
|
||||
'public/modules/*/views/**/*.html'
|
||||
'public/modules/*/views/*/*.html',
|
||||
'public/modules/*/views/*/*/*.html',
|
||||
],
|
||||
tests: [
|
||||
unit_tests: [
|
||||
'public/lib/angular-mocks/angular-mocks.js',
|
||||
'public/modules/*/tests/*.js',
|
||||
'public/modules/*/tests/*/*.js',
|
||||
'public/modules/*/tests/unit/*.js',
|
||||
'public/modules/*/tests/unit/**/*.js',
|
||||
],
|
||||
e2e_tests: [
|
||||
'public/modules/*/tests/e2e/**.js',
|
||||
]
|
||||
}
|
||||
};
|
||||
|
BIN
docs/Autosave Notification Types/update_type1.tiff
Normal file
BIN
docs/Autosave Notification Types/update_type1.tiff
Normal file
Binary file not shown.
BIN
docs/Autosave Notification Types/update_type2.tiff
Normal file
BIN
docs/Autosave Notification Types/update_type2.tiff
Normal file
Binary file not shown.
BIN
docs/Autosave Notification Types/update_type3.tiff
Normal file
BIN
docs/Autosave Notification Types/update_type3.tiff
Normal file
Binary file not shown.
BIN
docs/Autosave Notification Types/update_type4.tiff
Normal file
BIN
docs/Autosave Notification Types/update_type4.tiff
Normal file
Binary file not shown.
BIN
docs/Autosave Notification Types/update_type5.tiff
Normal file
BIN
docs/Autosave Notification Types/update_type5.tiff
Normal file
Binary file not shown.
24
gruntfile.js
24
gruntfile.js
@ -152,18 +152,18 @@ module.exports = function(grunt) {
|
||||
configFile: 'karma.conf.js'
|
||||
}
|
||||
},
|
||||
// protractor: {
|
||||
// options: {
|
||||
// configFile: 'protractor.conf.js',
|
||||
// keepAlive: true,
|
||||
// noColor: false
|
||||
// },
|
||||
// e2e: {
|
||||
// options: {
|
||||
// args: {} // Target-specific arguments
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
protractor: {
|
||||
options: {
|
||||
configFile: 'protractor.conf.js',
|
||||
keepAlive: true,
|
||||
noColor: false
|
||||
},
|
||||
e2e: {
|
||||
options: {
|
||||
args: {} // Target-specific arguments
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Load NPM tasks
|
||||
|
@ -15,15 +15,17 @@ module.exports = function(config) {
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
// List of files / patterns to load in the browser
|
||||
files: bowerDep.concat(applicationConfiguration.assets.js, applicationConfiguration.assets.tests, applicationConfiguration.assets.views),
|
||||
files: bowerDep.concat(applicationConfiguration.assets.js, applicationConfiguration.assets.unit_tests, applicationConfiguration.assets.views),
|
||||
|
||||
// Test results reporter to use
|
||||
// Possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
|
||||
reporters: ['mocha', 'html', 'progress'],
|
||||
|
||||
preprocessors: {
|
||||
'public/modules/**/*.html': ['ng-html2js'],
|
||||
'public/modules/**/*.js': ['coverage'],
|
||||
'public/modules/*/views/**/*.html': ['ng-html2js'],
|
||||
'public/modules/*/views/*.html': ['ng-html2js'],
|
||||
'public/modules/*/*.js': ['coverage'],
|
||||
'public/modules/*/*[!tests]*/*.js': ['coverage'],
|
||||
},
|
||||
|
||||
ngHtml2JsPreprocessor: {
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "Medform",
|
||||
"name": "NodeForm",
|
||||
"description": "PDF generated form builder",
|
||||
"version": "1.0.3",
|
||||
"homepage": "https://github.com/whitef0x0/medform",
|
||||
"homepage": "https://github.com/whitef0x0/NodeForm",
|
||||
"authors": [
|
||||
"David Baldwynn <polydaic@gmail.com>"
|
||||
],
|
||||
@ -56,7 +56,7 @@
|
||||
"karma-chrome-launcher": "~0.1.2",
|
||||
"karma-coverage": "~0.2.0",
|
||||
"karma-firefox-launcher": "~0.1.3",
|
||||
"karma-jasmine": "~0.2.1",
|
||||
"karma-jasmine": "^0.2.3",
|
||||
"karma-phantomjs-launcher": "~0.1.2",
|
||||
"load-grunt-tasks": "~1.0.0",
|
||||
"lodash": "~2.4.1",
|
||||
@ -90,7 +90,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"karma-chrome-launcher": "^0.1.12",
|
||||
"karma-jasmine": "^0.2.3",
|
||||
"karma-jasmine-html-reporter": "^0.1.8",
|
||||
"karma-mocha-reporter": "^1.1.1",
|
||||
"karma-ng-html2js-preprocessor": "^0.1.2",
|
||||
|
@ -24,55 +24,55 @@ angular.module(ApplicationConfiguration.applicationModuleName).constant('USER_RO
|
||||
superuser: 'superuser',
|
||||
});
|
||||
|
||||
// angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', '$state', '$stateParams',
|
||||
// function($rootScope, Auth, $state, $stateParams) {
|
||||
angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', '$state', '$stateParams',
|
||||
function($rootScope, Auth, $state, $stateParams) {
|
||||
|
||||
// $rootScope.$state = $state;
|
||||
// $rootScope.$stateParams = $stateParams;
|
||||
$rootScope.$state = $state;
|
||||
$rootScope.$stateParams = $stateParams;
|
||||
|
||||
// // add previous state property
|
||||
// $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) {
|
||||
// $state.previous = fromState;
|
||||
// add previous state property
|
||||
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) {
|
||||
$state.previous = fromState;
|
||||
|
||||
// //Redirect to listForms if user is authenticated
|
||||
// if(toState.name === 'home' || toState.name === 'signin' || toState.name === 'resendVerifyEmail' || toState.name === 'verify' || toState.name === 'signup' || toState.name === 'signup-success'){
|
||||
// if(Auth.isAuthenticated()){
|
||||
// event.preventDefault(); // stop current execution
|
||||
// $state.go('listForms'); // go to listForms page
|
||||
// }
|
||||
// }
|
||||
// //Redirect to 'home' route if user is not authenticated
|
||||
// else if(toState.name !== 'access_denied' && !Auth.isAuthenticated() ){
|
||||
// event.preventDefault(); // stop current execution
|
||||
// $state.go('home'); // go to listForms page
|
||||
// }
|
||||
//Redirect to listForms if user is authenticated
|
||||
if(toState.name === 'home' || toState.name === 'signin' || toState.name === 'resendVerifyEmail' || toState.name === 'verify' || toState.name === 'signup' || toState.name === 'signup-success'){
|
||||
if(Auth.isAuthenticated()){
|
||||
event.preventDefault(); // stop current execution
|
||||
$state.go('listForms'); // go to listForms page
|
||||
}
|
||||
}
|
||||
//Redirect to 'home' route if user is not authenticated
|
||||
else if(toState.name !== 'access_denied' && !Auth.isAuthenticated() ){
|
||||
event.preventDefault(); // stop current execution
|
||||
$state.go('home'); // go to listForms page
|
||||
}
|
||||
|
||||
// });
|
||||
});
|
||||
|
||||
// }
|
||||
// ]);
|
||||
}
|
||||
]);
|
||||
|
||||
// //Page access/authorization logic
|
||||
// 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;
|
||||
//Page access/authorization logic
|
||||
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;
|
||||
Auth.ensureHasCurrentUser(User);
|
||||
user = Auth.currentUser;
|
||||
|
||||
// if(user){
|
||||
// authenticator = new Authorizer(user);
|
||||
if(user){
|
||||
authenticator = new Authorizer(user);
|
||||
|
||||
// if( (permissions !== null) && !authenticator.canAccess(permissions) ){
|
||||
// event.preventDefault();
|
||||
// console.log('access denied')
|
||||
// $state.go('access_denied');
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }]);
|
||||
if( (permissions !== null) && !authenticator.canAccess(permissions) ){
|
||||
event.preventDefault();
|
||||
console.log('access denied')
|
||||
$state.go('access_denied');
|
||||
}
|
||||
}
|
||||
});
|
||||
}]);
|
||||
|
||||
//Then define the init function for starting up the application
|
||||
angular.element(document).ready(function() {
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Init the application configuration module for AngularJS application
|
||||
var ApplicationConfiguration = (function() {
|
||||
// Init module configuration options
|
||||
var applicationModuleName = 'medform';
|
||||
var applicationModuleName = 'NodeForm';
|
||||
var applicationModuleVendorDependencies = ['ngResource', 'ngAnimate', 'ui.router', 'ui.bootstrap', 'ui.utils', 'ngRaven', 'cgBusy'];
|
||||
|
||||
// Add a new vertical module
|
||||
|
519
public/dist/application.js
vendored
519
public/dist/application.js
vendored
@ -3,7 +3,7 @@
|
||||
// Init the application configuration module for AngularJS application
|
||||
var ApplicationConfiguration = (function() {
|
||||
// Init module configuration options
|
||||
var applicationModuleName = 'medform';
|
||||
var applicationModuleName = 'NodeForm';
|
||||
var applicationModuleVendorDependencies = ['ngResource', 'ngAnimate', 'ui.router', 'ui.bootstrap', 'ui.utils', 'ngRaven', 'cgBusy'];
|
||||
|
||||
// Add a new vertical module
|
||||
@ -660,9 +660,7 @@ angular.module('forms').controller('SubmitFormController', ['$scope', '$rootScop
|
||||
//error
|
||||
function( error ){
|
||||
$scope.error = error.message;
|
||||
console.log('ERROR: '+error.message);
|
||||
throw new Error('Error: '+error.message);
|
||||
|
||||
console.error('ERROR: '+error.message);
|
||||
$state.go('access_denied');
|
||||
}
|
||||
);
|
||||
@ -677,9 +675,6 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
|
||||
return {
|
||||
require: ['^form'],
|
||||
restrict: 'AE',
|
||||
controller: function ($scope) {
|
||||
|
||||
},
|
||||
link: function($scope, $element, $attrs, $ctrls) {
|
||||
angular.element(document).ready(function() {
|
||||
|
||||
@ -775,46 +770,10 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('forms').directive('changeFocus', function() {
|
||||
angular.module('forms').directive('configureFormDirective', ['$rootScope', '$http', 'Upload', '$timeout', 'TimeCounter', 'Auth', 'FormFields',
|
||||
function ($rootScope, $http, Upload, $timeout, TimeCounter, Auth, FormFields) {
|
||||
return {
|
||||
scope:{
|
||||
focusDownId: '@',
|
||||
focusUpId: '@',
|
||||
},
|
||||
link: function(scope, elem, attrs) {
|
||||
// console.log('aoeuaoeuaoeuaou');
|
||||
scope.focusUp = function(){
|
||||
if(!scope.$first) {
|
||||
console.log('focusUp');
|
||||
elem[0].previousElementSibling.find('input').focus();
|
||||
}
|
||||
scope.apply();
|
||||
};
|
||||
scope.focusDown = function(){
|
||||
if(!scope.$last) {
|
||||
elem[0].nextElementSibling.focus();
|
||||
}
|
||||
scope.apply();
|
||||
};
|
||||
|
||||
//Bind 'focus-down' click event to given dom element
|
||||
angular.element('#' + scope.focusDownId).bind('click', function() {
|
||||
scope.focusDown();
|
||||
});
|
||||
|
||||
//Bind 'focus-up' click event to given dom element
|
||||
angular.element('#' + scope.focusUpId).bind('click', function() {
|
||||
scope.focusUp();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
'use strict';
|
||||
|
||||
angular.module('forms').directive('configureFormDirective', ['$rootScope', '$http', 'Upload', '$timeout', 'timeCounter', 'Auth', 'FormFields',
|
||||
function ($rootScope, $http, Upload, $timeout, timeCounter, Auth, FormFields) {
|
||||
return {
|
||||
templateUrl: './modules/forms/views/directiveViews/form/configure-form.client.view.html',
|
||||
templateUrl: 'modules/forms/views/directiveViews/form/configure-form.client.view.html',
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
myform:'=',
|
||||
@ -827,20 +786,20 @@ angular.module('forms').directive('configureFormDirective', ['$rootScope', '$htt
|
||||
$scope.pdfLoading = false;
|
||||
$scope.languages = $rootScope.languages;
|
||||
|
||||
var _current_upload = null;
|
||||
this._current_upload = null;
|
||||
$scope.resetForm = $rootScope.resetForm;
|
||||
$scope.update = $rootScope.update;
|
||||
|
||||
var _unbindedPdfFields = $scope.pdfFields;
|
||||
this._unbindedPdfFields = $scope.pdfFields;
|
||||
|
||||
//DAVID: TODO: finish this so we can create a Form.pdfFieldMap
|
||||
// $scope.getUnbindedPdfFields = function(fieldType){
|
||||
// _unbindedPdfFields = $scope.pdfFields
|
||||
// this._unbindedPdfFields = $scope.pdfFields
|
||||
// }
|
||||
|
||||
//PDF Functions
|
||||
$scope.cancelUpload = function(){
|
||||
_current_upload.abort();
|
||||
this._current_upload.abort();
|
||||
$scope.pdfLoading = false;
|
||||
$scope.removePDF();
|
||||
};
|
||||
@ -854,13 +813,14 @@ angular.module('forms').directive('configureFormDirective', ['$rootScope', '$htt
|
||||
};
|
||||
|
||||
$scope.uploadPDF = function(files) {
|
||||
console.log(files)
|
||||
|
||||
if (files && files.length) {
|
||||
// for (var i = 0; i < files.length; i++) {
|
||||
var file = files[0];
|
||||
console.log(file);
|
||||
|
||||
_current_upload = Upload.upload({
|
||||
this._current_upload = Upload.upload({
|
||||
url: '/upload/pdf',
|
||||
fields: {
|
||||
'user': $scope.user,
|
||||
@ -871,6 +831,7 @@ angular.module('forms').directive('configureFormDirective', ['$rootScope', '$htt
|
||||
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
|
||||
$scope.log = 'progress: ' + progressPercentage + '% ' +
|
||||
evt.config.file.name + '\n' + $scope.log;
|
||||
|
||||
$scope.pdfLoading = true;
|
||||
}).success(function (data, status, headers, config) {
|
||||
$scope.log = 'file ' + data.originalname + ' uploaded as '+ data.name +'. JSON: ' + JSON.stringify(data) + '\n' + $scope.log;
|
||||
@ -898,16 +859,14 @@ angular.module('forms').directive('configureFormDirective', ['$rootScope', '$htt
|
||||
]);
|
||||
'use strict';
|
||||
|
||||
angular.module('forms')
|
||||
.directive('editFormDirective', ['$rootScope', '$q', '$http', '$timeout', 'timeCounter', 'Auth', 'FormFields',
|
||||
function ($rootScope, $q, $http, $timeout, timeCounter, Auth, FormFields) {
|
||||
angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$http', '$timeout', 'TimeCounter', 'Auth', 'FormFields',
|
||||
function ($rootScope, $q, $http, $timeout, TimeCounter, Auth, FormFields) {
|
||||
return {
|
||||
templateUrl: './modules/forms/views/directiveViews/form/edit-form.client.view.html',
|
||||
templateUrl: 'modules/forms/views/directiveViews/form/edit-form.client.view.html',
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
myform:'=',
|
||||
},
|
||||
// transclude: true,
|
||||
controller: function($scope){
|
||||
|
||||
/*
|
||||
@ -915,13 +874,15 @@ angular.module('forms')
|
||||
*/
|
||||
//Populate AddField with all available form field types
|
||||
$scope.addField = {};
|
||||
$scope.addField.types = FormFields.fields;
|
||||
$scope.addField.types = FormFields.types;
|
||||
|
||||
$scope.addField.types.forEach(function(type){
|
||||
type.lastAddedID = 1;
|
||||
return type;
|
||||
});
|
||||
|
||||
$scope.lastButtonID = 0;
|
||||
|
||||
// Accordion settings
|
||||
$scope.accordion = {};
|
||||
$scope.accordion.oneAtATime = true;
|
||||
@ -974,7 +935,7 @@ angular.module('forms')
|
||||
// // console.log('has class .dropzone :'+);
|
||||
// // if ($(e.target).hasClass('dropzone') && ui.item.sortable.droptarget && e.target != ui.item.sortable.droptarget[0] ) {
|
||||
// // // restore original types
|
||||
// // $scope.addField.types = FormFields.fields;
|
||||
// // $scope.addField.types = FormFields.types;
|
||||
// // }
|
||||
|
||||
|
||||
@ -986,63 +947,47 @@ angular.module('forms')
|
||||
** Field CRUD Methods
|
||||
*/
|
||||
// Add a new field
|
||||
$scope.addNewField = function(addOrReturn, fieldType){
|
||||
$scope.addNewField = function(modifyForm, fieldType){
|
||||
|
||||
// incr field_id counter
|
||||
$scope.addField.lastAddedID++;
|
||||
var fieldTitle;
|
||||
|
||||
for(var i = 0; i < $scope.addField.types.length; i++){
|
||||
// console.log($scope.addField.types[i].name === fieldType);
|
||||
if($scope.addField.types[i].name === fieldType){
|
||||
$scope.addField.types[i].lastAddedID++;
|
||||
// console.log($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' : true,
|
||||
'disabled' : false,
|
||||
title: fieldTitle,
|
||||
fieldType: fieldType,
|
||||
fieldValue: '',
|
||||
required: true,
|
||||
disabled: false,
|
||||
deletePreserved: false
|
||||
};
|
||||
console.log('\n\n---------\nAdded field CLIENT');
|
||||
console.log(newField);
|
||||
// console.log('\n\n---------\nAdded field CLIENT');
|
||||
// console.log(newField);
|
||||
newField._id = _.uniqueId();
|
||||
|
||||
// put newField into fields array
|
||||
if(addOrReturn){
|
||||
if(modifyForm){
|
||||
$scope.myform.form_fields.push(newField);
|
||||
}else {
|
||||
return newField;
|
||||
}
|
||||
|
||||
|
||||
// console.log(Date.now());
|
||||
// console.log($scope.myform.form_fields.length);
|
||||
return newField;
|
||||
};
|
||||
|
||||
// deletes particular field on button click
|
||||
$scope.deleteField = function (hashKey){
|
||||
// console.log($scope.myform.form_fields);
|
||||
for(var i = 0; i < $scope.myform.form_fields.length; i++){
|
||||
// console.log($scope.myform.form_fields[i].$$hashKey === hashKey);
|
||||
if($scope.myform.form_fields[i].$$hashKey === hashKey){
|
||||
$scope.myform.form_fields.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Delete particular field on button click
|
||||
$scope.deleteField = function (field_index){
|
||||
$scope.myform.form_fields.splice(field_index, 1);
|
||||
};
|
||||
$scope.duplicateField = function (field_index){
|
||||
console.log('field_index: '+field_index);
|
||||
var field = $scope.addNewField(false, $scope.myform.form_fields[field_index].fieldType);
|
||||
field.title = $scope.myform.form_fields[field_index].title;
|
||||
console.log($scope.myform.form_fields[field_index]);
|
||||
var currField = $scope.myform.form_fields[field_index];
|
||||
|
||||
//Insert field at selected index
|
||||
$scope.myform.form_fields.splice(field_index+1, 0, field);
|
||||
|
||||
$scope.myform.form_fields.splice(field_index+1, 0, currField);
|
||||
};
|
||||
|
||||
|
||||
@ -1051,24 +996,27 @@ angular.module('forms')
|
||||
*/
|
||||
|
||||
// add new Button to the startPage/EndPage
|
||||
$scope.addButton = function (newButtons){
|
||||
$scope.addButton = function(){
|
||||
|
||||
var newButton = {};
|
||||
newButton.bgColor = '#ddd';
|
||||
newButton.color = '#ffffff';
|
||||
newButton.text = 'Button';
|
||||
newButton._id = _.uniqueId();
|
||||
|
||||
$scope.myform.startPage.buttons.push(newButton);
|
||||
};
|
||||
|
||||
// delete particular Button
|
||||
$scope.deleteButton = function(button){
|
||||
var hashKey = _.chain(button.$$hashKey).words().last().parseInt().value();
|
||||
|
||||
// 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();;
|
||||
// var currHashKey = _.chain($scope.myform.startPage.buttons[i].$$hashKey).words().last().parseInt().value();
|
||||
currID = $scope.myform.startPage.buttons[i]._id;
|
||||
console.log(currID);
|
||||
|
||||
if(currHashKey === hashKey){
|
||||
if(currID === button._id){
|
||||
$scope.myform.startPage.buttons.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
@ -1076,7 +1024,6 @@ angular.module('forms')
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Field Option Methods
|
||||
*/
|
||||
@ -1087,8 +1034,9 @@ angular.module('forms')
|
||||
|
||||
var lastOptionID = 0;
|
||||
|
||||
if(field.fieldOptions[field.fieldOptions.length-1])
|
||||
if(field.fieldOptions[field.fieldOptions.length-1]){
|
||||
lastOptionID = field.fieldOptions[field.fieldOptions.length-1].option_id;
|
||||
}
|
||||
|
||||
// new option's id
|
||||
var option_id = lastOptionID + 1;
|
||||
@ -1129,6 +1077,122 @@ angular.module('forms')
|
||||
]);
|
||||
'use strict';
|
||||
|
||||
angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', '$http', 'Upload', '$timeout', 'TimeCounter', 'Auth', 'FormFields',
|
||||
function ($rootScope, $http, Upload, $timeout, TimeCounter, Auth, FormFields) {
|
||||
return {
|
||||
templateUrl: 'modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html',
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
myform:'=',
|
||||
user:'='
|
||||
},
|
||||
controller: function($scope){
|
||||
$scope.table = {
|
||||
masterChecker: false,
|
||||
rows: []
|
||||
};
|
||||
|
||||
//Fetch and display submissions of Form
|
||||
$scope.initFormSubmissions = function(){
|
||||
$http.get('/forms/'+$scope.myform._id+'/submissions')
|
||||
.success(function(data, status, headers){
|
||||
|
||||
console.log(data[0].form_fields);
|
||||
|
||||
var _tmpSubFormFields,
|
||||
defaultFormFields = _.cloneDeep($scope.myform.form_fields);
|
||||
|
||||
|
||||
//Iterate through form's submissions
|
||||
for(var i=0; i<data.length; i++){
|
||||
_tmpSubFormFields = _.merge(defaultFormFields, data[i].form_fields);
|
||||
data[i].form_fields = _tmpSubFormFields;
|
||||
}
|
||||
|
||||
// console.log(JSON.stringify(_data));
|
||||
$scope.table.rows = data;
|
||||
|
||||
// console.log('form submissions successfully fetched');
|
||||
// console.log( JSON.parse(JSON.stringify($scope.submissions)) ) ;
|
||||
// console.log( JSON.parse(JSON.stringify($scope.myform.form_fields)) );
|
||||
})
|
||||
.error(function(err){
|
||||
console.error('Could not fetch form submissions.\nError: '+err);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
** Table Functions
|
||||
*/
|
||||
$scope.isAtLeastOneChecked = function(){
|
||||
for(var i=0; i<$scope.table.rows.length; i++){
|
||||
if($scope.table.rows[i].selected) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
$scope.toggleAllCheckers = function(){
|
||||
for(var i=0; i<$scope.table.rows.length; i++){
|
||||
$scope.table.rows[i].selected = $scope.table.masterChecker;
|
||||
}
|
||||
};
|
||||
$scope.toggleObjSelection = function($event, description) {
|
||||
$event.stopPropagation();
|
||||
};
|
||||
$scope.rowClicked = function(row_index) {
|
||||
$scope.table.rows[row_index].selected = !$scope.table.rows[row_index].selected;
|
||||
};
|
||||
|
||||
/*
|
||||
* Form Submission Methods
|
||||
*/
|
||||
//Delete selected submissions of Form
|
||||
$scope.deleteSelectedSubmissions = function(){
|
||||
|
||||
var delete_ids = _.chain($scope.table.rows).filter(function(row){
|
||||
return !!row.selected;
|
||||
}).pluck('_id').value();
|
||||
|
||||
$http({ url: '/forms/'+$scope.myform._id+'/submissions',
|
||||
method: 'DELETE',
|
||||
data: {deleted_submissions: delete_ids},
|
||||
headers: {'Content-Type': 'application/json;charset=utf-8'}
|
||||
}).success(function(data, status, headers){
|
||||
//Remove deleted ids from table
|
||||
var tmpArray = [];
|
||||
for(var i=0; i<$scope.table.rows.length; i++){
|
||||
if(!$scope.table.rows[i].selected){
|
||||
tmpArray.push($scope.table.rows[i]);
|
||||
}
|
||||
}
|
||||
$scope.table.rows = tmpArray;
|
||||
})
|
||||
.error(function(err){
|
||||
console.log('Could not delete form submissions.\nError: ');
|
||||
console.log(err);
|
||||
console.error = err;
|
||||
});
|
||||
};
|
||||
|
||||
//Export selected submissions of Form
|
||||
$scope.exportSubmissions = function(type){
|
||||
var fileMIMETypeMap = {
|
||||
'xls': 'vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'json': 'json',
|
||||
'csv': 'csv',
|
||||
};
|
||||
|
||||
var blob = new Blob([document.getElementById('table-submission-data').innerHTM], {
|
||||
type: 'application/'+fileMIMETypeMap[type]+';charset=utf-8'
|
||||
});
|
||||
saveAs(blob, $scope.myform.title+'_sumbissions_export_'+Date.now()+'.'+type);
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
||||
'use strict';
|
||||
|
||||
angular.module('forms').directive('fieldIconDirective', function($http, $compile) {
|
||||
|
||||
return {
|
||||
@ -1171,14 +1235,14 @@ var __indexOf = [].indexOf || function(item) {
|
||||
return -1;
|
||||
};
|
||||
|
||||
angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$rootScope',
|
||||
function($http, $compile, $rootScope) {
|
||||
angular.module('forms').directive('fieldDirective', ['$templateCache', '$http', '$compile', '$rootScope',
|
||||
function($templateCache, $http, $compile, $rootScope) {
|
||||
|
||||
|
||||
var getTemplateUrl = function(field) {
|
||||
|
||||
var type = field.fieldType;
|
||||
var templateUrl = './modules/forms/views/directiveViews/field/';
|
||||
var templateUrl = 'modules/forms/views/directiveViews/field/';
|
||||
var supported_fields = [
|
||||
'textfield',
|
||||
'email',
|
||||
@ -1197,8 +1261,10 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root
|
||||
'natural'
|
||||
];
|
||||
if (__indexOf.call(supported_fields, type) >= 0) {
|
||||
return templateUrl += type + '.html';
|
||||
templateUrl += type + '.html';
|
||||
}
|
||||
var template = $templateCache.get(templateUrl);
|
||||
return template;
|
||||
};
|
||||
|
||||
var linker = function(scope, element) {
|
||||
@ -1214,22 +1280,23 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root
|
||||
defaultDate: 0,
|
||||
};
|
||||
}
|
||||
//DAVID: TODO: Make natural language processing work
|
||||
//Set only if we have a natural lang processing field
|
||||
else if(scope.field.fieldType === 'natural'){
|
||||
scope.field.fieldMatchValue = '';
|
||||
// else if(scope.field.fieldType === 'natural'){
|
||||
// scope.field.fieldMatchValue = '';
|
||||
|
||||
//Fires when field is changed
|
||||
scope.$watch('scope.field', function(newField, oldField) {
|
||||
// //Fires when field is changed
|
||||
// scope.$watch('scope.field', function(newField, oldField) {
|
||||
|
||||
});
|
||||
}
|
||||
// });
|
||||
// }
|
||||
|
||||
// GET template content from path
|
||||
var templateUrl = getTemplateUrl(scope.field);
|
||||
$http.get(templateUrl).success(function(data) {
|
||||
element.html(data);
|
||||
var template = getTemplateUrl(scope.field);
|
||||
// $http.get(templateUrl).success(function(data) {
|
||||
element.html(template);
|
||||
$compile(element.contents())(scope);
|
||||
});
|
||||
// });
|
||||
};
|
||||
|
||||
return {
|
||||
@ -1249,6 +1316,8 @@ angular.module('forms').directive('onFinishRender', function ($rootScope, $timeo
|
||||
restrict: 'A',
|
||||
link: function (scope, element, attrs) {
|
||||
|
||||
// $rootScope.$broadcast(' Started');
|
||||
|
||||
//Don't do anything if we don't have a ng-repeat on the current element
|
||||
if(!element.attr('ng-repeat')){
|
||||
return;
|
||||
@ -1256,182 +1325,31 @@ angular.module('forms').directive('onFinishRender', function ($rootScope, $timeo
|
||||
|
||||
var broadcastMessage = attrs.onFinishRender || 'ngRepeat';
|
||||
|
||||
if(!scope.$last) {
|
||||
$timeout(function () {
|
||||
if(scope.$first) {
|
||||
scope.$evalAsync(function () {
|
||||
// console.log(broadcastMessage+' Started');
|
||||
// console.log(Date.now());
|
||||
$rootScope.$broadcast(broadcastMessage+' Started');
|
||||
});
|
||||
}else if(scope.$last) {
|
||||
$timeout(function () {
|
||||
element.ready(function () {
|
||||
scope.$evalAsync(function () {
|
||||
// element.ready(function () {
|
||||
// console.log(broadcastMessage+'Finished');
|
||||
// console.log(Date.now());
|
||||
$rootScope.$broadcast(broadcastMessage+' Finished');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('forms').directive('submissionsFormDirective', ['$rootScope', '$http', 'Upload', '$timeout', 'timeCounter', 'Auth', 'FormFields',
|
||||
function ($rootScope, $http, Upload, $timeout, timeCounter, Auth, FormFields) {
|
||||
return {
|
||||
templateUrl: './modules/forms/views/directiveViews/form/submissions-form.client.view.html',
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
myform:'=',
|
||||
user:'='
|
||||
},
|
||||
controller: function($scope){
|
||||
$scope.table = {
|
||||
masterChecker: false,
|
||||
rows: []
|
||||
};
|
||||
|
||||
/*
|
||||
** Table Functions
|
||||
*/
|
||||
$scope.isAtLeastOneChecked = function(){
|
||||
// console.log('isAtLeastOneChecked');
|
||||
for(var i=0; i<$scope.table.rows.length; i++){
|
||||
if($scope.table.rows[i].selected) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
$scope.toggleAllCheckers = function(){
|
||||
// console.log('toggleAllCheckers');
|
||||
for(var i=0; i<$scope.table.rows.length; i++){
|
||||
$scope.table.rows[i].selected = $scope.table.masterChecker;
|
||||
}
|
||||
};
|
||||
$scope.toggleObjSelection = function($event, description) {
|
||||
$event.stopPropagation();
|
||||
};
|
||||
$scope.rowClicked = function(row_index) {
|
||||
$scope.table.rows[row_index].selected = !$scope.table.rows[row_index].selected;
|
||||
};
|
||||
|
||||
/*
|
||||
* Form Submission Methods
|
||||
*/
|
||||
//Delete selected submissions of Form
|
||||
$scope.deleteSelectedSubmissions = function(){
|
||||
// console.log('deleteSelectedSubmissions');
|
||||
var delete_ids = _.chain($scope.table.rows).filter(function(row){
|
||||
return !!row.selected;
|
||||
}).pluck('_id').value();
|
||||
|
||||
$http({ url: '/forms/'+$scope.myform._id+'/submissions',
|
||||
method: 'DELETE',
|
||||
data: {deleted_submissions: delete_ids},
|
||||
headers: {'Content-Type': 'application/json;charset=utf-8'}
|
||||
}).success(function(data, status, headers){
|
||||
//Remove deleted ids from table
|
||||
var tmpArray = [];
|
||||
for(var i=0; i<$scope.table.rows.length; i++){
|
||||
if(!$scope.table.rows[i].selected){
|
||||
tmpArray.push($scope.table.rows[i]);
|
||||
}
|
||||
}
|
||||
console.log(tmpArray);
|
||||
$scope.table.rows = tmpArray;
|
||||
})
|
||||
.error(function(err){
|
||||
console.log('Could not delete form submissions.\nError: ');
|
||||
console.log(err);
|
||||
console.error = err;
|
||||
});
|
||||
};
|
||||
|
||||
//Export selected submissions of Form
|
||||
$scope.exportSubmissions = function(type){
|
||||
var fileMIMETypeMap = {
|
||||
'xls': 'vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'json': 'json',
|
||||
'csv': 'csv',
|
||||
};
|
||||
|
||||
var blob = new Blob([document.getElementById('table-submission-data').innerHTM], {
|
||||
type: 'application/'+fileMIMETypeMap[type]+';charset=utf-8'
|
||||
});
|
||||
saveAs(blob, $scope.myform.title+'_sumbissions_export_'+Date.now()+'.'+type);
|
||||
};
|
||||
|
||||
|
||||
//Fetch and display submissions of Form
|
||||
$scope.showSubmissions = function(){
|
||||
$http.get('/forms/'+$scope.myform._id+'/submissions')
|
||||
.success(function(data, status, headers){
|
||||
|
||||
var _data = [],
|
||||
_currentSubmission,
|
||||
_tmpSubFormFields,
|
||||
defaultFormFields = JSON.parse(JSON.stringify($scope.myform.form_fields));
|
||||
|
||||
|
||||
//Iterate through form's submissions
|
||||
for(var i=0; i<data.length; i++){
|
||||
// _tmpSubFormFields = defaultFormFields;
|
||||
|
||||
_tmpSubFormFields = _.merge(defaultFormFields, data[i].form_fields);
|
||||
_data[i].form_fields = _tmpSubFormFields;
|
||||
|
||||
// currentSubmission = data[i];
|
||||
|
||||
// for(var x=0; x<defaultFormFields.length; x++){
|
||||
|
||||
// var currField__id = defaultFormFields[x]._id,
|
||||
// currField;
|
||||
|
||||
// _.find(currentSubmission.form_fields, function(fieldItem, fieldIdx){
|
||||
// if(fieldItem._id === currField__id){
|
||||
// currField = fieldItem;
|
||||
// return true;
|
||||
// }
|
||||
// });
|
||||
|
||||
// if( (typeof currField) !== 'undefined'){
|
||||
// _tmpSubFormFields[x].fieldValue = currField.fieldValue;
|
||||
// _tmpSubFormFields[x].$$hashKey = currField.$$hashKey;
|
||||
// }else {
|
||||
// _tmpSubFormFields[x].fieldValue = '';
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// _data[i] = currentSubmission;
|
||||
// _data[i].form_fields = _tmpSubFormFields;
|
||||
}
|
||||
|
||||
// console.log(JSON.stringify(_data));
|
||||
$scope.submissions = _data;
|
||||
$scope.table.rows = _data;
|
||||
if(!$scope.$$phase && !$scope.$digest){
|
||||
$scope.$apply();
|
||||
}
|
||||
// console.log('form submissions successfully fetched');
|
||||
// console.log( JSON.parse(JSON.stringify($scope.submissions)) ) ;
|
||||
// console.log( JSON.parse(JSON.stringify($scope.myform.form_fields)) );
|
||||
})
|
||||
.error(function(err){
|
||||
console.error('Could not fetch form submissions.\nError: '+err);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCounter', 'Auth', '$filter', '$rootScope',
|
||||
function ($http, $timeout, timeCounter, Auth, $filter, $rootScope) {
|
||||
angular.module('forms').directive('formDirective', ['$http', '$timeout', 'TimeCounter', 'Auth', '$filter', '$rootScope',
|
||||
function ($http, $timeout, TimeCounter, Auth, $filter, $rootScope) {
|
||||
return {
|
||||
templateUrl: './modules/forms/views/directiveViews/form/submit-form.client.view.html',
|
||||
templateUrl: 'modules/forms/views/directiveViews/form/submit-form.client.view.html',
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
form:'='
|
||||
@ -1440,12 +1358,12 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCo
|
||||
angular.element(document).ready(function() {
|
||||
|
||||
$scope.selected = null;
|
||||
timeCounter.startClock()
|
||||
TimeCounter.startClock()
|
||||
|
||||
$rootScope.setActiveField = function (field_id) {
|
||||
console.log('form field clicked: '+field_id);
|
||||
// console.log('form field clicked: '+field_id);
|
||||
$scope.selected = field_id;
|
||||
console.log($scope.selected);
|
||||
// console.log($scope.selected);
|
||||
};
|
||||
$scope.hideOverlay = function (){
|
||||
$scope.selected = null;
|
||||
@ -1453,7 +1371,7 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCo
|
||||
};
|
||||
|
||||
$scope.submit = function(){
|
||||
var _timeElapsed = timeCounter.stopClock();
|
||||
var _timeElapsed = TimeCounter.stopClock();
|
||||
$scope.form.timeElapsed = _timeElapsed;
|
||||
|
||||
// console.log('percentageComplete: '+$filter('formValidity')($scope.form)/$scope.form.visible_form_fields.length*100+'%');
|
||||
@ -1481,8 +1399,8 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCo
|
||||
};
|
||||
|
||||
$scope.reloadForm = function(){
|
||||
timeCounter.stopClock();
|
||||
timeCounter.startClock();
|
||||
TimeCounter.stopClock();
|
||||
TimeCounter.startClock();
|
||||
$scope.form.submitted = false;
|
||||
$scope.form.form_fields = _.chain($scope.form.form_fields).map(function(field){
|
||||
field.fieldValue = '';
|
||||
@ -1497,40 +1415,6 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'timeCo
|
||||
]);
|
||||
'use strict';
|
||||
|
||||
angular.module('forms').directive('tableDirective', ['$http', '$timeout', 'Auth',
|
||||
function ($http, $timeout, Auth) {
|
||||
return {
|
||||
templateUrl: './modules/forms/views/directiveViews/table/table.html',
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
rows:'=',
|
||||
extras:'=',
|
||||
},
|
||||
controller: function($scope){
|
||||
|
||||
$scope.toggleChecker = function(checked) {
|
||||
var rows = $scope.gridOptions.$gridScope.renderedRows,
|
||||
allChecked = true;
|
||||
|
||||
for (var r = 0; r < rows.length; r++) {
|
||||
if (rows[r].entity.checker !== true) {
|
||||
allChecked = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.gridOptions.$gridScope.checker = allChecked;
|
||||
};
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
]);
|
||||
'use strict';
|
||||
|
||||
//Forms service used for communicating with the forms REST endpoints
|
||||
angular.module('forms').service('CurrentForm',
|
||||
function(){
|
||||
@ -1549,9 +1433,10 @@ angular.module('forms').service('CurrentForm',
|
||||
);
|
||||
'use strict';
|
||||
|
||||
//TODO: DAVID: URGENT: Make this a $resource that fetches valid field types from server
|
||||
angular.module('forms').service('FormFields', [
|
||||
function() {
|
||||
this.fields = [
|
||||
this.types = [
|
||||
{
|
||||
name : 'textfield',
|
||||
value : 'Short Text'
|
||||
@ -1694,7 +1579,7 @@ angular.module('forms').factory('Submissions', ['$resource',
|
||||
]);
|
||||
'use strict';
|
||||
|
||||
angular.module('forms').service('timeCounter', [
|
||||
angular.module('forms').service('TimeCounter', [
|
||||
function(){
|
||||
var _startTime, _endTime, that=this;
|
||||
|
||||
|
2
public/dist/application.min.css
vendored
2
public/dist/application.min.css
vendored
File diff suppressed because one or more lines are too long
4
public/dist/application.min.js
vendored
4
public/dist/application.min.js
vendored
File diff suppressed because one or more lines are too long
@ -8,8 +8,7 @@
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a href="/#!/" class="navbar-brand">
|
||||
<!-- <i class="fa fa-5 fa-heartbeat"></i> -->
|
||||
Med<span>Forms</span>
|
||||
Node<span>Forms</span>
|
||||
</a>
|
||||
</div>
|
||||
<nav class="collapse navbar-collapse" collapse="!isCollapsed" role="navigation">
|
||||
|
@ -10,25 +10,26 @@
|
||||
<i class="fa fa-archive fa-3x"></i>
|
||||
</h3>
|
||||
<h2 class="col-xs-12" style="margin-top:0px">
|
||||
Med<span style="color: #FA787E">Forms</span>
|
||||
Node<span style="color: #FA787E">Forms</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="col-xs-12 row" style="margin-top:0px">
|
||||
<h1 class="lead col-md-10 col-md-offset-1 hidden-xs hidden-sm" style="font-size:3.8em;">
|
||||
Craft beautiful forms in seconds.
|
||||
</h1>
|
||||
<<<<<<< HEAD
|
||||
<h2 class="lead col-xs-12 text-center hidden-md hidden-lg" style="font-size:2.8em;">
|
||||
|
||||
<h2 class="lead col-sm-12 text-center hidden-md hidden-lg" style="font-size:2.8em;">
|
||||
Craft beautiful forms.
|
||||
</h2>
|
||||
<p class="lead col-xs-10 col-xs-offset-1 col-sm-8 col-sm-offset-2" style="font-size:1.5em; color:rgba(255,255,255,.75)">
|
||||
<i>Medforms is an opensource <b>form builder</b> that can create stunning forms from PDFs or from scratch</i>
|
||||
</p>
|
||||
=======
|
||||
<p class="lead col-xs-12" style="font-size:1.5em; color:rgba(255,255,255,.75)">
|
||||
|
||||
<p class="lead hidden-xs hidden-sm col-md-10 col-md-offset-1 col-lg-8 col-lg-offset-2" style="font-size:1.5em; color:rgba(255,255,255,.75)">
|
||||
<i>NodeForms is an opensource <b>form builder</b> that can create stunning forms from PDFs or from scratch</i>
|
||||
</p>
|
||||
|
||||
<p class="lead col-xs-12 hidden-md hidden-lg" style="font-size:1.5em; color:rgba(255,255,255,.75)">
|
||||
<i>NodeForms is an opensource, self-hosted <b>form builder</b> that can create stunning forms</i>
|
||||
</h1>
|
||||
>>>>>>> master
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12" style="margin-top:7%;">
|
||||
|
@ -4,7 +4,7 @@
|
||||
border-width:3px;
|
||||
}
|
||||
|
||||
section.content p {
|
||||
section.content p.breakwords {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,8 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
|
||||
require: ['^form'],
|
||||
restrict: 'AE',
|
||||
link: function($scope, $element, $attrs, $ctrls) {
|
||||
|
||||
//DAVID: TODO: Do we really need to check if our directive element is ready everytime
|
||||
angular.element(document).ready(function() {
|
||||
|
||||
var $formCtrl = $ctrls[0],
|
||||
@ -32,7 +34,7 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
|
||||
return false;
|
||||
};
|
||||
|
||||
var debounceSave = function () {
|
||||
this.debounceSave = function () {
|
||||
$rootScope.saveInProgress = true;
|
||||
$rootScope[$attrs.autoSaveCallback](true,
|
||||
function(err){
|
||||
@ -49,7 +51,7 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
|
||||
//Update/save Form if any Form fields are Dirty and Touched
|
||||
$scope.$watch(function(newValue, oldValue) {
|
||||
if($scope.anyDirtyAndTouched($scope.editForm) && !$rootScope.saveInProgress){
|
||||
debounceSave();
|
||||
this.debounceSave();
|
||||
}
|
||||
});
|
||||
|
||||
@ -79,7 +81,7 @@ angular.module('forms').directive('autoSaveForm', ['$rootScope', '$timeout', fun
|
||||
|
||||
savePromise = $timeout(function() {
|
||||
console.log('Saving Form');
|
||||
debounceSave();
|
||||
this.debounceSave();
|
||||
});
|
||||
}
|
||||
//If we are finished rendering then form saving should be finished
|
||||
|
@ -3,7 +3,7 @@
|
||||
angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$http', '$timeout', 'TimeCounter', 'Auth', 'FormFields',
|
||||
function ($rootScope, $q, $http, $timeout, TimeCounter, Auth, FormFields) {
|
||||
return {
|
||||
templateUrl: './modules/forms/views/directiveViews/form/edit-form.client.view.html',
|
||||
templateUrl: 'modules/forms/views/directiveViews/form/edit-form.client.view.html',
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
myform:'=',
|
||||
@ -22,6 +22,8 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht
|
||||
return type;
|
||||
});
|
||||
|
||||
$scope.lastButtonID = 0;
|
||||
|
||||
// Accordion settings
|
||||
$scope.accordion = {};
|
||||
$scope.accordion.oneAtATime = true;
|
||||
@ -93,10 +95,8 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht
|
||||
var fieldTitle;
|
||||
|
||||
for(var i = 0; i < $scope.addField.types.length; i++){
|
||||
// console.log($scope.addField.types[i].name === fieldType);
|
||||
if($scope.addField.types[i].name === fieldType){
|
||||
$scope.addField.types[i].lastAddedID++;
|
||||
// console.log($scope.addField.types[i].lastAddedID);
|
||||
fieldTitle = $scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;
|
||||
break;
|
||||
}
|
||||
@ -109,8 +109,9 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht
|
||||
disabled: false,
|
||||
deletePreserved: false
|
||||
};
|
||||
console.log('\n\n---------\nAdded field CLIENT');
|
||||
console.log(newField);
|
||||
// console.log('\n\n---------\nAdded field CLIENT');
|
||||
// console.log(newField);
|
||||
newField._id = _.uniqueId();
|
||||
|
||||
// put newField into fields array
|
||||
if(modifyForm){
|
||||
@ -119,25 +120,15 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht
|
||||
return newField;
|
||||
};
|
||||
|
||||
// deletes particular field on button click
|
||||
$scope.deleteField = function (hashKey){
|
||||
// console.log($scope.myform.form_fields);
|
||||
for(var i = 0; i < $scope.myform.form_fields.length; i++){
|
||||
// console.log($scope.myform.form_fields[i].$$hashKey === hashKey);
|
||||
if($scope.myform.form_fields[i].$$hashKey === hashKey){
|
||||
$scope.myform.form_fields.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Delete particular field on button click
|
||||
$scope.deleteField = function (field_index){
|
||||
$scope.myform.form_fields.splice(field_index, 1);
|
||||
};
|
||||
$scope.duplicateField = function (field_index){
|
||||
console.log('field_index: '+field_index);
|
||||
var field = $scope.addNewField(false, $scope.myform.form_fields[field_index].fieldType);
|
||||
field.title = $scope.myform.form_fields[field_index].title;
|
||||
console.log($scope.myform.form_fields[field_index]);
|
||||
var currField = $scope.myform.form_fields[field_index];
|
||||
|
||||
//Insert field at selected index
|
||||
$scope.myform.form_fields.splice(field_index+1, 0, field);
|
||||
$scope.myform.form_fields.splice(field_index+1, 0, currField);
|
||||
};
|
||||
|
||||
|
||||
@ -146,24 +137,27 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht
|
||||
*/
|
||||
|
||||
// add new Button to the startPage/EndPage
|
||||
$scope.addButton = function (newButtons){
|
||||
$scope.addButton = function(){
|
||||
|
||||
var newButton = {};
|
||||
newButton.bgColor = '#ddd';
|
||||
newButton.color = '#ffffff';
|
||||
newButton.text = 'Button';
|
||||
newButton._id = _.uniqueId();
|
||||
|
||||
$scope.myform.startPage.buttons.push(newButton);
|
||||
};
|
||||
|
||||
// delete particular Button
|
||||
$scope.deleteButton = function(button){
|
||||
var hashKey = _.chain(button.$$hashKey).words().last().parseInt().value();
|
||||
|
||||
// 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();
|
||||
// var currHashKey = _.chain($scope.myform.startPage.buttons[i].$$hashKey).words().last().parseInt().value();
|
||||
currID = $scope.myform.startPage.buttons[i]._id;
|
||||
console.log(currID);
|
||||
|
||||
if(currHashKey === hashKey){
|
||||
if(currID === button._id){
|
||||
$scope.myform.startPage.buttons.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
@ -171,7 +165,6 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Field Option Methods
|
||||
*/
|
||||
@ -182,8 +175,9 @@ angular.module('forms').directive('editFormDirective', ['$rootScope', '$q', '$ht
|
||||
|
||||
var lastOptionID = 0;
|
||||
|
||||
if(field.fieldOptions[field.fieldOptions.length-1])
|
||||
if(field.fieldOptions[field.fieldOptions.length-1]){
|
||||
lastOptionID = field.fieldOptions[field.fieldOptions.length-1].option_id;
|
||||
}
|
||||
|
||||
// new option's id
|
||||
var option_id = lastOptionID + 1;
|
||||
|
@ -3,7 +3,7 @@
|
||||
angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', '$http', 'Upload', '$timeout', 'TimeCounter', 'Auth', 'FormFields',
|
||||
function ($rootScope, $http, Upload, $timeout, TimeCounter, Auth, FormFields) {
|
||||
return {
|
||||
templateUrl: './modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html',
|
||||
templateUrl: 'modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html',
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
myform:'=',
|
||||
@ -15,18 +15,17 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
||||
rows: []
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Table Functions
|
||||
*/
|
||||
$scope.isAtLeastOneChecked = function(){
|
||||
// console.log('isAtLeastOneChecked');
|
||||
for(var i=0; i<$scope.table.rows.length; i++){
|
||||
if($scope.table.rows[i].selected) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
$scope.toggleAllCheckers = function(){
|
||||
// console.log('toggleAllCheckers');
|
||||
for(var i=0; i<$scope.table.rows.length; i++){
|
||||
$scope.table.rows[i].selected = $scope.table.masterChecker;
|
||||
}
|
||||
@ -41,9 +40,38 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
||||
/*
|
||||
* Form Submission Methods
|
||||
*/
|
||||
|
||||
//Fetch and display submissions of Form
|
||||
$scope.initFormSubmissions = function(){
|
||||
$http.get('/forms/'+$scope.myform._id+'/submissions')
|
||||
.success(function(data, status, headers){
|
||||
|
||||
console.log(data[0].form_fields);
|
||||
|
||||
var _tmpSubFormFields,
|
||||
defaultFormFields = _.cloneDeep($scope.myform.form_fields);
|
||||
|
||||
|
||||
//Iterate through form's submissions
|
||||
for(var i=0; i<data.length; i++){
|
||||
_tmpSubFormFields = _.merge(defaultFormFields, data[i].form_fields);
|
||||
data[i].form_fields = _tmpSubFormFields;
|
||||
data[i].selected = false;
|
||||
}
|
||||
|
||||
$scope.table.rows = data;
|
||||
|
||||
// console.log('form submissions successfully fetched');
|
||||
// console.log( JSON.parse(JSON.stringify($scope.submissions)) ) ;
|
||||
// console.log( JSON.parse(JSON.stringify($scope.myform.form_fields)) );
|
||||
})
|
||||
.error(function(err){
|
||||
console.error('Could not fetch form submissions.\nError: '+err);
|
||||
});
|
||||
};
|
||||
//Delete selected submissions of Form
|
||||
$scope.deleteSelectedSubmissions = function(){
|
||||
// console.log('deleteSelectedSubmissions');
|
||||
|
||||
var delete_ids = _.chain($scope.table.rows).filter(function(row){
|
||||
return !!row.selected;
|
||||
}).pluck('_id').value();
|
||||
@ -60,7 +88,6 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
||||
tmpArray.push($scope.table.rows[i]);
|
||||
}
|
||||
}
|
||||
console.log(tmpArray);
|
||||
$scope.table.rows = tmpArray;
|
||||
})
|
||||
.error(function(err){
|
||||
@ -84,69 +111,6 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
|
||||
saveAs(blob, $scope.myform.title+'_sumbissions_export_'+Date.now()+'.'+type);
|
||||
};
|
||||
|
||||
|
||||
//Fetch and display submissions of Form
|
||||
$scope.showSubmissions = function(){
|
||||
$http.get('/forms/'+$scope.myform._id+'/submissions')
|
||||
.success(function(data, status, headers){
|
||||
|
||||
var _data = [],
|
||||
_currentSubmission,
|
||||
_tmpSubFormFields,
|
||||
defaultFormFields = JSON.parse(JSON.stringify($scope.myform.form_fields));
|
||||
|
||||
|
||||
//Iterate through form's submissions
|
||||
for(var i=0; i<data.length; i++){
|
||||
// _tmpSubFormFields = defaultFormFields;
|
||||
|
||||
_tmpSubFormFields = _.merge(defaultFormFields, data[i].form_fields);
|
||||
_data[i].form_fields = _tmpSubFormFields;
|
||||
|
||||
// currentSubmission = data[i];
|
||||
|
||||
// for(var x=0; x<defaultFormFields.length; x++){
|
||||
|
||||
// var currField__id = defaultFormFields[x]._id,
|
||||
// currField;
|
||||
|
||||
// _.find(currentSubmission.form_fields, function(fieldItem, fieldIdx){
|
||||
// if(fieldItem._id === currField__id){
|
||||
// currField = fieldItem;
|
||||
// return true;
|
||||
// }
|
||||
// });
|
||||
|
||||
// if( (typeof currField) !== 'undefined'){
|
||||
// _tmpSubFormFields[x].fieldValue = currField.fieldValue;
|
||||
// _tmpSubFormFields[x].$$hashKey = currField.$$hashKey;
|
||||
// }else {
|
||||
// _tmpSubFormFields[x].fieldValue = '';
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// _data[i] = currentSubmission;
|
||||
// _data[i].form_fields = _tmpSubFormFields;
|
||||
}
|
||||
|
||||
// console.log(JSON.stringify(_data));
|
||||
$scope.submissions = _data;
|
||||
$scope.table.rows = _data;
|
||||
if(!$scope.$$phase && !$scope.$digest){
|
||||
$scope.$apply();
|
||||
}
|
||||
// console.log('form submissions successfully fetched');
|
||||
// console.log( JSON.parse(JSON.stringify($scope.submissions)) ) ;
|
||||
// console.log( JSON.parse(JSON.stringify($scope.myform.form_fields)) );
|
||||
})
|
||||
.error(function(err){
|
||||
console.error('Could not fetch form submissions.\nError: '+err);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -8,14 +8,14 @@ var __indexOf = [].indexOf || function(item) {
|
||||
return -1;
|
||||
};
|
||||
|
||||
angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$rootScope',
|
||||
function($http, $compile, $rootScope) {
|
||||
angular.module('forms').directive('fieldDirective', ['$templateCache', '$http', '$compile', '$rootScope',
|
||||
function($templateCache, $http, $compile, $rootScope) {
|
||||
|
||||
|
||||
var getTemplateUrl = function(field) {
|
||||
|
||||
var type = field.fieldType;
|
||||
var templateUrl = './modules/forms/views/directiveViews/field/';
|
||||
var templateUrl = 'modules/forms/views/directiveViews/field/';
|
||||
var supported_fields = [
|
||||
'textfield',
|
||||
'email',
|
||||
@ -34,8 +34,10 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root
|
||||
'natural'
|
||||
];
|
||||
if (__indexOf.call(supported_fields, type) >= 0) {
|
||||
return templateUrl += type + '.html';
|
||||
templateUrl += type + '.html';
|
||||
}
|
||||
var template = $templateCache.get(templateUrl);
|
||||
return template;
|
||||
};
|
||||
|
||||
var linker = function(scope, element) {
|
||||
@ -51,22 +53,23 @@ angular.module('forms').directive('fieldDirective', ['$http', '$compile', '$root
|
||||
defaultDate: 0,
|
||||
};
|
||||
}
|
||||
//DAVID: TODO: Make natural language processing work
|
||||
//Set only if we have a natural lang processing field
|
||||
else if(scope.field.fieldType === 'natural'){
|
||||
scope.field.fieldMatchValue = '';
|
||||
// else if(scope.field.fieldType === 'natural'){
|
||||
// scope.field.fieldMatchValue = '';
|
||||
|
||||
//Fires when field is changed
|
||||
scope.$watch('scope.field', function(newField, oldField) {
|
||||
// //Fires when field is changed
|
||||
// scope.$watch('scope.field', function(newField, oldField) {
|
||||
|
||||
});
|
||||
}
|
||||
// });
|
||||
// }
|
||||
|
||||
// GET template content from path
|
||||
var templateUrl = getTemplateUrl(scope.field);
|
||||
$http.get(templateUrl).success(function(data) {
|
||||
element.html(data);
|
||||
var template = getTemplateUrl(scope.field);
|
||||
// $http.get(templateUrl).success(function(data) {
|
||||
element.html(template);
|
||||
$compile(element.contents())(scope);
|
||||
});
|
||||
// });
|
||||
};
|
||||
|
||||
return {
|
||||
|
@ -1,45 +1,45 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('forms').directive('formDirective', ['$http', '$timeout', 'TimeCounter', 'Auth', '$filter', '$rootScope',
|
||||
angular.module('forms').directive('submitFormDirective', ['$http', '$timeout', 'TimeCounter', 'Auth', '$filter', '$rootScope',
|
||||
function ($http, $timeout, TimeCounter, Auth, $filter, $rootScope) {
|
||||
return {
|
||||
templateUrl: './modules/forms/views/directiveViews/form/submit-form.client.view.html',
|
||||
templateUrl: 'modules/forms/views/directiveViews/form/submit-form.client.view.html',
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
form:'='
|
||||
myform:'='
|
||||
},
|
||||
controller: function($scope){
|
||||
angular.element(document).ready(function() {
|
||||
|
||||
$scope.error = '';
|
||||
$scope.selected = null;
|
||||
$scope.submitted = false;
|
||||
|
||||
TimeCounter.startClock()
|
||||
|
||||
$rootScope.setActiveField = function (field_id) {
|
||||
console.log('form field clicked: '+field_id);
|
||||
$scope.selected = field_id;
|
||||
console.log($scope.selected);
|
||||
};
|
||||
$scope.hideOverlay = function (){
|
||||
$scope.selected = null;
|
||||
console.log($scope.myForm);
|
||||
};
|
||||
|
||||
$scope.submit = function(){
|
||||
var _timeElapsed = TimeCounter.stopClock();
|
||||
$scope.form.timeElapsed = _timeElapsed;
|
||||
|
||||
// console.log('percentageComplete: '+$filter('formValidity')($scope.form)/$scope.form.visible_form_fields.length*100+'%');
|
||||
$scope.form.percentageComplete = $filter('formValidity')($scope.form)/$scope.form.visible_form_fields.length*100;
|
||||
console.log($scope.form.percentageComplete);
|
||||
// delete $scope.form.visible_form_fields;
|
||||
var form = _.cloneDeep($scope.myform);
|
||||
form.timeElapsed = _timeElapsed;
|
||||
|
||||
// console.log('percentageComplete: '+$filter('formValidity')($scope.myform)/$scope.myform.visible_form_fields.length*100+'%');
|
||||
form.percentageComplete = $filter('formValidity')($scope.myform)/$scope.myform.visible_form_fields.length*100;
|
||||
console.log(form.percentageComplete)
|
||||
delete form.visible_form_fields;
|
||||
|
||||
$scope.authentication = Auth;
|
||||
|
||||
$scope.submitPromise = $http.post('/forms/'+$scope.form._id,$scope.form)
|
||||
$scope.submitPromise = $http.post('/forms/'+$scope.myform._id, form)
|
||||
.success(function(data, status, headers){
|
||||
console.log('form submitted successfully');
|
||||
// alert('Form submitted..');
|
||||
$scope.form.submitted = true;
|
||||
$scope.myform.submitted = true;
|
||||
})
|
||||
.error(function(error){
|
||||
console.log(error);
|
||||
@ -48,15 +48,18 @@ angular.module('forms').directive('formDirective', ['$http', '$timeout', 'TimeCo
|
||||
};
|
||||
|
||||
|
||||
$scope.exitstartPage = function () {
|
||||
$scope.form.startPage.showStart = false;
|
||||
$scope.exitStartPage = function () {
|
||||
$scope.myform.startPage.showStart = false;
|
||||
};
|
||||
|
||||
$scope.reloadForm = function(){
|
||||
//Reset Timer
|
||||
TimeCounter.stopClock();
|
||||
TimeCounter.startClock();
|
||||
$scope.form.submitted = false;
|
||||
$scope.form.form_fields = _.chain($scope.form.form_fields).map(function(field){
|
||||
|
||||
//Reset Form
|
||||
$scope.myform.submitted = false;
|
||||
$scope.myform.form_fields = _.chain($scope.myform.form_fields).map(function(field){
|
||||
field.fieldValue = '';
|
||||
return field;
|
||||
}).value();
|
||||
|
@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
//TODO: DAVID: URGENT: Make this a $resource that fetches valid field types from server
|
||||
angular.module('forms').service('FormFields', [
|
||||
function() {
|
||||
this.types = [
|
||||
|
@ -1,126 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
(function() {
|
||||
// Forms Controller Spec
|
||||
describe('editForm Tests', function() {
|
||||
// Initialize global variables
|
||||
var el, scope, controller, $httpBackend;
|
||||
|
||||
var sampleUser = {
|
||||
firstName: 'Full',
|
||||
lastName: 'Name',
|
||||
email: 'test@test.com',
|
||||
username: 'test@test.com',
|
||||
password: 'password',
|
||||
provider: 'local',
|
||||
roles: ['user'],
|
||||
_id: 'ed873933b1f1dea0ce12fab9',
|
||||
};
|
||||
|
||||
var pdfObj = {
|
||||
fieldname:"file",
|
||||
originalname:"test.pdf",
|
||||
name:"1440112660375.pdf",
|
||||
encoding:"7bit",
|
||||
mimetype:"application/pdf",
|
||||
path:"uploads/tmp/test@test.com/1440112660375.pdf",
|
||||
extension:"pdf",
|
||||
size:56223,
|
||||
truncated:false,
|
||||
buffer:null
|
||||
};
|
||||
|
||||
var sampleForm = {
|
||||
title: 'Form Title',
|
||||
admin: 'ed873933b1f1dea0ce12fab9',
|
||||
language: 'english',
|
||||
form_fields: [
|
||||
{fieldType:'textfield', title:'First Name', fieldValue: '', required: true, disabled: false, deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'nascar', fieldValue: '', required: true, disabled: false, deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'hockey', fieldValue: '', required: true, disabled: false, deletePreserved: false}
|
||||
],
|
||||
pdf: {},
|
||||
pdfFieldMap: {},
|
||||
startPage: {
|
||||
showStart: false
|
||||
},
|
||||
hideFooter: false,
|
||||
isGenerated: false,
|
||||
isLive: false,
|
||||
autofillPDFs: false,
|
||||
_id: '525a8422f6d0f87f0e407a33',
|
||||
};
|
||||
|
||||
// The $resource service augments the response object with methods for updating and deleting the resource.
|
||||
// If we were to use the standard toEqual matcher, our tests would fail because the test values would not match
|
||||
// the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher.
|
||||
// When the toEqualData matcher compares two objects, it takes only object properties into
|
||||
// account and ignores methods.
|
||||
beforeEach(function() {
|
||||
jasmine.addMatchers({
|
||||
toEqualData: function(util, customEqualityTesters) {
|
||||
return {
|
||||
compare: function(actual, expected) {
|
||||
return {
|
||||
pass: angular.equals(actual, expected)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Load the main application module
|
||||
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||
beforeEach(module('stateMock'));
|
||||
beforeEach(module('module-templates'));
|
||||
|
||||
beforeEach(inject(function($compile, $controller, $rootScope, _$httpBackend_) {
|
||||
//Instantiate directive.
|
||||
var tmp_scope = $rootScope.$new();
|
||||
tmp_scope.myform = sampleForm;
|
||||
|
||||
//gotacha: Controller and link functions will execute.
|
||||
el = angular.element('<edit-form-directive myform="myform"></edit-form-directive>');
|
||||
$compile(el)(tmp_scope);
|
||||
$rootScope.$digest();
|
||||
|
||||
// Point global variables to injected services
|
||||
$httpBackend = _$httpBackend_;
|
||||
|
||||
$httpBackend.whenGET(/.+\.html$/).respond('');
|
||||
$httpBackend.whenGET('/users/me/').respond('');
|
||||
|
||||
//Grab controller instance
|
||||
controller = el.controller();
|
||||
|
||||
//Grab scope. Depends on type of scope.
|
||||
//See angular.element documentation.
|
||||
scope = el.isolateScope() || el.scope();
|
||||
|
||||
}));
|
||||
|
||||
it('$scope.addNewField() should ADD a new field to $scope.myform.form_fields', function() {
|
||||
scope.addNewField(true, 'textfield');
|
||||
|
||||
var sampleFormField = {
|
||||
fieldType:'checkbox',
|
||||
title:'hockey',
|
||||
fieldValue: '',
|
||||
required: true,
|
||||
disabled: false,
|
||||
deletePreserved: false
|
||||
};
|
||||
|
||||
expect(scope.myform.form_fields.length).toEqual(sampleForm.form_fields.length+1);
|
||||
expect(_.last(scope.myform.form_fields)).toEqualData(sampleFormField);
|
||||
});
|
||||
|
||||
it('$scope.deleteField() should DELETE a field to $scope.myform.form_fields', function() {
|
||||
scope.deleteField(scope.myform.form_fields[0].$$hashKey);
|
||||
|
||||
expect(scope.myform.form_fields.length).toEqual(sampleForm.form_fields.length-1);
|
||||
expect(_.first(scope.myform.form_fields)).toEqualData(sampleForm.form_fields[1]);
|
||||
});
|
||||
});
|
||||
}());
|
@ -184,13 +184,13 @@
|
||||
};
|
||||
}));
|
||||
|
||||
it('AdminFormController should fetch current Form when instantiated', inject(function() {
|
||||
it('AdminFormController should fetch current Form when instantiated', function() {
|
||||
// Run controller functionality
|
||||
var controller = createAdminFormController();
|
||||
|
||||
// Test scope value
|
||||
expect(scope.myform).toEqualData(sampleForm);
|
||||
}));
|
||||
});
|
||||
|
||||
it('$scope.findOne() should fetch current Form', inject(function(Forms) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
(function() {
|
||||
// Forms Controller Spec
|
||||
describe('configureForm Tests', function() {
|
||||
describe('ConfigureForm Directive-Controller Tests', function() {
|
||||
// Initialize global variables
|
||||
var el, scope, controller, $httpBackend;
|
||||
|
||||
@ -99,8 +99,6 @@
|
||||
//See angular.element documentation.
|
||||
scope = el.isolateScope() || el.scope();
|
||||
|
||||
// spyOn(scope, 'update');
|
||||
// spyOn(scope, 'resetForm');
|
||||
}));
|
||||
|
||||
it('$scope.uploadPDF() should upload a pdf file', function() {
|
@ -0,0 +1,200 @@
|
||||
'use strict';
|
||||
|
||||
(function() {
|
||||
// Forms Controller Spec
|
||||
describe('EditSubmissions Directive-Controller Tests', function() {
|
||||
// Initialize global variables
|
||||
var el, scope, controller, $httpBackend;
|
||||
|
||||
var sampleUser = {
|
||||
firstName: 'Full',
|
||||
lastName: 'Name',
|
||||
email: 'test@test.com',
|
||||
username: 'test@test.com',
|
||||
password: 'password',
|
||||
provider: 'local',
|
||||
roles: ['user'],
|
||||
_id: 'ed873933b1f1dea0ce12fab9',
|
||||
};
|
||||
|
||||
var pdfObj = {
|
||||
fieldname:"file",
|
||||
originalname:"test.pdf",
|
||||
name:"1440112660375.pdf",
|
||||
encoding:"7bit",
|
||||
mimetype:"application/pdf",
|
||||
path:"uploads/tmp/test@test.com/1440112660375.pdf",
|
||||
extension:"pdf",
|
||||
size:56223,
|
||||
truncated:false,
|
||||
buffer:null
|
||||
};
|
||||
|
||||
var sampleForm = {
|
||||
title: 'Form Title',
|
||||
admin: 'ed873933b1f1dea0ce12fab9',
|
||||
language: 'english',
|
||||
form_fields: [
|
||||
{fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false}
|
||||
],
|
||||
pdf: {},
|
||||
pdfFieldMap: {},
|
||||
startPage: {
|
||||
showStart: false
|
||||
},
|
||||
hideFooter: false,
|
||||
isGenerated: false,
|
||||
isLive: false,
|
||||
autofillPDFs: false,
|
||||
_id: '525a8422f6d0f87f0e407a33',
|
||||
};
|
||||
|
||||
var sampleSubmission = {
|
||||
form_fields: [
|
||||
{fieldType:'textfield', title:'First Name', fieldValue: 'John Smith', deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'nascar', fieldValue: 1, deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'hockey', fieldValue: 0, deletePreserved: false}
|
||||
],
|
||||
admin: sampleUser,
|
||||
form: sampleForm,
|
||||
timeElapsed: 17.55
|
||||
};
|
||||
|
||||
var sampleSubmissions = [{
|
||||
form_fields: [
|
||||
{fieldType:'textfield', title:'First Name', fieldValue: 'The Terminator', deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'nascar', fieldValue: 0, deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'hockey', fieldValue: 1, deletePreserved: false}
|
||||
],
|
||||
admin: sampleUser,
|
||||
form: sampleForm,
|
||||
timeElapsed: 10.33
|
||||
},
|
||||
{
|
||||
form_fields: [
|
||||
{fieldType:'textfield', title:'First Name', fieldValue: 'John Smith', deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'nascar', fieldValue: 1, deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'hockey', fieldValue: 0, deletePreserved: false}
|
||||
],
|
||||
admin: sampleUser,
|
||||
form: sampleForm,
|
||||
timeElapsed: 2.33
|
||||
},
|
||||
{
|
||||
form_fields: [
|
||||
{fieldType:'textfield', title:'First Name', fieldValue: 'Jane Doe', deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'nascar', fieldValue: 1, deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'hockey', fieldValue: 1, deletePreserved: false}
|
||||
],
|
||||
admin: sampleUser,
|
||||
form: sampleForm,
|
||||
timeElapsed: 11.11
|
||||
}];
|
||||
|
||||
// The $resource service augments the response object with methods for updating and deleting the resource.
|
||||
// If we were to use the standard toEqual matcher, our tests would fail because the test values would not match
|
||||
// the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher.
|
||||
// When the toEqualData matcher compares two objects, it takes only object properties into
|
||||
// account and ignores methods.
|
||||
beforeEach(function() {
|
||||
jasmine.addMatchers({
|
||||
toEqualData: function(util, customEqualityTesters) {
|
||||
return {
|
||||
compare: function(actual, expected) {
|
||||
return {
|
||||
pass: angular.equals(actual, expected)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Load the main application module
|
||||
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||
beforeEach(module('stateMock'));
|
||||
beforeEach(module('module-templates'));
|
||||
|
||||
beforeEach(inject(function($compile, $controller, $rootScope, _$httpBackend_) {
|
||||
|
||||
// Point global variables to injected services
|
||||
$httpBackend = _$httpBackend_;
|
||||
|
||||
$httpBackend.whenGET('/users/me/').respond('');
|
||||
$httpBackend.whenGET(/^(\/forms\/)([0-9a-fA-F]{24})(\/submissions)$/).respond(200, sampleSubmissions);
|
||||
|
||||
//Instantiate directive.
|
||||
var tmp_scope = $rootScope.$new();
|
||||
tmp_scope.myform = sampleForm;
|
||||
tmp_scope.user = sampleUser;
|
||||
|
||||
//gotacha: Controller and link functions will execute.
|
||||
el = angular.element('<edit-submissions-form-directive myform="myform" user="user"></edit-submissions-form-directive>');
|
||||
$compile(el)(tmp_scope);
|
||||
$rootScope.$digest();
|
||||
|
||||
//Grab controller instance
|
||||
controller = el.controller();
|
||||
|
||||
//Grab scope. Depends on type of scope.
|
||||
//See angular.element documentation.
|
||||
scope = el.isolateScope() || el.scope();
|
||||
}));
|
||||
|
||||
it('$scope.initFormSubmissions() should fetch all relevant form submissions', function() {
|
||||
$httpBackend.expectGET(/^(\/forms\/)([0-9a-fA-F]{24})(\/submissions)$/).respond(200, sampleSubmissions);
|
||||
scope.initFormSubmissions();
|
||||
$httpBackend.flush();
|
||||
scope.$digest();
|
||||
});
|
||||
|
||||
describe('Form Table Methods', function(){
|
||||
|
||||
it('$scope.toggleAllCheckers should toggle all checkboxes in table', function(){
|
||||
scope.initFormSubmissions();
|
||||
$httpBackend.flush();
|
||||
|
||||
//Run Controller Logic to Test
|
||||
scope.table.masterChecker = true;
|
||||
scope.toggleAllCheckers();
|
||||
|
||||
for(var i=0; i<scope.table.rows.length; i++){
|
||||
expect(scope.table.rows[i].selected).toBe(true);
|
||||
}
|
||||
expect(scope.table.rows.length).not.toEqual(0);
|
||||
});
|
||||
|
||||
it('$scope.isAtLeastOneChecked should return true when at least one checkbox is selected', function(){
|
||||
scope.initFormSubmissions();
|
||||
$httpBackend.flush();
|
||||
|
||||
scope.table.masterChecker = true;
|
||||
scope.toggleAllCheckers();
|
||||
|
||||
//Run Controller Logic to Test
|
||||
var atLeastOne = scope.isAtLeastOneChecked();
|
||||
|
||||
expect(atLeastOne).toBe(true);
|
||||
});
|
||||
|
||||
it('$scope.deleteSelectedSubmissions should delete all submissions that are selected', function(){
|
||||
scope.initFormSubmissions();
|
||||
$httpBackend.flush();
|
||||
|
||||
scope.table.masterChecker = true;
|
||||
scope.toggleAllCheckers();
|
||||
|
||||
$httpBackend.expect('DELETE', /^(\/forms\/)([0-9a-fA-F]{24})(\/submissions)$/).respond(200);
|
||||
|
||||
//Run Controller Logic to Test
|
||||
scope.deleteSelectedSubmissions();
|
||||
|
||||
$httpBackend.flush();
|
||||
expect(scope.table.rows.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}());
|
@ -0,0 +1,202 @@
|
||||
'use strict';
|
||||
|
||||
(function() {
|
||||
// Forms Controller Spec
|
||||
describe('EditForm Directive-Controller Tests', function() {
|
||||
// Initialize global variables
|
||||
var el, scope, controller, $httpBackend;
|
||||
|
||||
var sampleUser = {
|
||||
firstName: 'Full',
|
||||
lastName: 'Name',
|
||||
email: 'test@test.com',
|
||||
username: 'test@test.com',
|
||||
password: 'password',
|
||||
provider: 'local',
|
||||
roles: ['user'],
|
||||
_id: 'ed873933b1f1dea0ce12fab9',
|
||||
};
|
||||
|
||||
var pdfObj = {
|
||||
fieldname:"file",
|
||||
originalname:"test.pdf",
|
||||
name:"1440112660375.pdf",
|
||||
encoding:"7bit",
|
||||
mimetype:"application/pdf",
|
||||
path:"uploads/tmp/test@test.com/1440112660375.pdf",
|
||||
extension:"pdf",
|
||||
size:56223,
|
||||
truncated:false,
|
||||
buffer:null
|
||||
};
|
||||
|
||||
var sampleForm = {
|
||||
title: 'Form Title',
|
||||
admin: 'ed873933b1f1dea0ce12fab9',
|
||||
language: 'english',
|
||||
form_fields: [
|
||||
{fieldType:'textfield', title:'First Name', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'nascar', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'hockey', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false}
|
||||
],
|
||||
pdf: {},
|
||||
pdfFieldMap: {},
|
||||
startPage: {
|
||||
showStart: false,
|
||||
buttons: [],
|
||||
},
|
||||
hideFooter: false,
|
||||
isGenerated: false,
|
||||
isLive: false,
|
||||
autofillPDFs: false,
|
||||
_id: '525a8422f6d0f87f0e407a33',
|
||||
};
|
||||
|
||||
// The $resource service augments the response object with methods for updating and deleting the resource.
|
||||
// If we were to use the standard toEqual matcher, our tests would fail because the test values would not match
|
||||
// the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher.
|
||||
// When the toEqualData matcher compares two objects, it takes only object properties into
|
||||
// account and ignores methods.
|
||||
beforeEach(function() {
|
||||
jasmine.addMatchers({
|
||||
toEqualData: function(util, customEqualityTesters) {
|
||||
return {
|
||||
compare: function(actual, expected) {
|
||||
return {
|
||||
pass: angular.equals(actual, expected)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Load the main application module
|
||||
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||
beforeEach(module('stateMock'));
|
||||
beforeEach(module('module-templates'));
|
||||
|
||||
beforeEach(inject(function($compile, $controller, $rootScope, _$httpBackend_) {
|
||||
//Instantiate directive.
|
||||
var tmp_scope = $rootScope.$new();
|
||||
tmp_scope.myform = _.cloneDeep(sampleForm);
|
||||
|
||||
//gotacha: Controller and link functions will execute.
|
||||
el = angular.element('<edit-form-directive myform="myform"></edit-form-directive>');
|
||||
$compile(el)(tmp_scope);
|
||||
$rootScope.$digest();
|
||||
|
||||
// Point global variables to injected services
|
||||
$httpBackend = _$httpBackend_;
|
||||
|
||||
$httpBackend.whenGET(/.+\.html$/).respond('');
|
||||
$httpBackend.whenGET('/users/me/').respond('');
|
||||
|
||||
//Grab controller instance
|
||||
controller = el.controller();
|
||||
|
||||
//Grab scope. Depends on type of scope.
|
||||
//See angular.element documentation.
|
||||
scope = el.isolateScope() || el.scope();
|
||||
|
||||
}));
|
||||
|
||||
describe('Form Field Tests',function(){
|
||||
|
||||
beforeEach(function(){
|
||||
scope.myform = _.cloneDeep(sampleForm);
|
||||
});
|
||||
|
||||
it('$scope.addNewField() should ADD a new field to $scope.myform.form_fields', function() {
|
||||
|
||||
//Run controller methods
|
||||
scope.addNewField(true, 'textfield');
|
||||
|
||||
var expectedFormField = {
|
||||
title:'Short Text2',
|
||||
fieldType:'textfield',
|
||||
fieldValue: '',
|
||||
required: true,
|
||||
disabled: false,
|
||||
deletePreserved: false
|
||||
};
|
||||
|
||||
var actualFormField = _.cloneDeep(_.last(scope.myform.form_fields));
|
||||
delete actualFormField._id;
|
||||
|
||||
expect(scope.myform.form_fields.length).toEqual(sampleForm.form_fields.length+1);
|
||||
expect(actualFormField).toEqualData(expectedFormField);
|
||||
});
|
||||
|
||||
it('$scope.deleteField() should DELETE a field to $scope.myform.form_fields', function() {
|
||||
|
||||
//Run controller methods
|
||||
scope.deleteField(0);
|
||||
|
||||
expect(scope.myform.form_fields.length).toEqual(sampleForm.form_fields.length-1);
|
||||
expect(_.first(scope.myform.form_fields)).toEqualData(sampleForm.form_fields[1]);
|
||||
});
|
||||
|
||||
it('$scope.duplicateField() should DUPLICATE a field and update $scope.myform.form_fields', function() {
|
||||
|
||||
//Run controller methods
|
||||
scope.duplicateField(0);
|
||||
|
||||
expect(scope.myform.form_fields.length).toEqual(sampleForm.form_fields.length+1);
|
||||
expect(scope.myform.form_fields[0]).toEqualData(scope.myform.form_fields[1]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Form Field Button Tests',function(){
|
||||
|
||||
it('$scope.addButton() should ADD a button to $scope.myform.startPage.buttons', function() {
|
||||
|
||||
var expectedStartPageBtn = {
|
||||
bgColor:'#ddd',
|
||||
color:'#ffffff',
|
||||
text: 'Button'
|
||||
};
|
||||
|
||||
//Run controller methods
|
||||
scope.addButton();
|
||||
var actualStartPageBtn = _.cloneDeep(_.last(scope.myform.startPage.buttons));
|
||||
delete actualStartPageBtn._id;
|
||||
|
||||
expect(scope.myform.startPage.buttons.length).toEqual(sampleForm.startPage.buttons.length+1);
|
||||
expect(actualStartPageBtn).toEqualData(expectedStartPageBtn);
|
||||
});
|
||||
|
||||
it('$scope.deleteButton() should DELETE a button from $scope.myform.startPage.buttons', function() {
|
||||
//Run controller methods
|
||||
scope.deleteButton(scope.myform.startPage.buttons[0]);
|
||||
|
||||
expect(scope.myform.startPage.buttons.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Form Field Option Tests',function(){
|
||||
it('$scope.addOption() should ADD a new option to a field.fieldOptions', function() {
|
||||
|
||||
//Run controller methods
|
||||
scope.addOption(scope.myform.form_fields[0]);
|
||||
|
||||
var expectedFieldOption = {
|
||||
option_id : 1,
|
||||
option_title : 'Option 1',
|
||||
option_value : 1
|
||||
};
|
||||
|
||||
expect(scope.myform.form_fields[0].fieldOptions.length).toEqual(sampleForm.form_fields[0].fieldOptions.length+1);
|
||||
expect(scope.myform.form_fields[0].fieldOptions[0]).toEqualData(expectedFieldOption);
|
||||
});
|
||||
|
||||
it('$scope.deleteOption() should DELETE remove option from field.fieldOptions', function() {
|
||||
|
||||
//Run controller methods
|
||||
expect(scope.myform.form_fields[0].fieldOptions.length).toEqual(0);
|
||||
expect(scope.myform.form_fields[0].fieldOptions[0]).not.toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
}());
|
@ -34,8 +34,8 @@
|
||||
}));
|
||||
|
||||
it('should be able render all field-icon types', inject(function($compile) {
|
||||
var currType,
|
||||
currClass;
|
||||
var currType, currClass;
|
||||
|
||||
for(var i=0; i<FormFields.types.length; i++){
|
||||
currType = FormFields.types[i];
|
||||
currClass = faClasses[currType.name];
|
@ -0,0 +1,84 @@
|
||||
'use strict';
|
||||
|
||||
(function() {
|
||||
// Forms Controller Spec
|
||||
describe('Field Directive Tests', function() {
|
||||
// Initialize global variables
|
||||
var scope,
|
||||
FormFields,
|
||||
$templateCache,
|
||||
$httpBackend,
|
||||
$compile;
|
||||
|
||||
var sampleUser = {
|
||||
firstName: 'Full',
|
||||
lastName: 'Name',
|
||||
email: 'test@test.com',
|
||||
username: 'test@test.com',
|
||||
password: 'password',
|
||||
provider: 'local',
|
||||
roles: ['user'],
|
||||
_id: 'ed873933b1f1dea0ce12fab9',
|
||||
};
|
||||
|
||||
var sampleFields = [
|
||||
{fieldType:'textfield', title:'First Name', fieldValue: 'AoeuName', deletePreserved: false, required: true, disabled: false},
|
||||
{fieldType:'email', title:'Email', fieldValue: 'aoeu@aoeu.com', deletePreserved: false, required: true, disabled: false},
|
||||
{fieldType:'yes_no', title:'Do you Play Hockey?', fieldValue: 'true', deletePreserved: false, required: true, disabled: false},
|
||||
{fieldType:'checkbox', title:'Receive emails from us', fieldValue: '', deletePreserved: false, required: true, disabled: false},
|
||||
{fieldType:'url', title:'Github Account', fieldValue: 'http://github.com/aoeu', deletePreserved: false, required: true, disabled: false},
|
||||
{fieldType:'textarea', title:'Bio', fieldValue: 'This is my bio.', deletePreserved: false, required: true, disabled: false},
|
||||
{fieldType:'number', title:'Phone #', fieldValue: '5325325325', deletePreserved: false, required: true, disabled: false},
|
||||
{fieldType:'legal', title:'You agree to terms and conditions', description:'By selecting \'I agree\' you are agreeing under Canadian law that you have read and accept terms and conditions outlayed below', fieldValue: '', deletePreserved: false, required: true, disabled: false},
|
||||
{fieldType:'dropdown', title:'Your Sex', fieldValue: 'male', fieldOptions:[ { 'option_id': 0, 'option_title': 'M', 'option_value': 'male' }, { 'option_id': 1, 'option_title': 'F', 'option_value': 'female' }], deletePreserved: false, required: true, disabled: false},
|
||||
{fieldType:'radio', title:'Your Sexual Orientation', fieldValue: 'hetero', fieldOptions:[ { 'option_id': 0, 'option_title': 'Heterosexual', 'option_value': 'hetero' }, { 'option_id': 1, 'option_title': 'Homosexual', 'option_value': 'homo' }, { 'option_id': 2, 'option_title': 'Bisexual', 'option_value': 'bi' }, { 'option_id': 3, 'option_title': 'Asexual', 'option_value': 'asex' }], deletePreserved: false, required: true, disabled: false},
|
||||
{fieldType:'rating', title:'Your Current Happiness', fieldValue: '0', deletePreserved: false, required: true, disabled: false},
|
||||
];
|
||||
|
||||
|
||||
// The $resource service augments the response object with methods for updating and deleting the resource.
|
||||
// If we were to use the standard toEqual matcher, our tests would fail because the test values would not match
|
||||
// the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher.
|
||||
// When the toEqualData matcher compares two objects, it takes only object properties into
|
||||
// account and ignores methods.
|
||||
beforeEach(function() {
|
||||
jasmine.addMatchers({
|
||||
toEqualData: function(util, customEqualityTesters) {
|
||||
return {
|
||||
compare: function(actual, expected) {
|
||||
return {
|
||||
pass: angular.equals(actual, expected)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Load the main application module
|
||||
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||
beforeEach(module('stateMock'));
|
||||
beforeEach(module('module-templates'));
|
||||
|
||||
beforeEach(inject(function($rootScope, _FormFields_, _$compile_) {
|
||||
scope = $rootScope.$new();
|
||||
FormFields = _FormFields_;
|
||||
|
||||
$compile = _$compile_;
|
||||
}));
|
||||
|
||||
|
||||
it('should be able to render all field types in html', inject(function($rootScope) {
|
||||
scope.fields = sampleFields;
|
||||
|
||||
for(var field in sampleFields){
|
||||
scope.myfield = field;
|
||||
var element = angular.element('<field-directive field="myfield"></field-directive>');
|
||||
$compile(element)(scope);
|
||||
scope.$digest();
|
||||
|
||||
expect(element.html()).not.toEqual('<div>'+field.title+'</div>');
|
||||
}
|
||||
}));
|
||||
});
|
||||
}());
|
@ -0,0 +1,204 @@
|
||||
'use strict';
|
||||
|
||||
(function() {
|
||||
// Forms Controller Spec
|
||||
describe('SubmitForm Directive-Controller Tests', function() {
|
||||
// Initialize global variables
|
||||
var el, scope, controller, $httpBackend;
|
||||
|
||||
var sampleUser = {
|
||||
firstName: 'Full',
|
||||
lastName: 'Name',
|
||||
email: 'test@test.com',
|
||||
username: 'test@test.com',
|
||||
password: 'password',
|
||||
provider: 'local',
|
||||
roles: ['user'],
|
||||
_id: 'ed873933b1f1dea0ce12fab9',
|
||||
};
|
||||
|
||||
var pdfObj = {
|
||||
fieldname:"file",
|
||||
originalname:"test.pdf",
|
||||
name:"1440112660375.pdf",
|
||||
encoding:"7bit",
|
||||
mimetype:"application/pdf",
|
||||
path:"uploads/tmp/test@test.com/1440112660375.pdf",
|
||||
extension:"pdf",
|
||||
size:56223,
|
||||
truncated:false,
|
||||
buffer:null
|
||||
};
|
||||
|
||||
var sampleForm = {
|
||||
title: 'Form Title',
|
||||
admin: 'ed873933b1f1dea0ce12fab9',
|
||||
language: 'english',
|
||||
form_fields: [
|
||||
{fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false},
|
||||
{fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false}
|
||||
],
|
||||
visible_form_fields: [
|
||||
{'fieldType':'textfield', 'title':'First Name', 'fieldValue': '', 'deletePreserved': false},
|
||||
{'fieldType':'checkbox', 'title':'nascar', 'fieldValue': '', 'deletePreserved': false},
|
||||
{'fieldType':'checkbox', 'title':'hockey', 'fieldValue': '', 'deletePreserved': false}
|
||||
],
|
||||
pdf: {},
|
||||
pdfFieldMap: {},
|
||||
startPage: {
|
||||
showStart: false
|
||||
},
|
||||
hideFooter: false,
|
||||
isGenerated: false,
|
||||
isLive: false,
|
||||
autofillPDFs: false,
|
||||
_id: '525a8422f6d0f87f0e407a33',
|
||||
};
|
||||
|
||||
var sampleSubmission = {
|
||||
form_fields: [
|
||||
{fieldType:'textfield', title:'First Name', fieldValue: 'John Smith', deletePreserved: false},
|
||||
{fieldType:'yes_no', title:'Do you like nascar', fieldValue: true, deletePreserved: false},
|
||||
{fieldType:'yes_no', title:'Do you like hockey', fieldValue: false, deletePreserved: false}
|
||||
],
|
||||
admin: sampleUser,
|
||||
form: sampleForm,
|
||||
timeElapsed: 17.55
|
||||
};
|
||||
|
||||
var sampleSubmissions = [{
|
||||
form_fields: [
|
||||
{fieldType:'textfield', title:'First Name', fieldValue: 'The Terminator', deletePreserved: false},
|
||||
{fieldType:'yes_no', title:'Do you like nascar', fieldValue: 'true', deletePreserved: false},
|
||||
{fieldType:'yes_no', title:'Do you like hockey', fieldValue: 'false', deletePreserved: false}
|
||||
],
|
||||
admin: sampleUser,
|
||||
form: sampleForm,
|
||||
timeElapsed: 10.33
|
||||
},
|
||||
{
|
||||
form_fields: [
|
||||
{fieldType:'textfield', title:'First Name', fieldValue: 'John Smith', deletePreserved: false},
|
||||
{fieldType:'yes_no', title:'Do you like nascar', fieldValue: 'true', deletePreserved: false},
|
||||
{fieldType:'yes_no', title:'Do you like hockey', fieldValue: 'true', deletePreserved: false}
|
||||
],
|
||||
admin: sampleUser,
|
||||
form: sampleForm,
|
||||
timeElapsed: 2.33
|
||||
},
|
||||
{
|
||||
form_fields: [
|
||||
{fieldType:'textfield', title:'First Name', fieldValue: 'Jane Doe', deletePreserved: false},
|
||||
{fieldType:'yes_no', title:'Do you like nascar', fieldValue: 'false', deletePreserved: false},
|
||||
{fieldType:'yes_no', title:'Do you like hockey', fieldValue: 'false', deletePreserved: false}
|
||||
],
|
||||
admin: sampleUser,
|
||||
form: sampleForm,
|
||||
timeElapsed: 11.11
|
||||
}];
|
||||
|
||||
// The $resource service augments the response object with methods for updating and deleting the resource.
|
||||
// If we were to use the standard toEqual matcher, our tests would fail because the test values would not match
|
||||
// the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher.
|
||||
// When the toEqualData matcher compares two objects, it takes only object properties into
|
||||
// account and ignores methods.
|
||||
beforeEach(function() {
|
||||
jasmine.addMatchers({
|
||||
toEqualData: function(util, customEqualityTesters) {
|
||||
return {
|
||||
compare: function(actual, expected) {
|
||||
return {
|
||||
pass: angular.equals(actual, expected)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Load the main application module
|
||||
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||
beforeEach(module('stateMock'));
|
||||
beforeEach(module('module-templates'));
|
||||
|
||||
beforeEach(inject(function($compile, $controller, $rootScope, _$httpBackend_) {
|
||||
|
||||
// Point global variables to injected services
|
||||
$httpBackend = _$httpBackend_;
|
||||
|
||||
$httpBackend.whenGET('/users/me/').respond('');
|
||||
|
||||
//Instantiate directive.
|
||||
var tmp_scope = $rootScope.$new();
|
||||
tmp_scope.myform = sampleForm;
|
||||
|
||||
//gotacha: Controller and link functions will execute.
|
||||
el = angular.element('<submit-form-directive myform="myform"></submit-form-directive>');
|
||||
$compile(el)(tmp_scope);
|
||||
$rootScope.$digest();
|
||||
|
||||
//Grab controller instance
|
||||
controller = el.controller();
|
||||
|
||||
//Grab scope. Depends on type of scope.
|
||||
//See angular.element documentation.
|
||||
scope = el.isolateScope() || el.scope();
|
||||
}));
|
||||
|
||||
var Validator = (function() {
|
||||
return {
|
||||
hasMinimumFields: function(entry) {
|
||||
return !_.isEmpty(entry._id) && !_.isEmpty(entry.title);
|
||||
},
|
||||
isNewForm: function(entry) {
|
||||
return this.hasMinimumFields(entry);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
it('$scope.submit() should submit valid form', function(){
|
||||
//Initialize variables
|
||||
scope.myform.form_fields = sampleSubmissions[0].form_fields;
|
||||
|
||||
var expectedForm = _.cloneDeep(sampleForm);
|
||||
expectedForm.form_fields = sampleSubmissions[0].form_fields;
|
||||
delete expectedForm.visible_form_fields;
|
||||
|
||||
var data = function(data) {
|
||||
var form = angular.fromJson(data);
|
||||
var compareForm = _.cloneDeep(form);
|
||||
delete compareForm.timeElapsed;
|
||||
delete compareForm.percentageComplete;
|
||||
|
||||
return Validator.isNewForm(form) && _.isEqual(compareForm, expectedForm);
|
||||
};
|
||||
|
||||
|
||||
// console.log('!_.isEmpty(expectedForm.timeElapsed): '+!_.isEmpty(expectedForm.timeElapsed));
|
||||
console.log('data:'+data(expectedForm));
|
||||
|
||||
// //Set expected HTTP requests
|
||||
$httpBackend.expect('POST',/^(\/forms\/)([0-9a-fA-F]{24})$/, data).respond(200);
|
||||
|
||||
// //Run Controller Logic to Test
|
||||
scope.submit();
|
||||
|
||||
$httpBackend.flush();
|
||||
expect(scope.myform.submitted).toBe(true);
|
||||
expect(scope.error).toEqual('');
|
||||
});
|
||||
|
||||
it('$scope.reloadForm() should reset and reload form', function(){
|
||||
scope.submit();
|
||||
scope.reloadForm();
|
||||
|
||||
expect(scope.submitted).toBe(false);
|
||||
for(var i=0; i<scope.myform.form_fields.length; i++){
|
||||
expect(scope.myform.form_fields[i].fieldValue).toEqual('');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}());
|
@ -86,8 +86,8 @@
|
||||
<tab-heading>
|
||||
View Submissions
|
||||
</tab-heading>
|
||||
<submissions-form-directive myform="myform" user="user">
|
||||
</submissions-form-directive>
|
||||
<edit-submissions-form-directive myform="myform" user="user">
|
||||
</edit-submissions-form-directive>
|
||||
</tab>
|
||||
</tabset>
|
||||
<!--
|
||||
|
@ -1,13 +1,20 @@
|
||||
<div class="field row" ng-click="setActiveField(field._id)" ng-if="field.fieldOptions.length > 0">
|
||||
<div class="col-xs-12 field-title field-title">{{field.title}} <span class="required-error" ng-show="field.required && field.fieldValue == 0">(* required)</span> </div>
|
||||
|
||||
<div class="col-xs-12 field-input">
|
||||
<div ng-repeat="option in field.fieldOptions" class="row-fluid">
|
||||
<label class="btn btn-info col-xs-3">
|
||||
<input ng-focus="setActiveField(field._id)"type="checkbox" value="{{option.option_value}}" ng-model="field.fieldValue" ng-model-options="{ debounce: 250 }" ng-required="field.required" ng-disabled="field.disabled" ng-init="field.fieldValue = field.fieldOptions[0].option_value"/>
|
||||
<input ng-focus="setActiveField(field._id)"
|
||||
type="checkbox"
|
||||
value="{{option.option_value}}"
|
||||
ng-model="field.fieldValue"
|
||||
ng-model-options="{ debounce: 250 }"
|
||||
ng-required="field.required"
|
||||
ng-disabled="field.disabled"
|
||||
ng-init="field.fieldValue = field.fieldOptions[0].option_value"/>
|
||||
<span ng-bind="option.option_title"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="field row" ng-click="setActiveField(field._id)">
|
||||
</div>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="row field" ng-if="form.autofillPDFs">
|
||||
<div class="field row" ng-if="form.autofillPDFs">
|
||||
<div class="col-sm-4 field-title">
|
||||
<h5>{{field.title}} <span class="required-error" ng-show="field.required && field.fieldValue == 0">(* required)</span></h5>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="textfield natural field row" ng-click="setActiveField(field._id)">
|
||||
<div class="field row textfield natural" ng-click="setActiveField(field._id)">
|
||||
<div class="col-xs-12 field-title"><h3><span class="fa fa-angle-double-right"></span> {{field.title}} <span class="required-error" ng-show="field.required && !field.fieldValue">*(required)</span></h3></div>
|
||||
<div class="col-xs-12 field-input">
|
||||
<input ng-focus="setActiveField(field._id)"type="text"
|
||||
|
@ -1,7 +1,15 @@
|
||||
<div class="textfield field row" ng-click="setActiveField(field._id)">
|
||||
<div class="col-xs-12 field-title"><h3><span class="fa fa-angle-double-right"></span> {{field.title}} <span class="required-error" ng-show="field.required && !field.fieldValue">*(required)</span></h3></div>
|
||||
<div class="col-xs-12 field-title">
|
||||
<h3>
|
||||
<span class="fa fa-angle-double-right"></span> {{field.title}}
|
||||
<span class="required-error" ng-show="field.required && !field.fieldValue">
|
||||
*(required)
|
||||
</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="col-xs-12 field-input">
|
||||
<input ng-focus="setActiveField(field._id)"type="text"
|
||||
<input ng-focus="setActiveField(field._id)"
|
||||
type="text"
|
||||
class="text-field-input"
|
||||
ng-model="field.fieldValue"
|
||||
ng-model-options="{ debounce: 250 }"
|
||||
|
@ -111,7 +111,7 @@
|
||||
</div>
|
||||
|
||||
|
||||
<!-- generate typeform from MedForm yes/no field -->
|
||||
<!-- generate typeform from NodeForm yes/no field -->
|
||||
<div class="row field">
|
||||
<div class="col-sm-6 field-title">
|
||||
<h5>Autogenerate Typeform?</h5>
|
||||
|
@ -392,7 +392,7 @@
|
||||
<div class="col-md-1 hidden-xs hidden-sm" style="padding:0 5px;" >
|
||||
<div class="panel-group tool-panel text-center">
|
||||
<div class="panel panel-default" ng-repeat="field in myform.form_fields" ng-if="!field.deletePreserved">
|
||||
<div class="panel-heading" style="padding: 10px 10px; height: 37px;" ng-click="deleteField(field.$$hashKey)">
|
||||
<div class="panel-heading" style="padding: 10px 10px; height: 37px;" ng-click="deleteField($index)">
|
||||
<span class="text-center">
|
||||
<a href="" class="fa fa-trash-o"></a>
|
||||
</span>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<div class="submissions-table row container">
|
||||
<div class="submissions-table row container" ng-init="initFormSubmissions()">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-2">
|
||||
|
@ -2,17 +2,17 @@
|
||||
|
||||
<section class="overlay submitform" ng-if="selected" ng-click="hideOverlay()"></section>
|
||||
|
||||
<div ng-show="!form.submitted && form.startPage.showStart" class="form-submitted">
|
||||
<div ng-show="!myform.submitted && myform.startPage.showStart" class="form-submitted">
|
||||
<div class="field row text-center">
|
||||
<div class="col-xs-12 text-center">
|
||||
<h1>Welcome to {{form.title}}</h1>
|
||||
<h1>Welcome to {{myform.title}}</h1>
|
||||
</div>
|
||||
<div class="col-xs-10 col-xs-offset-1 text-center">
|
||||
<p>{{form.startPage.introText}}</p>
|
||||
<p>{{myform.startPage.introText}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-actions">
|
||||
<p ng-repeat="button in form.startPage.buttons" class="col-xs-6 col-xs-offset-3 text-center">
|
||||
<p ng-repeat="button in myform.startPage.buttons" class="col-xs-6 col-xs-offset-3 text-center">
|
||||
<button class="btn btn-info" type="button">
|
||||
<a href="{{button.url}}" style="font-size: 1.6em; text-decoration: none;">{{button.buttonText}}</a>
|
||||
</button>
|
||||
@ -21,22 +21,22 @@
|
||||
<div class="row form-actions">
|
||||
<p class="col-xs-6 col-xs-offset-3 text-center">
|
||||
<button class="btn btn-info" type="button">
|
||||
<a ng-click="exitstartPage()" style="font-size: 1.6em; text-decoration: none;">Continue to Form</a>
|
||||
<a ng-click="exitStartPage()" style="font-size: 1.6em; text-decoration: none;">Continue to Form</a>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="!form.submitted && !form.startPage.showStart" data-ng-init="initFocus()">
|
||||
<div ng-show="!myform.submitted && !myform.startPage.showStart" data-ng-init="initFocus()">
|
||||
<div class="field row" style="padding-bottom:5em;">
|
||||
<div class="col-sm-10 col-sm-offset-1">
|
||||
<h1>{{ form.title }} <span style="font-size:0.8em; color: #bbb;" ng-if="!form.isLive">(private preview)</span></h1>
|
||||
<h1>{{ myform.title }} <span style="font-size:0.8em; color: #bbb;" ng-if="!myform.isLive">(private preview)</span></h1>
|
||||
<hr>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<form name="myForm" class="submission-form col-sm-12 col-md-offset-1 col-md-10">
|
||||
<div ng-repeat="field in form.form_fields" ng-if="!field.deletePreserved" ng-class="{activeField: selected == field._id }" class="row field-directive">
|
||||
<div ng-repeat="field in myform.form_fields" ng-if="!field.deletePreserved" ng-class="{activeField: selected == field._id }" class="row field-directive">
|
||||
<field-directive field="field" >
|
||||
</field-directive>
|
||||
</div>
|
||||
@ -46,16 +46,16 @@
|
||||
<hr>
|
||||
|
||||
<div class="row form-actions">
|
||||
<button class="btn btn-success col-sm-2 col-sm-offset-5" type="button" ng-disabled="myForm.$invalid" ng-click="submit()" style="font-size: 1.6em;">
|
||||
<button class="btn btn-success col-sm-2 col-sm-offset-5" type="button" ng-disabled="mymyform.$invalid" ng-click="submit()" style="font-size: 1.6em;">
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-show="form.submitted" class="form-submitted">
|
||||
<div ng-show="myform.submitted" class="form-submitted">
|
||||
|
||||
<!-- <div class="field row">
|
||||
<div class="col-sm-11 col-sm-offset-1"><h1>{{ form.title }}</h1>
|
||||
<div class="col-sm-11 col-sm-offset-1"><h1>{{ myform.title }}</h1>
|
||||
<hr>
|
||||
</div>
|
||||
</div> -->
|
||||
@ -71,7 +71,7 @@
|
||||
</p>
|
||||
<!-- <p class="text-center col-xs-2" ng-if="authentication.isAuthenticated()">
|
||||
<button class="btn btn-caution left" type="button">
|
||||
<a href="/#!/forms/{{form._id}}/admin" style="color:white; font-size: 1.6em; text-decoration: none;">Edit Form</a>
|
||||
<a href="/#!/forms/{{myform._id}}/admin" style="color:white; font-size: 1.6em; text-decoration: none;">Edit Form</a>
|
||||
</button>
|
||||
</p> -->
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<section data-ng-controller="SubmitFormController" class="public-form" ng-init="initForm()">
|
||||
|
||||
<form-directive form="myform"></form-directive>
|
||||
<submit-form-directive myform="myform"></submit-form-directive>
|
||||
|
||||
<section ng-if="!myform.hideFooter" class="navbar navbar-fixed-bottom" style="background-color:rgba(242,242,242,0.5); padding-top:15px;">
|
||||
<div class="container" >
|
||||
@ -10,10 +10,10 @@
|
||||
</div>
|
||||
<div class="hidden-xs hidden-sm col-md-6 col-md-offset-3 row">
|
||||
<div class="col-md-4 col-md-offset-2" ng-if="!authentication.isAuthenticated()">
|
||||
<a href="/#!/forms" class="btn btn-default">Create a Medform</a>
|
||||
<a href="/#!/forms" class="btn btn-default">Create a NodeForm</a>
|
||||
</div>
|
||||
<div class="col-md-4 col-md-offset-2" ng-if="authentication.isAuthenticated()" class="hidden-sm hidden-xs">
|
||||
<a href="/#!/forms/{{myform._id}}/admin" class="btn btn-default">Edit this Medform</a>
|
||||
<a href="/#!/forms/{{myform._id}}/admin" class="btn btn-default">Edit this NodeForm</a>
|
||||
</div>
|
||||
<div class="col-md-1 col-md-offset-2" style="padding-left:5px" class="hidden-sm hidden-xs">
|
||||
<div class="btn btn-info" id="focusDownButton">\/</div>
|
||||
|
@ -5,12 +5,11 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca
|
||||
|
||||
$scope = $rootScope;
|
||||
$scope.credentials = {};
|
||||
$scope.error = null;
|
||||
$scope.error = '';
|
||||
|
||||
$scope.signin = function() {
|
||||
User.login($scope.credentials).then(
|
||||
function(response) {
|
||||
// console.log(response);
|
||||
Auth.login(response);
|
||||
$scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User);
|
||||
|
||||
@ -39,6 +38,7 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca
|
||||
function(error) {
|
||||
if(error) {
|
||||
$scope.error = error;
|
||||
console.log(error);
|
||||
}else {
|
||||
console.log('No response received');
|
||||
}
|
||||
|
@ -3,9 +3,6 @@
|
||||
angular.module('users').controller('PasswordController', ['$scope', '$stateParams', '$state', 'User',
|
||||
function($scope, $stateParams, $state, User) {
|
||||
|
||||
//If user is signed in then redirect back home
|
||||
// if ($scope.authentication.isAuthenticated()) $state.go('home');
|
||||
|
||||
// Submit forgotten password account id
|
||||
$scope.askForPasswordReset = function() {
|
||||
User.askForPasswordReset($scope.credentials).then(
|
||||
|
@ -3,16 +3,12 @@
|
||||
angular.module('users').controller('SettingsController', ['$scope', '$rootScope', '$http', '$state', 'Users',
|
||||
function($scope, $rootScope, $http, $state, Users) {
|
||||
$scope.user = $rootScope.user;
|
||||
console.log($scope.user);
|
||||
// If user is not signed in then redirect back home
|
||||
if (!$scope.user) $state.go('home');
|
||||
|
||||
// Check if there are additional accounts
|
||||
$scope.hasConnectedAdditionalSocialAccounts = function(provider) {
|
||||
for (var i in $scope.user.additionalProvidersData) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
@ -68,6 +64,5 @@ angular.module('users').controller('SettingsController', ['$scope', '$rootScope'
|
||||
});
|
||||
};
|
||||
|
||||
// });
|
||||
}
|
||||
]);
|
@ -1,40 +1,45 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('users').factory('Auth', function($window) {
|
||||
angular.module('users').factory('Auth', ['$window',
|
||||
function($window) {
|
||||
|
||||
var userState = {
|
||||
isLoggedIn: false
|
||||
};
|
||||
|
||||
var service = {
|
||||
currentUser: null,
|
||||
_currentUser: null,
|
||||
get currentUser(){
|
||||
return this._currentUser;
|
||||
},
|
||||
|
||||
// Note: we can't make the User a dependency of Auth
|
||||
// because that would create a circular dependency
|
||||
// Auth <- $http <- $resource <- LoopBackResource <- User <- Auth
|
||||
ensureHasCurrentUser: function(User) {
|
||||
if (service.currentUser && service.currentUser.username) {
|
||||
if (service._currentUser && service._currentUser.username) {
|
||||
console.log('Using local current user.');
|
||||
// console.log(service.currentUser);
|
||||
return service.currentUser;
|
||||
// console.log(service._currentUser);
|
||||
return service._currentUser;
|
||||
}
|
||||
else if ($window.user){
|
||||
console.log('Using cached current user.');
|
||||
// console.log($window.user);
|
||||
service.currentUser = $window.user;
|
||||
return service.currentUser;
|
||||
service._currentUser = $window.user;
|
||||
return service._currentUser;
|
||||
}
|
||||
else{
|
||||
console.log('Fetching current user from the server.');
|
||||
User.getCurrent().then(function(user) {
|
||||
// success
|
||||
service.currentUser = user;
|
||||
service._currentUser = user;
|
||||
userState.isLoggedIn = true;
|
||||
$window.user = service.currentUser;
|
||||
return service.currentUser;
|
||||
$window.user = service._currentUser;
|
||||
return service._currentUser;
|
||||
},
|
||||
function(response) {
|
||||
userState.isLoggedIn = false;
|
||||
service.currentUser = null;
|
||||
service._currentUser = null;
|
||||
$window.user = null;
|
||||
console.log('User.getCurrent() err', response);
|
||||
return null;
|
||||
@ -43,7 +48,7 @@ angular.module('users').factory('Auth', function($window) {
|
||||
},
|
||||
|
||||
isAuthenticated: function() {
|
||||
return !!service.currentUser;
|
||||
return !!service._currentUser;
|
||||
},
|
||||
|
||||
getUserState: function() {
|
||||
@ -52,14 +57,16 @@ angular.module('users').factory('Auth', function($window) {
|
||||
|
||||
login: function(new_user) {
|
||||
userState.isLoggedIn = true;
|
||||
service.currentUser = new_user;
|
||||
service._currentUser = new_user;
|
||||
},
|
||||
|
||||
logout: function() {
|
||||
$window.user = null;
|
||||
userState.isLoggedIn = false;
|
||||
service.currentUser = null;
|
||||
service._currentUser = null;
|
||||
},
|
||||
};
|
||||
return service;
|
||||
});
|
||||
|
||||
}
|
||||
]);
|
||||
|
@ -3,7 +3,6 @@
|
||||
angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', '$state',
|
||||
function($window, $q, $timeout, $http, $state) {
|
||||
|
||||
|
||||
var userService = {
|
||||
getCurrent: function() {
|
||||
var deferred = $q.defer();
|
||||
@ -26,9 +25,11 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', '
|
||||
}).error(function(error) {
|
||||
deferred.reject(error.message || error);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
logout: function() {
|
||||
|
||||
var deferred = $q.defer();
|
||||
$http.get('/auth/signout').success(function(response) {
|
||||
deferred.resolve(null);
|
||||
@ -41,12 +42,10 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', '
|
||||
signup: function(credentials) {
|
||||
|
||||
var deferred = $q.defer();
|
||||
|
||||
$http.post('/auth/signup', credentials).success(function(response) {
|
||||
// If successful we assign the response to the global user model
|
||||
deferred.resolve(response);
|
||||
}).error(function(error) {
|
||||
|
||||
deferred.reject(error.message || error);
|
||||
});
|
||||
|
||||
@ -54,8 +53,9 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', '
|
||||
},
|
||||
|
||||
resendVerifyEmail: function(_email) {
|
||||
|
||||
var deferred = $q.defer();
|
||||
$http.post('/auth/verify/', {email: _email}).success(function(response) {
|
||||
$http.post('/auth/verify', {email: _email}).success(function(response) {
|
||||
deferred.resolve(response);
|
||||
}).error(function(error) {
|
||||
deferred.reject(error.message || error);
|
||||
@ -65,6 +65,12 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', '
|
||||
},
|
||||
|
||||
validateVerifyToken: function(token) {
|
||||
|
||||
//DAVID: TODO: The valid length of a token should somehow be linked to server config values
|
||||
//DAVID: TODO: SEMI-URGENT: Should we even be doing this?
|
||||
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();
|
||||
$http.get('/auth/verify/'+token).success(function(response) {
|
||||
deferred.resolve(response);
|
||||
@ -76,6 +82,7 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', '
|
||||
},
|
||||
|
||||
resetPassword: function(passwordDetails, token) {
|
||||
|
||||
var deferred = $q.defer();
|
||||
$http.get('/auth/password/'+token, passwordDetails).success(function(response) {
|
||||
deferred.resolve();
|
||||
@ -88,12 +95,11 @@ angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', '
|
||||
|
||||
// Submit forgotten password account id
|
||||
askForPasswordReset: function(credentials) {
|
||||
|
||||
var deferred = $q.defer();
|
||||
$http.post('/auth/forgot', credentials).success(function(response) {
|
||||
// Show user success message and clear form
|
||||
|
||||
deferred.resolve(response);
|
||||
|
||||
}).error(function(error) {
|
||||
// Show user error message
|
||||
deferred.reject(error.message || error);
|
||||
|
@ -0,0 +1,181 @@
|
||||
// 'use strict';
|
||||
|
||||
// (function() {
|
||||
// // Forms Controller Spec
|
||||
// describe('Authentication Controller Tests', function() {
|
||||
// // Initialize global variables
|
||||
// var AuthenticationController,
|
||||
// scope,
|
||||
// $httpBackend,
|
||||
// $stateParams,
|
||||
// $location,
|
||||
// $state;
|
||||
|
||||
// var sampleUser = {
|
||||
// firstName: 'Full',
|
||||
// lastName: 'Name',
|
||||
// email: 'test@test.com',
|
||||
// username: 'test@test.com',
|
||||
// password: 'password',
|
||||
// provider: 'local',
|
||||
// roles: ['user'],
|
||||
// _id: 'ed873933b1f1dea0ce12fab9'
|
||||
// };
|
||||
|
||||
// var sampleForm = {
|
||||
// title: 'Form Title',
|
||||
// admin: 'ed873933b1f1dea0ce12fab9',
|
||||
// language: 'english',
|
||||
// form_fields: [
|
||||
// {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false},
|
||||
// {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false},
|
||||
// {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false}
|
||||
// ],
|
||||
// _id: '525a8422f6d0f87f0e407a33'
|
||||
// };
|
||||
|
||||
// var expectedForm = {
|
||||
// title: 'Form Title',
|
||||
// admin: 'ed873933b1f1dea0ce12fab9',
|
||||
// language: 'english',
|
||||
// form_fields: [
|
||||
// {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false},
|
||||
// {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false},
|
||||
// {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false}
|
||||
// ],
|
||||
// visible_form_fields: [
|
||||
// {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false},
|
||||
// {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false},
|
||||
// {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false}
|
||||
// ],
|
||||
// _id: '525a8422f6d0f87f0e407a33'
|
||||
// };
|
||||
|
||||
// var sampleCredentials = {
|
||||
// username: sampleUser.username,
|
||||
// password: sampleUser.password,
|
||||
// };
|
||||
|
||||
|
||||
|
||||
// // The $resource service augments the response object with methods for updating and deleting the resource.
|
||||
// // If we were to use the standard toEqual matcher, our tests would fail because the test values would not match
|
||||
// // the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher.
|
||||
// // When the toEqualData matcher compares two objects, it takes only object properties into
|
||||
// // account and ignores methods.
|
||||
// beforeEach(function() {
|
||||
// jasmine.addMatchers({
|
||||
// toEqualData: function(util, customEqualityTesters) {
|
||||
// return {
|
||||
// compare: function(actual, expected) {
|
||||
// return {
|
||||
// pass: angular.equals(actual, expected)
|
||||
// };
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
|
||||
|
||||
// // Load the main application module
|
||||
// beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||
|
||||
// beforeEach(module('stateMock'));
|
||||
|
||||
// // Mock Users Service
|
||||
// beforeEach(module(function($provide) {
|
||||
// $provide.service('User', function($q) {
|
||||
// return {
|
||||
// getCurrent: function() {
|
||||
// var deferred = $q.defer();
|
||||
// deferred.resolve( JSON.stringify(sampleUser) );
|
||||
// return deferred.promise;
|
||||
// },
|
||||
// login: function(credentials) {
|
||||
// var deferred = $q.defer();
|
||||
// if( credentials.password === sampleUser.password && credentials.username === sampleUser.username){
|
||||
// deferred.resolve( JSON.stringify(sampleUser) );
|
||||
// }else {
|
||||
// deferred.resolve('Error: User could not be loggedin');
|
||||
// }
|
||||
|
||||
// return deferred.promise;
|
||||
// },
|
||||
// logout: function() {
|
||||
// var deferred = $q.defer();
|
||||
// deferred.resolve(null);
|
||||
// return deferred.promise;
|
||||
// },
|
||||
// signup: function(credentials) {
|
||||
// var deferred = $q.defer();
|
||||
// if( credentials.password === sampleUser.password && credentials.username === sampleUser.username){
|
||||
// deferred.resolve( JSON.stringify(sampleUser) );
|
||||
// }else {
|
||||
// deferred.resolve('Error: User could not be signed up');
|
||||
// }
|
||||
|
||||
// return deferred.promise;
|
||||
// }
|
||||
// };
|
||||
// });
|
||||
// }));
|
||||
|
||||
// // Mock Authentication Service
|
||||
// beforeEach(module(function($provide) {
|
||||
// $provide.service('Auth', function() {
|
||||
// return {
|
||||
// ensureHasCurrentUser: function() {
|
||||
// return sampleUser;
|
||||
// },
|
||||
// isAuthenticated: function() {
|
||||
// return true;
|
||||
// },
|
||||
// getUserState: function() {
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
// });
|
||||
// }));
|
||||
|
||||
// // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
|
||||
// // This allows us to inject a service but then attach it to a variable
|
||||
// // with the same name as the service.
|
||||
// beforeEach(inject(function($controller, $rootScope, _$state_, _$location_, _$stateParams_, _$httpBackend_, CurrentForm, Forms) {
|
||||
// // Set a new global scope
|
||||
// scope = $rootScope.$new();
|
||||
// scope.abc = 'hello';
|
||||
|
||||
// // Point global variables to injected services
|
||||
// $stateParams = _$stateParams_;
|
||||
// $httpBackend = _$httpBackend_;
|
||||
// $location = _$location_;
|
||||
// $state = _$state_;
|
||||
|
||||
// // $httpBackend.whenGET(/\.html$/).respond('');
|
||||
// $httpBackend.whenGET('/users/me/').respond('');
|
||||
|
||||
// // Initialize the Forms controller.
|
||||
// AuthenticationController = $controller('AuthenticationController', { $scope: scope });
|
||||
// }));
|
||||
|
||||
// it('$scope.signin should sigin in user with valid credentials', inject(function(Auth) {
|
||||
|
||||
// //Set $state transition
|
||||
// // $state.expectTransitionTo('listForms');
|
||||
// //Set POST response
|
||||
// // $httpBackend.expect('POST', '/auth/signin', sampleCredentials).respond(200, sampleUser);
|
||||
|
||||
// scope.abc = 'sampleCredentials';
|
||||
// //Run Controller Logic to Test
|
||||
// scope.signin();
|
||||
|
||||
// // $httpBackend.flush();
|
||||
|
||||
// // Test scope value
|
||||
// // expect(Auth.ensureHasCurrentUser()).toEqualData(sampleUser);
|
||||
// }));
|
||||
|
||||
|
||||
// });
|
||||
// }());
|
@ -0,0 +1,93 @@
|
||||
'use strict';
|
||||
|
||||
(function() {
|
||||
// Forms Controller Spec
|
||||
describe('Auth Service Tests', function() {
|
||||
// Initialize global variables
|
||||
var Auth;
|
||||
|
||||
var sampleUser = {
|
||||
firstName: 'Full',
|
||||
lastName: 'Name',
|
||||
email: 'test@test.com',
|
||||
username: 'test@test.com',
|
||||
password: 'password',
|
||||
provider: 'local',
|
||||
roles: ['user'],
|
||||
_id: 'ed873933b1f1dea0ce12fab9'
|
||||
};
|
||||
|
||||
|
||||
// The $resource service augments the response object with methods for updating and deleting the resource.
|
||||
// If we were to use the standard toEqual matcher, our tests would fail because the test values would not match
|
||||
// the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher.
|
||||
// When the toEqualData matcher compares two objects, it takes only object properties into
|
||||
// account and ignores methods.
|
||||
beforeEach(function() {
|
||||
jasmine.addMatchers({
|
||||
toEqualData: function(util, customEqualityTesters) {
|
||||
return {
|
||||
compare: function(actual, expected) {
|
||||
return {
|
||||
pass: angular.equals(actual, expected)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Load the main application module
|
||||
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||
|
||||
// The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
|
||||
// This allows us to inject a service but then attach it to a variable
|
||||
// with the same name as the service.
|
||||
beforeEach(inject(function(_Auth_) {
|
||||
Auth = _Auth_;
|
||||
}));
|
||||
|
||||
it('Auth.login() should save user in Auth.currentUser', function() {
|
||||
//Run Service Logic to Test
|
||||
Auth.login(sampleUser);
|
||||
expect(Auth.currentUser).toEqualData(sampleUser);
|
||||
});
|
||||
|
||||
it('Auth.logout() should remove saved user', inject(function($window) {
|
||||
//Run Service Logic to Test
|
||||
Auth.logout();
|
||||
|
||||
expect($window.user).toEqual(null);
|
||||
expect(Auth.currentUser).toEqual(null);
|
||||
expect(Auth.isAuthenticated()).toBe(false);
|
||||
expect(Auth.getUserState().isLoggedIn).toBe(false);
|
||||
}));
|
||||
|
||||
it('Auth.getUserState() should fetch current user state', function() {
|
||||
|
||||
//Run Service Logic to Test
|
||||
Auth.login(sampleUser);
|
||||
var currUserState = Auth.getUserState();
|
||||
|
||||
expect(currUserState.isLoggedIn).toBe(true);
|
||||
|
||||
//Run Service Logic to Test
|
||||
Auth.logout();
|
||||
currUserState = Auth.getUserState();
|
||||
|
||||
expect(currUserState.isLoggedIn).toBe(false);
|
||||
});
|
||||
|
||||
it('Auth.ensureHasCurrentUser() should fetch most current user if it exists in $window, currentUser or fetch it from /users/me', function() {
|
||||
Auth.login(sampleUser);
|
||||
|
||||
//Run Service Logic to Test
|
||||
var currUser = Auth.ensureHasCurrentUser(sampleUser);
|
||||
|
||||
expect(currUser).not.toEqual(null);
|
||||
expect(currUser).toEqualData(sampleUser);
|
||||
});
|
||||
|
||||
});
|
||||
}());
|
@ -0,0 +1,69 @@
|
||||
'use strict';
|
||||
|
||||
(function() {
|
||||
// Forms Controller Spec
|
||||
describe('Authorizer Service Tests', function() {
|
||||
// Initialize global variables
|
||||
var Authorizer;
|
||||
|
||||
var sampleUser = {
|
||||
firstName: 'Full',
|
||||
lastName: 'Name',
|
||||
email: 'test@test.com',
|
||||
username: 'test@test.com',
|
||||
password: 'password',
|
||||
provider: 'local',
|
||||
roles: ['user'],
|
||||
_id: 'ed873933b1f1dea0ce12fab9'
|
||||
};
|
||||
|
||||
|
||||
// The $resource service augments the response object with methods for updating and deleting the resource.
|
||||
// If we were to use the standard toEqual matcher, our tests would fail because the test values would not match
|
||||
// the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher.
|
||||
// When the toEqualData matcher compares two objects, it takes only object properties into
|
||||
// account and ignores methods.
|
||||
beforeEach(function() {
|
||||
jasmine.addMatchers({
|
||||
toEqualData: function(util, customEqualityTesters) {
|
||||
return {
|
||||
compare: function(actual, expected) {
|
||||
return {
|
||||
pass: angular.equals(actual, expected)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Load the main application module
|
||||
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||
|
||||
// The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
|
||||
// This allows us to inject a service but then attach it to a variable
|
||||
// with the same name as the service.
|
||||
beforeEach(inject(function(_Authorizer_) {
|
||||
Authorizer = _Authorizer_;
|
||||
}));
|
||||
|
||||
it('Authorizer.canAccess() should return expected values for \'admin\' and \'user\' accounts', function() {
|
||||
var sampleAdminUser = _.cloneDeep(sampleUser);
|
||||
sampleAdminUser.roles.push('admin');
|
||||
|
||||
//Run Service Logic to Test
|
||||
var authenticatorUser = new Authorizer(sampleUser);
|
||||
var authenticatorAdmin = new Authorizer(sampleAdminUser);
|
||||
|
||||
expect(authenticatorUser.canAccess('editForm')).toBe(true);
|
||||
expect(authenticatorUser.canAccess('editAdminSettings')).toBe(false);
|
||||
expect(authenticatorUser.canAccess('viewAdminSettings')).toBe(false);
|
||||
|
||||
expect(authenticatorAdmin.canAccess('editForm')).toBe(true);
|
||||
expect(authenticatorAdmin.canAccess('editAdminSettings')).toBe(true);
|
||||
expect(authenticatorAdmin.canAccess('viewAdminSettings')).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
}());
|
@ -0,0 +1,196 @@
|
||||
'use strict';
|
||||
|
||||
(function() {
|
||||
// Forms Controller Spec
|
||||
describe('User Service Tests', function() {
|
||||
// Initialize global variables
|
||||
var User,
|
||||
$httpBackend;
|
||||
|
||||
var sampleUser = {
|
||||
firstName: 'Full',
|
||||
lastName: 'Name',
|
||||
email: 'test@test.com',
|
||||
username: 'test@test.com',
|
||||
password: 'password',
|
||||
provider: 'local',
|
||||
roles: ['user'],
|
||||
_id: 'ed873933b1f1dea0ce12fab9'
|
||||
};
|
||||
|
||||
var sampleVerifyToken = 'WyuAIchArQnstkq5erx0kiTcTbBbgixYeBGtThFmRpcAJNQ2';
|
||||
var sampleForgotToken = 'c2e8f74455cdccc454dfef941ff315fa4f7b1f0a';
|
||||
var sampleCredentials = {
|
||||
username: sampleUser.username,
|
||||
password: sampleUser.password,
|
||||
};
|
||||
|
||||
var samplePasswordDetails = {
|
||||
newPassword: sampleUser.password,
|
||||
verifyPassword: sampleUser.password,
|
||||
};
|
||||
|
||||
// The $resource service augments the response object with methods for updating and deleting the resource.
|
||||
// If we were to use the standard toEqual matcher, our tests would fail because the test values would not match
|
||||
// the responses exactly. To solve the problem, we define a new toEqualData Jasmine matcher.
|
||||
// When the toEqualData matcher compares two objects, it takes only object properties into
|
||||
// account and ignores methods.
|
||||
beforeEach(function() {
|
||||
jasmine.addMatchers({
|
||||
toEqualData: function(util, customEqualityTesters) {
|
||||
return {
|
||||
compare: function(actual, expected) {
|
||||
return {
|
||||
pass: angular.equals(actual, expected)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Load the main application module
|
||||
beforeEach(module(ApplicationConfiguration.applicationModuleName));
|
||||
|
||||
beforeEach(module('stateMock'));
|
||||
|
||||
// Mock Users Service
|
||||
// beforeEach(module(function($provide) {
|
||||
// $provide.service('User', function($q) {
|
||||
// return {
|
||||
// getCurrent: function() {
|
||||
// var deferred = $q.defer();
|
||||
// deferred.resolve( JSON.stringify(sampleUser) );
|
||||
// return deferred.promise;
|
||||
// },
|
||||
// login: function(credentials) {
|
||||
// var deferred = $q.defer();
|
||||
// if( credentials.password === sampleUser.password && credentials.username === sampleUser.username){
|
||||
// deferred.resolve( JSON.stringify(sampleUser) );
|
||||
// }else {
|
||||
// deferred.resolve('Error: User could not be loggedin');
|
||||
// }
|
||||
|
||||
// return deferred.promise;
|
||||
// },
|
||||
// logout: function() {
|
||||
// var deferred = $q.defer();
|
||||
// deferred.resolve(null);
|
||||
// return deferred.promise;
|
||||
// },
|
||||
// signup: function(credentials) {
|
||||
// var deferred = $q.defer();
|
||||
// if( credentials.password === sampleUser.password && credentials.username === sampleUser.username){
|
||||
// deferred.resolve( JSON.stringify(sampleUser) );
|
||||
// }else {
|
||||
// deferred.resolve('Error: User could not be signed up');
|
||||
// }
|
||||
|
||||
// return deferred.promise;
|
||||
// }
|
||||
// };
|
||||
// });
|
||||
// }));
|
||||
|
||||
// The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
|
||||
// This allows us to inject a service but then attach it to a variable
|
||||
// with the same name as the service.
|
||||
beforeEach(inject(function(_$httpBackend_, _User_) {
|
||||
// Point global variables to injected services
|
||||
$httpBackend = _$httpBackend_;
|
||||
User = _User_;
|
||||
}));
|
||||
|
||||
it('User.login() should send a POST request to /auth/signin', function() {
|
||||
|
||||
//Set POST response
|
||||
$httpBackend.expect('POST', '/auth/signin', sampleCredentials).respond(200, sampleUser);
|
||||
|
||||
//Run Service Logic to Test
|
||||
User.login(sampleCredentials);
|
||||
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('User.logout() should logout user with /auth/signout', function() {
|
||||
|
||||
//Set POST response
|
||||
$httpBackend.expect('GET', '/auth/signout').respond(200);
|
||||
|
||||
//Run Service Logic to Test
|
||||
User.logout();
|
||||
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('User.getCurrent() should fetch user from /users/me', function() {
|
||||
|
||||
//Set POST response
|
||||
$httpBackend.expect('GET', '/users/me').respond(200, sampleUser);
|
||||
|
||||
//Run Service Logic to Test
|
||||
User.getCurrent();
|
||||
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
|
||||
it('User.signup() should signup user with /auth/signup', function() {
|
||||
|
||||
//Set POST response
|
||||
$httpBackend.expect('POST', '/auth/signup', sampleCredentials).respond(200);
|
||||
|
||||
//Run Service Logic to Test
|
||||
User.signup(sampleCredentials);
|
||||
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('User.resendVerifyEmail() should send POST request to /auth/verify', function() {
|
||||
|
||||
//Set POST response
|
||||
$httpBackend.expect('POST', '/auth/verify', {email: sampleUser.email}).respond(200);
|
||||
|
||||
//Run Service Logic to Test
|
||||
User.resendVerifyEmail(sampleUser.email);
|
||||
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('User.validateVerifyToken() should send GET request to /auth/verify/:token', function() {
|
||||
|
||||
//Set POST response
|
||||
$httpBackend.expect('GET', '/auth/verify/'+sampleVerifyToken).respond(200);
|
||||
|
||||
//Run Service Logic to Test
|
||||
expect(function(){ User.validateVerifyToken(sampleVerifyToken) }).not.toThrow();
|
||||
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('User.resetPassword() should send GET request to /auth/forgot/:token', function() {
|
||||
|
||||
//Set POST response
|
||||
$httpBackend.expect('GET', '/auth/password/'+sampleForgotToken).respond(200);
|
||||
|
||||
//Run Service Logic to Test
|
||||
User.resetPassword(samplePasswordDetails, sampleForgotToken);
|
||||
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it('User.askForPasswordReset() should send POST request to /auth/forgot', function() {
|
||||
|
||||
//Set POST response
|
||||
$httpBackend.expect('POST', '/auth/forgot', sampleCredentials).respond(200, sampleUser);
|
||||
|
||||
//Run Service Logic to Test
|
||||
User.askForPasswordReset(sampleCredentials);
|
||||
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
}());
|
Loading…
Reference in New Issue
Block a user