From ebec20c1de7aefa82ceb480f840a40842ac9d0bc Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Mon, 20 Jun 2016 15:35:41 -0700 Subject: [PATCH] got subdomains to work in production --- config/env/production.js | 3 +- gruntfile.js | 13 +- public/dist/form-application.js | 1219 +++++++++++++++++ public/dist/form-application.min.js | 3 + .../admin-form.client.controller.test.js | 256 ---- .../list-forms.client.controller.test.js | 224 --- .../submit-form.client.controller.test.js | 230 ---- .../configure-form.client.directive.test.js | 135 -- ...-form-submissions.client.directive.test.js | 200 --- .../edit-form.client.directive.test.js | 206 --- .../entry-page.client.directive.test.js | 93 -- .../field-icon.client.directive.test.js | 54 - .../directives/field.client.directive.test.js | 97 -- .../on-finish-render.client.directive.test.js | 46 - .../submit-form.client.directive.test.js | 203 --- .../current-form.client.service.test.js | 54 - .../time-counter.client.service.test.js | 28 - .../forms/tests/unit/stateMock.js | 32 - 18 files changed, 1232 insertions(+), 1864 deletions(-) create mode 100644 public/dist/form-application.js create mode 100644 public/dist/form-application.min.js delete mode 100644 public/form_modules/forms/tests/unit/controllers/admin-form.client.controller.test.js delete mode 100644 public/form_modules/forms/tests/unit/controllers/list-forms.client.controller.test.js delete mode 100644 public/form_modules/forms/tests/unit/controllers/submit-form.client.controller.test.js delete mode 100644 public/form_modules/forms/tests/unit/directives/configure-form.client.directive.test.js delete mode 100644 public/form_modules/forms/tests/unit/directives/edit-form-submissions.client.directive.test.js delete mode 100644 public/form_modules/forms/tests/unit/directives/edit-form.client.directive.test.js delete mode 100644 public/form_modules/forms/tests/unit/directives/entry-page.client.directive.test.js delete mode 100644 public/form_modules/forms/tests/unit/directives/field-icon.client.directive.test.js delete mode 100644 public/form_modules/forms/tests/unit/directives/field.client.directive.test.js delete mode 100644 public/form_modules/forms/tests/unit/directives/on-finish-render.client.directive.test.js delete mode 100644 public/form_modules/forms/tests/unit/directives/submit-form.client.directive.test.js delete mode 100644 public/form_modules/forms/tests/unit/services/current-form.client.service.test.js delete mode 100644 public/form_modules/forms/tests/unit/services/time-counter.client.service.test.js delete mode 100644 public/form_modules/forms/tests/unit/stateMock.js diff --git a/config/env/production.js b/config/env/production.js index c60edf43..170830a1 100755 --- a/config/env/production.js +++ b/config/env/production.js @@ -24,7 +24,8 @@ module.exports = { }, assets: { css: 'public/dist/application.min.css', - js: 'public/dist/application.min.js' + js: 'public/dist/application.min.js', + form_js: 'public/dist/form-application.min.js' }, facebook: { clientID: process.env.FACEBOOK_ID || 'APP_ID', diff --git a/gruntfile.js b/gruntfile.js index 711ef147..003f9a0c 100755 --- a/gruntfile.js +++ b/gruntfile.js @@ -12,8 +12,8 @@ module.exports = function(grunt) { serverJS: ['gruntfile.js', 'server.js', 'config/**/*.js', 'app/**/*.js', '!app/tests/'], clientViews: ['public/modules/**/views/**/*.html', '!public/modules/**/demo/**/*.html', '!public/modules/**/dist/**/*.html', '!public/modules/**/node_modules/**/*.html'], - clientJS: ['public/js/*.js', 'public/modules/**/*.js', '!public/modules/**/gruntfile.js', '!public/modules/**/demo/**/*.js', '!public/modules/**/dist/**/*.js', '!public/modules/**/node_modules/**/*.js'], - clientCSS: ['public/modules/**/*.css', '!public/modules/**/demo/**/*.css', '!public/modules/**/dist/**/*.css', '!public/modules/**/node_modules/**/*.css'], + clientJS: ['public/js/*.js', 'public/form_modules/**/*.js', 'public/modules/**/*.js', '!public/modules/**/gruntfile.js', '!public/modules/**/demo/**/*.js', '!public/modules/**/dist/**/*.js', '!public/modules/**/node_modules/**/*.js'], + clientCSS: ['public/modules/**/*.css', 'public/form_modules/**/*.css', '!public/modules/**/demo/**/*.css', '!public/modules/**/dist/**/*.css', '!public/modules/**/node_modules/**/*.css'], serverTests: ['app/tests/**/*.js'], clientTests: ['public/modules/**/tests/*.js', '!public/modules/**/demo/**/*.js', '!public/modules/**/dist/**/*.js', '!public/modules/**/node_modules/**/*.js'] @@ -97,7 +97,8 @@ module.exports = function(grunt) { mangle: false }, files: { - 'public/dist/application.min.js': 'public/dist/application.js' + 'public/dist/application.min.js': 'public/dist/application.js', + 'public/dist/form-application.min.js': 'public/dist/form-application.js' } } }, @@ -134,7 +135,8 @@ module.exports = function(grunt) { ngAnnotate: { production: { files: { - 'public/dist/application.js': '<%= applicationJavaScriptFiles %>' + 'public/dist/application.js': '<%= applicationJavaScriptFiles %>', + 'public/dist/form-application.js': '<%= formApplicationJavaScriptFiles %>' } } }, @@ -177,7 +179,7 @@ module.exports = function(grunt) { unit: { configFile: 'karma.conf.js', singleRun: true - } + } }, protractor: { options: { @@ -286,6 +288,7 @@ module.exports = function(grunt) { var config = require('./config/config'); grunt.config.set('applicationJavaScriptFiles', config.assets.js); + grunt.config.set('formApplicationJavaScriptFiles', config.assets.form_js); grunt.config.set('applicationCSSFiles', config.assets.css); }); diff --git a/public/dist/form-application.js b/public/dist/form-application.js new file mode 100644 index 00000000..fa07d851 --- /dev/null +++ b/public/dist/form-application.js @@ -0,0 +1,1219 @@ +'use strict'; + +// Init the application configuration module for AngularJS application +var ApplicationConfiguration = (function() { + // Init module configuration options + var applicationModuleName = 'NodeForm'; + var applicationModuleVendorDependencies = ['duScroll', 'ui.select', 'cgBusy', 'ngSanitize', 'vButton', 'ngResource', 'NodeForm.templates', 'ui.router', 'ui.bootstrap', 'ui.utils', 'pascalprecht.translate', 'ng.deviceDetector']; + + // Add a new vertical module + var registerModule = function(moduleName, dependencies) { + // Create angular module + angular.module(moduleName, dependencies || []); + + // Add the module to the AngularJS configuration file + angular.module(applicationModuleName).requires.push(moduleName); + }; + + return { + applicationModuleName: applicationModuleName, + applicationModuleVendorDependencies: applicationModuleVendorDependencies, + registerModule: registerModule + }; +})(); + +'use strict'; + +//Start by defining the main module and adding the module dependencies +angular.module(ApplicationConfiguration.applicationModuleName, ApplicationConfiguration.applicationModuleVendorDependencies); + +// Setting HTML5 Location Mode +angular.module(ApplicationConfiguration.applicationModuleName).config(['$locationProvider', + function($locationProvider) { + $locationProvider.hashPrefix('!'); + } +]); + +//Permission Constants +angular.module(ApplicationConfiguration.applicationModuleName).constant('APP_PERMISSIONS', { + viewAdminSettings: 'viewAdminSettings', + editAdminSettings: 'editAdminSettings', + editForm: 'editForm', + viewPrivateForm: 'viewPrivateForm' +}); + +//User Role constants +angular.module(ApplicationConfiguration.applicationModuleName).constant('USER_ROLES', { + admin: 'admin', + normal: 'user', + superuser: 'superuser' +}); + +//form url +angular.module(ApplicationConfiguration.applicationModuleName).constant('FORM_URL', '/forms/:formId'); + +//Then define the init function for starting up the application +angular.element(document).ready(function() { + //Fixing facebook bug with redirect + if (window.location.hash === '#_=_') window.location.hash = '#!'; + + //Then init the app + angular.bootstrap(document, [ApplicationConfiguration.applicationModuleName]); +}); + +angular.module('NodeForm.templates', []).run(['$templateCache', function($templateCache) { + "use strict"; + $templateCache.put("modules/core/views/header.client.view.html", + "
"); + $templateCache.put("modules/forms/admin/views/admin-form.client.view.html", + "
"); + $templateCache.put("modules/forms/admin/views/list-forms.client.view.html", + "

{{ 'CREATE_A_NEW_FORM' | translate }}
Name
Language

{{ 'CREATED_ON' | translate }}
"); + $templateCache.put("modules/forms/base/views/submit-form.client.view.html", + "
"); + $templateCache.put("modules/forms/admin/views/adminTabs/analyze.html", + ""); + $templateCache.put("modules/forms/admin/views/adminTabs/configure.html", + ""); + $templateCache.put("modules/forms/admin/views/adminTabs/create.html", + ""); + $templateCache.put("modules/forms/admin/views/adminTabs/design.html", + "

{{ 'DESIGN_HEADER' | translate }}

{{ 'DESIGN_HEADER' | translate }}

{{ 'BACKGROUND_COLOR' | translate }}
{{ 'QUESTION_TEXT_COLOR' | translate }}
{{ 'ANSWER_TEXT_COLOR' | translate }}
{{ 'BTN_BACKGROUND_COLOR' | translate }}
{{ 'BTN_TEXT_COLOR' | translate }}
"); + $templateCache.put("modules/forms/admin/views/directiveViews/cgBusy/update-form-message-TypeA.html", + "
{{$message}}
"); + $templateCache.put("modules/forms/admin/views/directiveViews/cgBusy/update-form-message-TypeB.html", + "
{{$message}}
"); + $templateCache.put("modules/forms/admin/views/directiveViews/form/configure-form.client.view.html", + "

{{ 'PDF Generation/EMR' | translate }}

{{ 'PDF Generation/EMR' | translate }}

{{ 'SAVE_PDF_SUBMISSIONS' | translate }}
{{ 'UPLOAD_YOUR_PDF' | translate }}
{{myform.pdf.name}}
{{ 'UPLOAD_YOUR_PDF' | translate }}
{{ 'Autogenerate Form?' | translate }}


{{ 'ADVANCED_SETTINGS' | translate }}

{{ 'ADVANCED_SETTINGS' | translate }}

{{ 'FORM_NAME' | translate }}
{{ 'FORM_STATUS' | translate }}
{{ 'GA_TRACKING_CODE' | translate }}
Language
* required
{{ 'DISPLAY_FOOTER' | translate }}
Display Start Page?
"); + $templateCache.put("modules/forms/admin/views/directiveViews/form/edit-form.client.view.html", + "

{{ 'ADD_FIELD_LG' | translate }}

{{ 'ADD_FIELD_MD' | translate }}

{{ 'ADD_FIELD_SM' | translate }}

Start Page

{{ 'PREVIEW_START_PAGE' | translate }}

    {{myform.startPage.introTitle}}

    {{myform.startPage.introParagraph}}

{{ 'EDIT_START_PAGE' | translate }}


{{ 'INTRO_TITLE' | translate }}:
{{ 'INTRO_PARAGRAPH' | translate }}:
{{ 'INTRO_BTN' | translate }}:


Buttons:
{{ 'BUTTON_TEXT' | translate }}
{{ 'BUTTON_LINK' | translate }}


{{field.title}} *

{{ 'PREVIEW_FIELD' | translate }}


{{ 'EDIT_FIELD' | translate }}


{{ 'QUESTION_TITLE' | translate }}:

{{ 'QUESTION_DESCRIPTION' | translate }}:

{{ 'OPTIONS' | translate }}:

{{ 'NUM_OF_STEPS' | translate }}

Shape:

Required:
Disabled:

{{ 'CLICK_FIELDS_FOOTER' | translate }}


"); + $templateCache.put("modules/forms/admin/views/directiveViews/form/edit-submissions-form.client.view.html", + "
Overview Analytics
{{ 'TOTAL_VIEWS' | translate }}
{{ 'RESPONSES' | translate }}
{{ 'COMPLETION_RATE' | translate }}
{{ 'AVERAGE_TIME_TO_COMPLETE' | translate }}
{{myform.analytics.views}}
{{myform.analytics.submissions}}
{{myform.analytics.conversionRate | number:0}}%
{{AverageTimeElapsed | secondsToDateTime | date:'mm:ss'}}
Device Analytics
{{ 'DESKTOP_AND_LAPTOP' | translate }}
{{ 'TABLETS' | translate }}
{{ 'PHONES' | translate }}
{{ 'OTHER' | translate }}
{{ 'UNIQUE_VISITS' | translate }}
{{DeviceStatistics.desktop.visits}}
{{ 'UNIQUE_VISITS' | translate }}
{{DeviceStatistics.tablet.visits}}
{{ 'UNIQUE_VISITS' | translate }}
{{DeviceStatistics.tablet.visits}}
{{ 'UNIQUE_VISITS' | translate }}
{{DeviceStatistics.other.visits}}
{{ 'RESPONSES' | translate }}
{{DeviceStatistics.desktop.responses}}
{{ 'RESPONSES' | translate }}
{{DeviceStatistics.tablet.responses}}
{{ 'RESPONSES' | translate }}
{{DeviceStatistics.phone.responses}}
{{ 'RESPONSES' | translate }}
{{DeviceStatistics.other.responses}}
{{ 'COMPLETION_RATE' | translate }}
{{DeviceStatistics.desktop.completion}}
{{ 'COMPLETION_RATE' | translate }}
{{DeviceStatistics.tablet.completion}}
{{ 'COMPLETION_RATE' | translate }}
{{DeviceStatistics.phone.completion}}
{{ 'COMPLETION_RATE' | translate }}
{{DeviceStatistics.other.completion}}
{{ 'AVERAGE_TIME_TO_COMPLETE' | translate }}
{{DeviceStatistics.desktop.average_time | secondsToDateTime | date:'mm:ss'}}
{{ 'AVERAGE_TIME_TO_COMPLETE' | translate }}
{{DeviceStatistics.tablet.average_time | secondsToDateTime | date:'mm:ss'}}
{{ 'AVERAGE_TIME_TO_COMPLETE' | translate }}
{{DeviceStatistics.phone.average_time | secondsToDateTime | date:'mm:ss'}}
{{ 'AVERAGE_TIME_TO_COMPLETE' | translate }}
{{DeviceStatistics.other.average_time | secondsToDateTime | date:'mm:ss'}}
Field Analytics
{{ 'FIELD_TITLE' | translate }}
{{ 'FIELD_VIEWS' | translate }}
{{ 'FIELD_RESPONSES' | translate }}
{{ 'FIELD_DROPOFF' | translate }}
{{fieldStats.field.title}}
{{fieldStats.totalViews}}
{{fieldStats.responses}}
{{fieldStats.continueRate}}%

Responses Table
#{{value.title}}{{ 'PERCENTAGE_COMPLETE' | translate }}{{ 'TIME_ELAPSED' | translate }}{{ 'DEVICE' | translate }}{{ 'LOCATION' | translate }}{{ 'IP_ADDRESS' | translate }}{{ 'DATE_SUBMITTED' | translate }} (UTC){{ 'GENERATED_PDF' | translate }}
{{$index+1}}{{field.fieldValue}}{{row.percentageComplete}}%{{row.timeElapsed | secondsToDateTime | date:'mm:ss'}}{{row.device.name}}, {{row.device.type}}{{row.geoLocation.city}}, {{row.geoLocation.country_name}}{{row.ipAddr}}{{row.created | date:'yyyy-MM-dd HH:mm:ss'}}{{ 'GENERATED_PDF' | translate }}
"); + $templateCache.put("modules/forms/base/views/directiveViews/entryPage/startPage.html", + "

{{pageData.introTitle}}

{{pageData.introParagraph}}

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

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{field.description}}

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

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{field.description}}


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

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{field.file.originalname}}
{{ UPLOAD_FILE | translate }}
"); + $templateCache.put("modules/forms/base/views/directiveViews/field/hidden.html", + ""); + $templateCache.put("modules/forms/base/views/directiveViews/field/legal.html", + "

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}


{{field.description}}


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

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{field.description}}


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

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{field.description}}

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

{{field.title}}

{{field.description}}

{{field.description}}


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

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{ 'NEWLINE' | translate }}

{{field.description}}

Press SHIFT+ENTER to add a newline
{{ 'ENTER' | translate }}
"); + $templateCache.put("modules/forms/base/views/directiveViews/field/textfield.html", + "

{{index+1}} {{field.title}} ({{ 'OPTIONAL' | translate }})

{{field.description}}

{{ 'ENTER' | translate }}
"); + $templateCache.put("modules/forms/base/views/directiveViews/field/yes_no.html", + "

{{index+1}} {{field.title}} {{ 'OPTIONAL' | translate }}

{{field.description}}


"); + $templateCache.put("modules/forms/base/views/directiveViews/form/submit-form.client.view.html", + "

{{myform.startPage.introTitle}}

{{myform.startPage.introParagraph}}

{{ 'COMPLETING_NEEDED' | translate:translateAdvancementData }}
{{ 'ENTER' | translate }}

{{ 'ADVANCEMENT' | translate:translateAdvancementData }}

{{ 'FORM_SUCCESS' | translate }}

"); + $templateCache.put("modules/users/views/authentication/access-denied.client.view.html", + "

{{ 'ACCESS_DENIED_TEXT' | translate }}

{{ 'SIGNIN_BTN' | translate }}
"); + $templateCache.put("modules/users/views/authentication/signin.client.view.html", + "

Sign into your account

Error:
  or  {{ 'SIGNUP_BTN' | translate }}
"); + $templateCache.put("modules/users/views/authentication/signup-success.client.view.html", + "

{{ 'SUCCESS_HEADER' | translate }}

{{ 'SUCCESS_TEXT' | translate }}

{{ 'NOT_ACTIVATED_YET' | translate }}



{{ 'BEFORE_YOU_CONTINUE' | translate }} polydaic@gmail.com

"); + $templateCache.put("modules/users/views/authentication/signup.client.view.html", + "

Signup with your email

Couldn't complete registration due to errors:
{{ 'LANGUAGE_LABEL' | translate }}

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

{{ 'PASSWORD_RESTORE_HEADER' | translate }}

{{ 'ENTER_YOUR_EMAIL' | translate }}

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

{{ 'PASSWORD_RESET_INVALID' | translate }}

{{ 'ASK_FOR_NEW_PASSWORD' | translate }}
"); + $templateCache.put("modules/users/views/password/reset-password-success.client.view.html", + "

{{ 'PASSWORD_RESET_SUCCESS' | translate }}

{{ 'CONTINUE_TO_LOGIN' | translate }}
"); + $templateCache.put("modules/users/views/password/reset-password.client.view.html", + "

Reset your password

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

Change your password


{{ 'PASSWORD_CHANGE_SUCCESS' | translate }}
"); + $templateCache.put("modules/users/views/settings/edit-profile.client.view.html", + "1

Edit your profile

{{ 'PROFILE_SAVE_SUCCESS' | translate }}
{{ 'PROFILE_SAVE_ERROR' | translate }}
{{ 'FIRST_NAME_LABEL' | translate }}
Last Name

{{ 'LANGUAGE_LABEL' | translate }}
Username
{{ 'EMAIL_LABEL' | translate }}
"); + $templateCache.put("modules/users/views/settings/social-accounts.client.view.html", + "

Connected social accounts:

Connect other social accounts:

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

Resend your account verification email

Enter your account email.

{{error}}

Verification Email has been Sent

{{ 'VERIFICATION_EMAIL_SENT' | translate }} {{username}}.
{{ 'NOT_ACTIVATED_YET' | translate }}

{{ 'CHECK_YOUR_EMAIL' | translate }} polydaic@gmail.com

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

{{ 'CONTINUE_TO_LOGIN' | translate }}

{{ 'VERIFY_ERROR' | translate }}

{{ 'REVERIFY_ACCOUNT_LINK' | translate }} {{ 'SIGNIN_BTN' | translate }}
"); +}]); + +'use strict'; + +// Use Application configuration module to register a new module +ApplicationConfiguration.registerModule('view-form', [ + 'ngFileUpload', 'ui.router.tabs', 'ui.date', 'ui.sortable', + 'angular-input-stars', 'pascalprecht.translate' +]);//, 'colorpicker.module' @TODO reactivate this module + +'use strict'; + +angular.module('view-form').config(['$translateProvider', function ($translateProvider) { + + $translateProvider.translations('english', { + FORM_SUCCESS: 'Form entry successfully submitted!', + REVIEW: 'Review', + BACK_TO_FORM: 'Go back to Form', + EDIT_FORM: 'Edit this TellForm', + CREATE_FORM: 'Create this TellForm', + ADVANCEMENT: '{{done}} out of {{total}} answered', + CONTINUE_FORM: 'Continue to Form', + REQUIRED: 'required', + COMPLETING_NEEDED: '{{answers_not_completed}} answer(s) need completing', + OPTIONAL: 'optional', + ERROR_EMAIL_INVALID: 'Please enter a valid email address', + ERROR_NOT_A_NUMBER: 'Please enter valid numbers only', + ERROR_URL_INVALID: 'Please a valid url', + OK: 'OK', + ENTER: 'press ENTER', + YES: 'Yes', + NO: 'No', + NEWLINE: 'press SHIFT+ENTER to create a newline', + CONTINUE: 'Continue', + LEGAL_ACCEPT: 'I accept', + LEGAL_NO_ACCEPT: 'I don’t accept', + DELETE: 'Delete', + CANCEL: 'Cancel', + SUBMIT: 'Submit', + UPLOAD_FILE: 'Upload your File', + }); + + $translateProvider.preferredLanguage('english') + .fallbackLanguage('english') + .useSanitizeValueStrategy('escape'); + +}]); + +'use strict'; + +angular.module('view-form').config(['$translateProvider', function ($translateProvider) { + + $translateProvider.translations('french', { + FORM_SUCCESS: 'Votre formulaire a été enregistré!', + REVIEW: 'Incomplet', + BACK_TO_FORM: 'Retourner au formulaire', + EDIT_FORM: 'Éditer le Tellform', + CREATE_FORM: 'Créer un TellForm', + ADVANCEMENT: '{{done}} complétés sur {{total}}', + CONTINUE_FORM: 'Aller au formulaire', + REQUIRED: 'obligatoire', + COMPLETING_NEEDED: '{{answers_not_completed}} réponse(s) doive(nt) être complétée(s)', + OPTIONAL: 'facultatif', + ERROR_EMAIL_INVALID: 'Merci de rentrer une adresse mail valide', + ERROR_NOT_A_NUMBER: 'Merce de ne rentrer que des nombres', + ERROR_URL_INVALID: 'Merci de rentrer une url valide', + OK: 'OK', + ENTER: 'presser ENTRÉE', + YES: 'Oui', + NO: 'Non', + NEWLINE: 'presser SHIFT+ENTER pour créer une nouvelle ligne', + CONTINUE: 'Continuer', + LEGAL_ACCEPT: 'J’accepte', + LEGAL_NO_ACCEPT: 'Je n’accepte pas', + DELETE: 'Supprimer', + CANCEL: 'Réinitialiser', + SUBMIT: 'Enregistrer', + UPLOAD_FILE: 'Envoyer un fichier', + Y: 'O', + N: 'N', + }); + +}]); + +'use strict'; + +angular.module('view-form').config(['$translateProvider', function ($translateProvider) { + + $translateProvider.translations('german', { + FORM_SUCCESS: 'Ihre Angaben wurden gespeichert.', + REVIEW: 'Unvollständig', + BACK_TO_FORM: 'Zurück zum Formular', + EDIT_FORM: '', + CREATE_FORM: '', + ADVANCEMENT: '{{done}} von {{total}} beantwortet', + CONTINUE_FORM: 'Zum Formular', + REQUIRED: 'verpflichtend', + COMPLETING_NEEDED: 'Es fehlen/fehtl noch {{answers_not_completed}} Antwort(en)', + OPTIONAL: 'fakultativ', + ERROR_EMAIL_INVALID: 'Bitte gültige Mailadresse eingeben', + ERROR_NOT_A_NUMBER: 'Bitte nur Zahlen eingeben', + ERROR_URL_INVALID: 'Bitte eine gültige URL eingeben', + OK: 'Okay', + ENTER: 'Eingabetaste drücken', + YES: 'Ja', + NO: 'Nein', + NEWLINE: 'Für eine neue Zeile SHIFT+ENTER drücken', + CONTINUE: 'Weiter', + LEGAL_ACCEPT: 'I accept', + LEGAL_NO_ACCEPT: 'I don’t accept', + DELETE: 'Entfernen', + CANCEL: 'Canceln', + SUBMIT: 'Speichern', + UPLOAD_FILE: 'Datei versenden', + Y: 'J', + N: 'N', + }); + +}]); + +'use strict'; + +angular.module('view-form').config(['$translateProvider', function ($translateProvider) { + + $translateProvider.translations('italian', { + FORM_SUCCESS: 'Il formulario è stato inviato con successo!', + REVIEW: 'Incompleto', + BACK_TO_FORM: 'Ritorna al formulario', + EDIT_FORM: '', + CREATE_FORM: '', + ADVANCEMENT: '{{done}} su {{total}} completate', + CONTINUE_FORM: 'Vai al formulario', + REQUIRED: 'obbligatorio', + COMPLETING_NEEDED: '{{answers_not_completed}} risposta/e deve/ono essere completata/e', + OPTIONAL: 'opzionale', + ERROR_EMAIL_INVALID: 'Si prega di inserire un indirizzo email valido', + ERROR_NOT_A_NUMBER: 'Si prega di inserire solo numeri', + ERROR_URL_INVALID: 'Grazie per inserire un URL valido', + OK: 'OK', + ENTER: 'premere INVIO', + YES: 'Sì', + NO: 'No', + NEWLINE: 'premere SHIFT+INVIO per creare una nuova linea', + CONTINUE: 'Continua', + LEGAL_ACCEPT: 'I accept', + LEGAL_NO_ACCEPT: 'I don’t accept', + DELETE: 'Cancella', + CANCEL: 'Reset', + SUBMIT: 'Registra', + UPLOAD_FILE: 'Invia un file', + Y: 'S', + N: 'N', + }); + +}]); + +'use strict'; + +angular.module('view-form').config(['$translateProvider', function ($translateProvider) { + + $translateProvider.translations('spanish', { + FORM_SUCCESS: '¡El formulario ha sido enviado con éxito!', + REVIEW: 'Revisar', + BACK_TO_FORM: 'Regresar al formulario', + EDIT_FORM: '', + CREATE_FORM: '', + ADVANCEMENT: '{{done}} de {{total}} contestadas', + CONTINUE_FORM: 'Continuar al formulario', + REQUIRED: 'Información requerida', + COMPLETING_NEEDED: '{{answers_not_completed}} respuesta(s) necesita(n) ser completada(s)', + OPTIONAL: 'Opcional', + ERROR_EMAIL_INVALID: 'Favor de proporcionar un correo electrónico válido', + ERROR_NOT_A_NUMBER: 'Por favor, introduzca sólo números válidos', + ERROR_URL_INVALID: 'Favor de proporcionar un url válido', + OK: 'OK', + ENTER: 'pulse INTRO', + YES: 'Si', + NO: 'No', + NEWLINE: 'presione SHIFT+INTRO para crear una nueva línea', + CONTINUE: 'Continuar', + LEGAL_ACCEPT: 'I accept', + LEGAL_NO_ACCEPT: 'I don’t accept', + DELETE: 'Eliminar', + CANCEL: 'Cancelar', + SUBMIT: 'Registrar', + UPLOAD_FILE: 'Cargar el archivo', + Y: 'S', + N: 'N' + }); + +}]); + +'use strict'; + +// Configuring the Forms drop-down menus +angular.module('view-form').filter('formValidity', + function(){ + return function(formObj){ + if(formObj && formObj.form_fields && formObj.visible_form_fields){ + + //get keys + var formKeys = Object.keys(formObj); + + //we only care about things that don't start with $ + var fieldKeys = formKeys.filter(function(key){ + return key[0] !== '$'; + }); + + var fields = formObj.form_fields; + + var valid_count = fields.filter(function(field){ + if(typeof field === 'object' && field.fieldType !== 'statement' && field.fieldType !== 'rating'){ + return !!(field.fieldValue); + } + + }).length; + return valid_count - (formObj.form_fields.length - formObj.visible_form_fields.length); + } + return 0; + }; +}); + +'use strict'; + +// Setting up route +angular.module('view-form').config(['$stateProvider', + + function($stateProvider) { + // Forms state routing + $stateProvider. + state('submitForm', { + url: '/forms/:formId', + templateUrl: '/static/form_modules/forms/base/views/submit-form.client.view.html', + resolve: { + Forms: 'Forms', + myForm: ["Forms", "$stateParams", function (Forms, $stateParams) { + return Forms.get({formId: $stateParams.formId}).$promise; + }] + }, + controller: 'SubmitFormController', + controllerAs: 'ctrl' + }) + } +]); + +(function () { + 'use strict'; + + // Create the SendVisitorData service + angular + .module('view-form') + .factory('SendVisitorData', SendVisitorData); + + SendVisitorData.$inject = ['Socket', '$state']; + + function SendVisitorData(Socket, $state) { + + // Create a controller method for sending visitor data + function send(form, lastActiveIndex, timeElapsed) { + + // Create a new message object + var visitorData = { + referrer: document.referrer, + isSubmitted: form.submitted, + formId: form._id, + lastActiveField: form.form_fields[lastActiveIndex]._id, + timeElapsed: timeElapsed + }; + Socket.emit('form-visitor-data', visitorData); + } + + function init(){ + // Make sure the Socket is connected + if (!Socket.socket) { + Socket.connect(); + } + } + + var service = { + send: send + }; + + init(); + return service; + + } +}()); + + +'use strict'; + +angular.module('view-form').directive('keyToOption', function(){ + return { + restrict: 'A', + scope: { + field: '=' + }, + link: function($scope, $element, $attrs, $select) { + $element.bind('keydown keypress', function(event) { + + var keyCode = event.which || event.keyCode; + var index = parseInt(String.fromCharCode(keyCode))-1; + //console.log($scope.field); + + if (index < $scope.field.fieldOptions.length) { + event.preventDefault(); + $scope.$apply(function () { + $scope.field.fieldValue = $scope.field.fieldOptions[index].option_value; + }); + } + + }); + } + }; +}); + +'use strict'; + +angular.module('view-form').directive('keyToTruthy', ['$rootScope', function($rootScope){ + return { + restrict: 'A', + scope: { + field: '=' + }, + link: function($scope, $element, $attrs) { + $element.bind('keydown keypress', function(event) { + var keyCode = event.which || event.keyCode; + var truthyKeyCode = $attrs.keyCharTruthy.charCodeAt(0) - 32; + var falseyKeyCode = $attrs.keyCharFalsey.charCodeAt(0) - 32; + + if(keyCode === truthyKeyCode ) { + event.preventDefault(); + $scope.$apply(function() { + $scope.field.fieldValue = 'true'; + }); + }else if(keyCode === falseyKeyCode){ + event.preventDefault(); + $scope.$apply(function() { + $scope.field.fieldValue = 'false'; + }); + } + }); + } + }; +}]); + + +'use strict'; + +// Configuring the Forms drop-down menus +angular.module('view-form') +.filter('formValidity', function(){ + return function(formObj){ + if(formObj && formObj.form_fields && formObj.visible_form_fields){ + + //get keys + var formKeys = Object.keys(formObj); + + //we only care about things that don't start with $ + var fieldKeys = formKeys.filter(function(key){ + return key[0] !== '$'; + }); + + var fields = formObj.form_fields; + + var valid_count = fields.filter(function(field){ + if(typeof field === 'object' && field.fieldType !== 'statement' && field.fieldType !== 'rating'){ + return !!(field.fieldValue); + } + + }).length; + return valid_count - (formObj.form_fields.length - formObj.visible_form_fields.length); + } + return 0; + }; +}); + +angular.module('view-form').value('supportedFields', [ + 'textfield', + 'textarea', + 'date', + 'dropdown', + 'hidden', + 'password', + 'radio', + 'legal', + 'statement', + 'rating', + 'yes_no', + 'number', + 'natural' +]); + +'use strict'; + +// SubmitForm controller +angular.module('view-form').controller('SubmitFormController', [ + '$scope', '$rootScope', '$state', '$translate', 'myForm', + function($scope, $rootScope, $state, $translate, myForm) { + $scope.myform = myForm; + + $translate.use(myForm.language); + + } +]); + +'use strict'; + +angular.module('view-form').directive('fieldIconDirective', function() { + + return { + template: '', + restrict: 'E', + scope: { + typeName: '@' + }, + controller: ["$scope", function($scope){ + var iconTypeMap = { + 'textfield': 'fa fa-pencil-square-o', + 'dropdown': 'fa fa-th-list', + 'date': 'fa fa-calendar', + 'checkbox': 'fa fa-check-square-o', + 'radio': 'fa fa-dot-circle-o', + 'email': 'fa fa-envelope-o', + 'textarea': 'fa fa-pencil-square', + 'legal': 'fa fa-legal', + 'file': 'fa fa-cloud-upload', + 'rating': 'fa fa-star-half-o', + 'link': 'fa fa-link', + 'scale': 'fa fa-sliders', + 'stripe': 'fa fa-credit-card', + 'statement': 'fa fa-quote-left', + 'yes_no': 'fa fa-toggle-on', + 'number': 'fa fa-slack' + }; + $scope.typeIcon = iconTypeMap[$scope.typeName]; + }] + }; +}); + +'use strict'; + +// coffeescript's for in loop +var __indexOf = [].indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (i in this && this[i] === item) return i; + } + return -1; +}; + +angular.module('view-form').directive('fieldDirective', ['$http', '$compile', '$rootScope', '$templateCache', 'supportedFields', + function($http, $compile, $rootScope, $templateCache, supportedFields) { + + var getTemplateUrl = function(fieldType) { + var type = fieldType; + + var supported_fields = [ + 'textfield', + 'textarea', + 'date', + 'dropdown', + 'hidden', + 'password', + 'radio', + 'legal', + 'statement', + 'rating', + 'yes_no', + 'number', + 'natural' + ]; + + var templateUrl = 'modules/forms/base/views/directiveViews/field/'; + + if (__indexOf.call(supportedFields, type) >= 0) { + templateUrl = templateUrl+type+'.html'; + } + return $templateCache.get(templateUrl); + }; + + return { + template: '
{{field.title}}
', + restrict: 'E', + scope: { + field: '=', + required: '&', + design: '=', + index: '=', + forms: '=' + }, + link: function(scope, element) { + + $rootScope.chooseDefaultOption = scope.chooseDefaultOption = function(type) { + if(type === 'yes_no'){ + scope.field.fieldValue = 'true'; + }else if(type === 'rating'){ + scope.field.fieldValue = 0; + }else if(scope.field.fieldType === 'radio'){ + console.log(scope.field); + scope.field.fieldValue = scope.field.fieldOptions[0].option_value; + console.log(scope.field.fieldValue); + }else if(type === 'legal'){ + scope.field.fieldValue = 'true'; + $rootScope.nextField(); + } + }; + + scope.setActiveField = $rootScope.setActiveField; + + //Set format only if field is a date + if(scope.field.fieldType === 'date'){ + scope.dateOptions = { + changeYear: true, + changeMonth: true, + altFormat: 'mm/dd/yyyy', + yearRange: '1900:-0', + defaultDate: 0 + }; + } + + var fieldType = scope.field.fieldType; + + if(scope.field.fieldType === 'number' || scope.field.fieldType === 'textfield' || scope.field.fieldType === 'email' || scope.field.fieldType === 'link'){ + switch(scope.field.fieldType){ + case 'textfield': + scope.field.input_type = 'text'; + break; + case 'email': + scope.field.input_type = 'email'; + scope.field.placeholder = 'joesmith@example.com'; + break; + case 'number': + scope.field.input_type = 'text'; + scope.field.validateRegex = /^-?\d+$/; + break; + default: + scope.field.input_type = 'url'; + scope.field.placeholder = 'http://example.com'; + break; + } + fieldType = 'textfield'; + } + var template = getTemplateUrl(fieldType); + element.html(template).show(); + var output = $compile(element.contents())(scope); + } + }; +}]); + +'use strict'; + +//TODO: DAVID: Need to refactor this +angular.module('view-form').directive('onEnterKey', ['$rootScope', function($rootScope){ + return { + restrict: 'A', + link: function($scope, $element, $attrs) { + $element.bind('keydown keypress', function(event) { + + var keyCode = event.which || event.keyCode; + + var onEnterKeyDisabled = false; + if($attrs.onEnterKeyDisabled !== null) onEnterKeyDisabled = $attrs.onEnterKeyDisabled; + + if(keyCode === 13 && !event.shiftKey && !onEnterKeyDisabled) { + event.preventDefault(); + $rootScope.$apply(function() { + $rootScope.$eval($attrs.onEnterKey); + }); + } + }); + } + }; +}]).directive('onTabKey', ['$rootScope', function($rootScope){ + return { + restrict: 'A', + link: function($scope, $element, $attrs) { + $element.bind('keydown keypress', function(event) { + + var keyCode = event.which || event.keyCode; + + if(keyCode === 9 && !event.shiftKey) { + + event.preventDefault(); + $rootScope.$apply(function() { + $rootScope.$eval($attrs.onTabKey); + }); + } + }); + } + }; +}]).directive('onEnterOrTabKey', ['$rootScope', function($rootScope){ + return { + restrict: 'A', + link: function($scope, $element, $attrs) { + $element.bind('keydown keypress', function(event) { + + var keyCode = event.which || event.keyCode; + + if((keyCode === 13 || keyCode === 9) && !event.shiftKey) { + event.preventDefault(); + $rootScope.$apply(function() { + $rootScope.$eval($attrs.onEnterOrTabKey); + }); + } + }); + } + }; +}]).directive('onTabAndShiftKey', ['$rootScope', function($rootScope){ + return { + restrict: 'A', + link: function($scope, $element, $attrs) { + $element.bind('keydown keypress', function(event) { + + var keyCode = event.which || event.keyCode; + + if(keyCode === 9 && event.shiftKey) { + event.preventDefault(); + $rootScope.$apply(function() { + $rootScope.$eval($attrs.onTabAndShiftKey); + }); + } + }); + } + }; +}]); + +'use strict'; + +angular.module('view-form').directive('onFinishRender', ["$rootScope", "$timeout", function ($rootScope, $timeout) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + + //Don't do anything if we don't have a ng-repeat on the current element + if(!element.attr('ng-repeat') && !element.attr('data-ng-repeat')){ + return; + } + + var broadcastMessage = attrs.onFinishRender || 'ngRepeat'; + + if(scope.$first && !scope.$last) { + scope.$evalAsync(function () { + $rootScope.$broadcast(broadcastMessage+' Started'); + }); + }else if(scope.$last) { + scope.$evalAsync(function () { + // console.log(broadcastMessage+'Finished'); + $rootScope.$broadcast(broadcastMessage+' Finished'); + }); + } + } + }; +}]); + +'use strict'; + + +angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCounter', '$filter', '$rootScope', 'SendVisitorData', + function ($http, TimeCounter, $filter, $rootScope, SendVisitorData) { + return { + templateUrl: 'modules/forms/base/views/directiveViews/form/submit-form.client.view.html', + restrict: 'E', + scope: { + myform:'=' + }, + controller: ["$document", "$window", "$scope", function($document, $window, $scope){ + $scope.noscroll = false; + $scope.forms = {}; + + var form_fields_count = $scope.myform.visible_form_fields.filter(function(field){ + if(field.fieldType === 'statement' || field.fieldType === 'rating'){ + return false; + } + return true; + }).length; + + var nb_valid = $filter('formValidity')($scope.myform); + $scope.translateAdvancementData = { + done: nb_valid, + total: form_fields_count, + answers_not_completed: form_fields_count - nb_valid + }; + + $scope.reloadForm = function(){ + //Reset Form + $scope.myform.submitted = false; + $scope.myform.form_fields = _.chain($scope.myform.visible_form_fields).map(function(field){ + field.fieldValue = ''; + return field; + }).value(); + + $scope.loading = false; + $scope.error = ''; + + $scope.selected = { + _id: '', + index: 0 + }; + $scope.setActiveField($scope.myform.visible_form_fields[0]._id, 0, false); + + //console.log($scope.selected); + //Reset Timer + TimeCounter.restartClock(); + }; + + //Fire event when window is scrolled + $window.onscroll = function(){ + $scope.scrollPos = document.body.scrollTop || document.documentElement.scrollTop || 0; + var elemBox = document.getElementsByClassName('activeField')[0].getBoundingClientRect(); + $scope.fieldTop = elemBox.top; + $scope.fieldBottom = elemBox.bottom; + + //console.log($scope.forms.myForm); + var field_id; + var field_index; + + if(!$scope.noscroll){ + //Focus on submit button + if( $scope.selected.index === $scope.myform.visible_form_fields.length-1 && $scope.fieldBottom < 200){ + field_index = $scope.selected.index+1; + field_id = 'submit_field'; + $scope.setActiveField(field_id, field_index, false); + } + //Focus on field above submit button + else if($scope.selected.index === $scope.myform.visible_form_fields.length){ + if($scope.fieldTop > 200){ + field_index = $scope.selected.index-1; + field_id = $scope.myform.visible_form_fields[field_index]._id; + $scope.setActiveField(field_id, field_index, false); + } + }else if( $scope.fieldBottom < 0){ + field_index = $scope.selected.index+1; + field_id = $scope.myform.visible_form_fields[field_index]._id; + $scope.setActiveField(field_id, field_index, false); + }else if ( $scope.selected.index !== 0 && $scope.fieldTop > 0) { + field_index = $scope.selected.index-1; + field_id = $scope.myform.visible_form_fields[field_index]._id; + $scope.setActiveField(field_id, field_index, false); + } + //console.log('$scope.selected.index: '+$scope.selected.index); + //console.log('scroll pos: '+$scope.scrollPos+' fieldTop: '+$scope.fieldTop+' fieldBottom: '+$scope.fieldBottom); + $scope.$apply(); + } + }; + + /* + ** Field Controls + */ + var getActiveField = function(){ + if($scope.selected === null){ + console.error('current active field is null'); + throw new Error('current active field is null'); + } + + if($scope.selected._id === 'submit_field') { + return $scope.myform.form_fields.length - 1; + } else { + return $scope.selected.index; + } + }; + + $scope.setActiveField = $rootScope.setActiveField = function(field_id, field_index, animateScroll) { + if($scope.selected === null || $scope.selected._id === field_id){ + //console.log('not scrolling'); + //console.log($scope.selected); + return; + } + //console.log('field_id: '+field_id); + //console.log('field_index: '+field_index); + //console.log($scope.selected); + + $scope.selected._id = field_id; + $scope.selected.index = field_index; + + var nb_valid = $filter('formValidity')($scope.myform); + $scope.translateAdvancementData = { + done: nb_valid, + total: form_fields_count, + answers_not_completed: form_fields_count - nb_valid + }; + + if(animateScroll){ + $scope.noscroll=true; + setTimeout(function() { + $document.scrollToElement(angular.element('.activeField'), -10, 200).then(function() { + $scope.noscroll = false; + setTimeout(function() { + if (document.querySelectorAll('.activeField .focusOn').length) { + //Handle default case + document.querySelectorAll('.activeField .focusOn')[0].focus(); + } else if(document.querySelectorAll('.activeField input').length) { + //Handle case for rating input + document.querySelectorAll('.activeField input')[0].focus(); + } else { + //Handle case for dropdown input + document.querySelectorAll('.activeField .selectize-input')[0].focus(); + } + }); + }); + }); + }else { + setTimeout(function() { + if (document.querySelectorAll('.activeField .focusOn')[0]) { + //FIXME: DAVID: Figure out how to set focus without scroll movement in HTML Dom + document.querySelectorAll('.activeField .focusOn')[0].focus(); + } else { + document.querySelectorAll('.activeField input')[0].focus(); + } + }); + } + + SendVisitorData.send($scope.myform, getActiveField(), TimeCounter.getTimeElapsed()); + }; + + $rootScope.nextField = $scope.nextField = function(){ + //console.log('nextfield'); + //console.log($scope.selected.index); + //console.log($scope.myform.visible_form_fields.length-1); + var selected_index, selected_id; + if($scope.selected.index < $scope.myform.visible_form_fields.length-1){ + selected_index = $scope.selected.index+1; + selected_id = $scope.myform.visible_form_fields[selected_index]._id; + $rootScope.setActiveField(selected_id, selected_index, true); + } else if($scope.selected.index === $scope.myform.visible_form_fields.length-1) { + //console.log('Second last element'); + selected_index = $scope.selected.index+1; + selected_id = 'submit_field'; + $rootScope.setActiveField(selected_id, selected_index, true); + } + }; + + $rootScope.prevField = $scope.prevField = function(){ + if($scope.selected.index > 0){ + var selected_index = $scope.selected.index - 1; + var selected_id = $scope.myform.visible_form_fields[selected_index]._id; + $scope.setActiveField(selected_id, selected_index, true); + } + }; + + /* + ** Form Display Functions + */ + $scope.exitStartPage = function(){ + $scope.myform.startPage.showStart = false; + if($scope.myform.visible_form_fields.length > 0){ + $scope.selected._id = $scope.myform.visible_form_fields[0]._id; + } + }; + + $rootScope.goToInvalid = $scope.goToInvalid = function() { + document.querySelectorAll('.ng-invalid.focusOn')[0].focus(); + }; + + $rootScope.submitForm = $scope.submitForm = function() { + + var _timeElapsed = TimeCounter.stopClock(); + $scope.loading = true; + + var form = _.cloneDeep($scope.myform); + + form.timeElapsed = _timeElapsed; + + form.percentageComplete = $filter('formValidity')($scope.myform) / $scope.myform.visible_form_fields.length * 100; + delete form.visible_form_fields; + + for(var i=0; i < $scope.myform.form_fields.length; i++){ + if($scope.myform.form_fields[i].fieldType === 'dropdown' && !$scope.myform.form_fields[i].deletePreserved){ + $scope.myform.form_fields[i].fieldValue = $scope.myform.form_fields[i].fieldValue.option_value; + } + } + + setTimeout(function () { + $scope.submitPromise = $http.post('/forms/' + $scope.myform._id, form) + .success(function (data, status, headers) { + console.log($scope.myform.form_fields[0]); + $scope.myform.submitted = true; + $scope.loading = false; + SendVisitorData.send($scope.myform, getActiveField(), _timeElapsed); + }) + .error(function (error) { + $scope.loading = false; + console.error(error); + $scope.error = error.message; + }); + }, 500); + }; + + //Reload our form + $scope.reloadForm(); + }] + }; + } +]); + +'use strict'; + +//Forms service used for communicating with the forms REST endpoints +angular.module('view-form').service('CurrentForm', + function(){ + + //Private variables + var _form = {}; + + //Public Methods + this.getForm = function() { + return _form; + }; + this.setForm = function(form) { + _form = form; + }; + } +); + +'use strict'; + +//Forms service used for communicating with the forms REST endpoints +angular.module('view-form').factory('Forms', ['$resource', 'FORM_URL', + function($resource, FORM_URL) { + return $resource(FORM_URL, { + formId: '@_id' + }, { + 'query' : { + method: 'GET', + isArray: true + //DAVID: TODO: Do we really need to get visible_form_fields for a Query? + // transformResponse: function(data, header) { + // var forms = angular.fromJson(data); + // angular.forEach(forms, function(form, idx) { + // form.visible_form_fields = _.filter(form.form_fields, function(field){ + // return (field.deletePreserved === false); + // }); + // }); + // return forms; + // } + }, + 'get' : { + method: 'GET', + transformResponse: function(data, header) { + var form = angular.fromJson(data); + + form.visible_form_fields = _.filter(form.form_fields, function(field){ + return (field.deletePreserved === false); + }); + return form; + } + }, + 'update': { + method: 'PUT' + }, + 'save': { + method: 'POST' + } + }); + } +]); + +(function () { + 'use strict'; + + // Create the Socket.io wrapper service + angular + .module('view-form') + .factory('Socket', Socket); + + Socket.$inject = ['$timeout', '$window']; + + function Socket($timeout, $window) { + var service = { + connect: connect, + emit: emit, + on: on, + removeListener: removeListener, + socket: null + }; + + connect(window.location.protocol+'//'+window.location.hostname+':'+$window.socketPort); + + return service; + + // Connect to Socket.io server + function connect(url) { + service.socket = io(url, {'transports': ['websocket', 'polling']}); + } + + // Wrap the Socket.io 'emit' method + function emit(eventName, data) { + if (service.socket) { + service.socket.emit(eventName, data); + } + } + + // Wrap the Socket.io 'on' method + function on(eventName, callback) { + if (service.socket) { + service.socket.on(eventName, function (data) { + $timeout(function () { + callback(data); + }); + }); + } + } + + // Wrap the Socket.io 'removeListener' method + function removeListener(eventName) { + if (service.socket) { + service.socket.removeListener(eventName); + } + } + } +}()); + +'use strict'; + +angular.module('view-form').service('TimeCounter', [ + function(){ + var _startTime, _endTime = null, that=this; + + this.timeSpent = 0; + + this.restartClock = function(){ + _startTime = Date.now(); + _endTime = null; + // console.log('Clock Started'); + }; + + this.getTimeElapsed = function(){ + if(_startTime) { + return Math.abs(Date.now().valueOf() - _startTime.valueOf()) / 1000; + } + }; + + this.stopClock = function(){ + if(_startTime && _endTime === null){ + _endTime = Date.now(); + this.timeSpent = Math.abs(_endTime.valueOf() - _startTime.valueOf())/1000; + this._startTime = this._endTime = null; + + return this.timeSpent; + }else{ + return new Error('Clock has not been started'); + } + }; + + this.clockStarted = function(){ + return !!this._startTime; + }; + + } +]); diff --git a/public/dist/form-application.min.js b/public/dist/form-application.min.js new file mode 100644 index 00000000..c9b36171 --- /dev/null +++ b/public/dist/form-application.min.js @@ -0,0 +1,3 @@ +"use strict";var ApplicationConfiguration=function(){var applicationModuleName="NodeForm",applicationModuleVendorDependencies=["duScroll","ui.select","cgBusy","ngSanitize","vButton","ngResource","NodeForm.templates","ui.router","ui.bootstrap","ui.utils","pascalprecht.translate","ng.deviceDetector"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("FORM_URL","/forms/:formId"),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),angular.module("NodeForm.templates",[]).run(["$templateCache",function($templateCache){$templateCache.put("modules/core/views/header.client.view.html",''),$templateCache.put("modules/forms/admin/views/admin-form.client.view.html",'
'),$templateCache.put("modules/forms/admin/views/list-forms.client.view.html",'

{{ \'CREATE_A_NEW_FORM\' | translate }}
Name
Language

'),$templateCache.put("modules/forms/base/views/submit-form.client.view.html","
"),$templateCache.put("modules/forms/admin/views/adminTabs/analyze.html",""),$templateCache.put("modules/forms/admin/views/adminTabs/configure.html",""),$templateCache.put("modules/forms/admin/views/adminTabs/create.html",""),$templateCache.put("modules/forms/admin/views/adminTabs/design.html",'
{{ \'BACKGROUND_COLOR\' | translate }}
{{ \'QUESTION_TEXT_COLOR\' | translate }}
{{ \'ANSWER_TEXT_COLOR\' | translate }}
{{ \'BTN_BACKGROUND_COLOR\' | translate }}
{{ \'BTN_TEXT_COLOR\' | translate }}
'),$templateCache.put("modules/forms/admin/views/directiveViews/cgBusy/update-form-message-TypeA.html",'
{{$message}}
'),$templateCache.put("modules/forms/admin/views/directiveViews/cgBusy/update-form-message-TypeB.html",'
{{$message}}
'),$templateCache.put("modules/forms/admin/views/directiveViews/form/configure-form.client.view.html",'
{{ \'SAVE_PDF_SUBMISSIONS\' | translate }}
{{ \'UPLOAD_YOUR_PDF\' | translate }}
{{myform.pdf.name}}
{{ \'UPLOAD_YOUR_PDF\' | translate }}
{{ \'Autogenerate Form?\' | translate }}
{{ \'FORM_NAME\' | translate }}
{{ \'FORM_STATUS\' | translate }}
{{ \'GA_TRACKING_CODE\' | translate }}
Language
* required
{{ \'DISPLAY_FOOTER\' | translate }}
Display Start Page?
'),$templateCache.put("modules/forms/admin/views/directiveViews/form/edit-form.client.view.html",'

{{ \'EDIT_START_PAGE\' | translate }}


{{ \'INTRO_TITLE\' | translate }}:
{{ \'INTRO_PARAGRAPH\' | translate }}:
{{ \'INTRO_BTN\' | translate }}:


Buttons:
{{ \'BUTTON_TEXT\' | translate }}
{{ \'BUTTON_LINK\' | translate }}


{{field.title}} *

{{ \'EDIT_FIELD\' | translate }}


{{ \'QUESTION_TITLE\' | translate }}:

{{ \'QUESTION_DESCRIPTION\' | translate }}:

{{ \'OPTIONS\' | translate }}:

{{ \'NUM_OF_STEPS\' | translate }}

Shape:

Required:
Disabled:

{{ \'CLICK_FIELDS_FOOTER\' | translate }}


'),$templateCache.put("modules/forms/admin/views/directiveViews/form/edit-submissions-form.client.view.html",'
Overview Analytics
{{ \'TOTAL_VIEWS\' | translate }}
{{ \'RESPONSES\' | translate }}
{{ \'COMPLETION_RATE\' | translate }}
{{ \'AVERAGE_TIME_TO_COMPLETE\' | translate }}
{{myform.analytics.views}}
{{myform.analytics.submissions}}
{{myform.analytics.conversionRate | number:0}}%
{{AverageTimeElapsed | secondsToDateTime | date:\'mm:ss\'}}
Device Analytics
{{ \'DESKTOP_AND_LAPTOP\' | translate }}
{{ \'TABLETS\' | translate }}
{{ \'PHONES\' | translate }}
{{ \'OTHER\' | translate }}
{{ \'UNIQUE_VISITS\' | translate }}
{{DeviceStatistics.desktop.visits}}
{{ \'UNIQUE_VISITS\' | translate }}
{{DeviceStatistics.tablet.visits}}
{{ \'UNIQUE_VISITS\' | translate }}
{{DeviceStatistics.tablet.visits}}
{{ \'UNIQUE_VISITS\' | translate }}
{{DeviceStatistics.other.visits}}
{{ \'RESPONSES\' | translate }}
{{DeviceStatistics.desktop.responses}}
{{ \'RESPONSES\' | translate }}
{{DeviceStatistics.tablet.responses}}
{{ \'RESPONSES\' | translate }}
{{DeviceStatistics.phone.responses}}
{{ \'RESPONSES\' | translate }}
{{DeviceStatistics.other.responses}}
{{ \'COMPLETION_RATE\' | translate }}
{{DeviceStatistics.desktop.completion}}
{{ \'COMPLETION_RATE\' | translate }}
{{DeviceStatistics.tablet.completion}}
{{ \'COMPLETION_RATE\' | translate }}
{{DeviceStatistics.phone.completion}}
{{ \'COMPLETION_RATE\' | translate }}
{{DeviceStatistics.other.completion}}
{{ \'AVERAGE_TIME_TO_COMPLETE\' | translate }}
{{DeviceStatistics.desktop.average_time | secondsToDateTime | date:\'mm:ss\'}}
{{ \'AVERAGE_TIME_TO_COMPLETE\' | translate }}
{{DeviceStatistics.tablet.average_time | secondsToDateTime | date:\'mm:ss\'}}
{{ \'AVERAGE_TIME_TO_COMPLETE\' | translate }}
{{DeviceStatistics.phone.average_time | secondsToDateTime | date:\'mm:ss\'}}
{{ \'AVERAGE_TIME_TO_COMPLETE\' | translate }}
{{DeviceStatistics.other.average_time | secondsToDateTime | date:\'mm:ss\'}}
Field Analytics
{{ \'FIELD_TITLE\' | translate }}
{{ \'FIELD_VIEWS\' | translate }}
{{ \'FIELD_RESPONSES\' | translate }}
{{ \'FIELD_DROPOFF\' | translate }}
{{fieldStats.field.title}}
{{fieldStats.totalViews}}
{{fieldStats.responses}}
{{fieldStats.continueRate}}%

Responses Table
#{{value.title}}{{ \'PERCENTAGE_COMPLETE\' | translate }}{{ \'TIME_ELAPSED\' | translate }}{{ \'DEVICE\' | translate }}{{ \'LOCATION\' | translate }}{{ \'IP_ADDRESS\' | translate }}{{ \'DATE_SUBMITTED\' | translate }} (UTC){{ \'GENERATED_PDF\' | translate }}
{{$index+1}}{{field.fieldValue}}{{row.percentageComplete}}%{{row.timeElapsed | secondsToDateTime | date:\'mm:ss\'}}{{row.device.name}}, {{row.device.type}}{{row.geoLocation.city}}, {{row.geoLocation.country_name}}{{row.ipAddr}}{{row.created | date:\'yyyy-MM-dd HH:mm:ss\'}}{{ \'GENERATED_PDF\' | translate }}
'), +$templateCache.put("modules/forms/base/views/directiveViews/entryPage/startPage.html",'

{{pageData.introTitle}}

{{pageData.introParagraph}}

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

{{index+1}} {{field.title}} {{ \'OPTIONAL\' | translate }}

{{field.description}}

'),$templateCache.put("modules/forms/base/views/directiveViews/field/dropdown.html",'
'),$templateCache.put("modules/forms/base/views/directiveViews/field/file.html",'

{{index+1}} {{field.title}} {{ \'OPTIONAL\' | translate }}

{{field.file.originalname}}
{{ UPLOAD_FILE | translate }}
'),$templateCache.put("modules/forms/base/views/directiveViews/field/hidden.html",''),$templateCache.put("modules/forms/base/views/directiveViews/field/legal.html",'
'),$templateCache.put("modules/forms/base/views/directiveViews/field/radio.html",'

{{index+1}} {{field.title}} {{ \'OPTIONAL\' | translate }}

{{field.description}}


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

{{index+1}} {{field.title}} {{ \'OPTIONAL\' | translate }}

{{field.description}}

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

{{field.title}}

{{field.description}}

{{field.description}}


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

{{index+1}} {{field.title}} {{ \'OPTIONAL\' | translate }}

{{ \'NEWLINE\' | translate }}

{{field.description}}

Press SHIFT+ENTER to add a newline
'),$templateCache.put("modules/forms/base/views/directiveViews/field/textfield.html",'

{{index+1}} {{field.title}} ({{ \'OPTIONAL\' | translate }})

{{field.description}}

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

{{index+1}} {{field.title}} {{ \'OPTIONAL\' | translate }}

{{field.description}}


'),$templateCache.put("modules/forms/base/views/directiveViews/form/submit-form.client.view.html",'

{{myform.startPage.introTitle}}

{{myform.startPage.introParagraph}}

{{ \'COMPLETING_NEEDED\' | translate:translateAdvancementData }}
{{ \'FORM_SUCCESS\' | translate }}

'),$templateCache.put("modules/users/views/authentication/access-denied.client.view.html","

{{ 'ACCESS_DENIED_TEXT' | translate }}

{{ 'SIGNIN_BTN' | translate }}
"),$templateCache.put("modules/users/views/authentication/signin.client.view.html",'

Sign into your account

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

{{ \'SUCCESS_HEADER\' | translate }}

{{ \'SUCCESS_TEXT\' | translate }}

{{ \'NOT_ACTIVATED_YET\' | translate }}



{{ \'BEFORE_YOU_CONTINUE\' | translate }} polydaic@gmail.com

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

Signup with your email

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

{{ \'PASSWORD_RESTORE_HEADER\' | translate }}

{{ \'ENTER_YOUR_EMAIL\' | translate }}

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

{{ 'PASSWORD_RESET_INVALID' | translate }}

{{ 'ASK_FOR_NEW_PASSWORD' | translate }}
"),$templateCache.put("modules/users/views/password/reset-password-success.client.view.html","

{{ 'PASSWORD_RESET_SUCCESS' | translate }}

{{ 'CONTINUE_TO_LOGIN' | translate }}
"),$templateCache.put("modules/users/views/password/reset-password.client.view.html",'

Reset your password

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

Change your password

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

Edit your profile

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

Connected social accounts:

Connect other social accounts:

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

Resend your account verification email

Enter your account email.

{{error}}

Verification Email has been Sent

{{ \'VERIFICATION_EMAIL_SENT\' | translate }} {{username}}.
{{ \'NOT_ACTIVATED_YET\' | translate }}

{{ \'CHECK_YOUR_EMAIL\' | translate }} polydaic@gmail.com

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

{{ 'CONTINUE_TO_LOGIN' | translate }}

{{ 'VERIFY_ERROR' | translate }}

{{ 'REVERIFY_ACCOUNT_LINK' | translate }} {{ 'SIGNIN_BTN' | translate }}
")}]),ApplicationConfiguration.registerModule("view-form",["ngFileUpload","ui.router.tabs","ui.date","ui.sortable","angular-input-stars","pascalprecht.translate"]),angular.module("view-form").config(["$translateProvider",function($translateProvider){$translateProvider.translations("english",{FORM_SUCCESS:"Form entry successfully submitted!",REVIEW:"Review",BACK_TO_FORM:"Go back to Form",EDIT_FORM:"Edit this TellForm",CREATE_FORM:"Create this TellForm",ADVANCEMENT:"{{done}} out of {{total}} answered",CONTINUE_FORM:"Continue to Form",REQUIRED:"required",COMPLETING_NEEDED:"{{answers_not_completed}} answer(s) need completing",OPTIONAL:"optional",ERROR_EMAIL_INVALID:"Please enter a valid email address",ERROR_NOT_A_NUMBER:"Please enter valid numbers only",ERROR_URL_INVALID:"Please a valid url",OK:"OK",ENTER:"press ENTER",YES:"Yes",NO:"No",NEWLINE:"press SHIFT+ENTER to create a newline",CONTINUE:"Continue",LEGAL_ACCEPT:"I accept",LEGAL_NO_ACCEPT:"I don’t accept",DELETE:"Delete",CANCEL:"Cancel",SUBMIT:"Submit",UPLOAD_FILE:"Upload your File"}),$translateProvider.preferredLanguage("english").fallbackLanguage("english").useSanitizeValueStrategy("escape")}]),angular.module("view-form").config(["$translateProvider",function($translateProvider){$translateProvider.translations("french",{FORM_SUCCESS:"Votre formulaire a été enregistré!",REVIEW:"Incomplet",BACK_TO_FORM:"Retourner au formulaire",EDIT_FORM:"Éditer le Tellform",CREATE_FORM:"Créer un TellForm",ADVANCEMENT:"{{done}} complétés sur {{total}}",CONTINUE_FORM:"Aller au formulaire",REQUIRED:"obligatoire",COMPLETING_NEEDED:"{{answers_not_completed}} réponse(s) doive(nt) être complétée(s)",OPTIONAL:"facultatif",ERROR_EMAIL_INVALID:"Merci de rentrer une adresse mail valide",ERROR_NOT_A_NUMBER:"Merce de ne rentrer que des nombres",ERROR_URL_INVALID:"Merci de rentrer une url valide",OK:"OK",ENTER:"presser ENTRÉE",YES:"Oui",NO:"Non",NEWLINE:"presser SHIFT+ENTER pour créer une nouvelle ligne",CONTINUE:"Continuer",LEGAL_ACCEPT:"J’accepte",LEGAL_NO_ACCEPT:"Je n’accepte pas",DELETE:"Supprimer",CANCEL:"Réinitialiser",SUBMIT:"Enregistrer",UPLOAD_FILE:"Envoyer un fichier",Y:"O",N:"N"})}]),angular.module("view-form").config(["$translateProvider",function($translateProvider){$translateProvider.translations("german",{FORM_SUCCESS:"Ihre Angaben wurden gespeichert.",REVIEW:"Unvollständig",BACK_TO_FORM:"Zurück zum Formular",EDIT_FORM:"",CREATE_FORM:"",ADVANCEMENT:"{{done}} von {{total}} beantwortet",CONTINUE_FORM:"Zum Formular",REQUIRED:"verpflichtend",COMPLETING_NEEDED:"Es fehlen/fehtl noch {{answers_not_completed}} Antwort(en)",OPTIONAL:"fakultativ",ERROR_EMAIL_INVALID:"Bitte gültige Mailadresse eingeben",ERROR_NOT_A_NUMBER:"Bitte nur Zahlen eingeben",ERROR_URL_INVALID:"Bitte eine gültige URL eingeben",OK:"Okay",ENTER:"Eingabetaste drücken",YES:"Ja",NO:"Nein",NEWLINE:"Für eine neue Zeile SHIFT+ENTER drücken",CONTINUE:"Weiter",LEGAL_ACCEPT:"I accept",LEGAL_NO_ACCEPT:"I don’t accept",DELETE:"Entfernen",CANCEL:"Canceln",SUBMIT:"Speichern",UPLOAD_FILE:"Datei versenden",Y:"J",N:"N"})}]),angular.module("view-form").config(["$translateProvider",function($translateProvider){$translateProvider.translations("italian",{FORM_SUCCESS:"Il formulario è stato inviato con successo!",REVIEW:"Incompleto",BACK_TO_FORM:"Ritorna al formulario",EDIT_FORM:"",CREATE_FORM:"",ADVANCEMENT:"{{done}} su {{total}} completate",CONTINUE_FORM:"Vai al formulario",REQUIRED:"obbligatorio",COMPLETING_NEEDED:"{{answers_not_completed}} risposta/e deve/ono essere completata/e",OPTIONAL:"opzionale",ERROR_EMAIL_INVALID:"Si prega di inserire un indirizzo email valido",ERROR_NOT_A_NUMBER:"Si prega di inserire solo numeri",ERROR_URL_INVALID:"Grazie per inserire un URL valido",OK:"OK",ENTER:"premere INVIO",YES:"Sì",NO:"No",NEWLINE:"premere SHIFT+INVIO per creare una nuova linea",CONTINUE:"Continua",LEGAL_ACCEPT:"I accept",LEGAL_NO_ACCEPT:"I don’t accept",DELETE:"Cancella",CANCEL:"Reset",SUBMIT:"Registra",UPLOAD_FILE:"Invia un file",Y:"S",N:"N"})}]),angular.module("view-form").config(["$translateProvider",function($translateProvider){$translateProvider.translations("spanish",{FORM_SUCCESS:"¡El formulario ha sido enviado con éxito!",REVIEW:"Revisar",BACK_TO_FORM:"Regresar al formulario",EDIT_FORM:"",CREATE_FORM:"",ADVANCEMENT:"{{done}} de {{total}} contestadas",CONTINUE_FORM:"Continuar al formulario",REQUIRED:"Información requerida",COMPLETING_NEEDED:"{{answers_not_completed}} respuesta(s) necesita(n) ser completada(s)",OPTIONAL:"Opcional",ERROR_EMAIL_INVALID:"Favor de proporcionar un correo electrónico válido",ERROR_NOT_A_NUMBER:"Por favor, introduzca sólo números válidos",ERROR_URL_INVALID:"Favor de proporcionar un url válido",OK:"OK",ENTER:"pulse INTRO",YES:"Si",NO:"No",NEWLINE:"presione SHIFT+INTRO para crear una nueva línea",CONTINUE:"Continuar",LEGAL_ACCEPT:"I accept",LEGAL_NO_ACCEPT:"I don’t accept",DELETE:"Eliminar",CANCEL:"Cancelar",SUBMIT:"Registrar",UPLOAD_FILE:"Cargar el archivo",Y:"S",N:"N"})}]),angular.module("view-form").filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field&&"statement"!==field.fieldType&&"rating"!==field.fieldType?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}),angular.module("view-form").config(["$stateProvider",function($stateProvider){$stateProvider.state("submitForm",{url:"/forms/:formId",templateUrl:"/static/form_modules/forms/base/views/submit-form.client.view.html",resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"SubmitFormController",controllerAs:"ctrl"})}]),function(){function SendVisitorData(Socket,$state){function send(form,lastActiveIndex,timeElapsed){var visitorData={referrer:document.referrer,isSubmitted:form.submitted,formId:form._id,lastActiveField:form.form_fields[lastActiveIndex]._id,timeElapsed:timeElapsed};Socket.emit("form-visitor-data",visitorData)}function init(){Socket.socket||Socket.connect()}var service={send:send};return init(),service}angular.module("view-form").factory("SendVisitorData",SendVisitorData),SendVisitorData.$inject=["Socket","$state"]}(),angular.module("view-form").directive("keyToOption",function(){return{restrict:"A",scope:{field:"="},link:function($scope,$element,$attrs,$select){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode,index=parseInt(String.fromCharCode(keyCode))-1;index<$scope.field.fieldOptions.length&&(event.preventDefault(),$scope.$apply(function(){$scope.field.fieldValue=$scope.field.fieldOptions[index].option_value}))})}}}),angular.module("view-form").directive("keyToTruthy",["$rootScope",function($rootScope){return{restrict:"A",scope:{field:"="},link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode,truthyKeyCode=$attrs.keyCharTruthy.charCodeAt(0)-32,falseyKeyCode=$attrs.keyCharFalsey.charCodeAt(0)-32;keyCode===truthyKeyCode?(event.preventDefault(),$scope.$apply(function(){$scope.field.fieldValue="true"})):keyCode===falseyKeyCode&&(event.preventDefault(),$scope.$apply(function(){$scope.field.fieldValue="false"}))})}}}]),angular.module("view-form").filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field&&"statement"!==field.fieldType&&"rating"!==field.fieldType?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}),angular.module("view-form").value("supportedFields",["textfield","textarea","date","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"]),angular.module("view-form").controller("SubmitFormController",["$scope","$rootScope","$state","$translate","myForm",function($scope,$rootScope,$state,$translate,myForm){$scope.myform=myForm,$translate.use(myForm.language)}]),angular.module("view-form").directive("fieldIconDirective",function(){return{template:'',restrict:"E",scope:{typeName:"@"},controller:["$scope",function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}]}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("view-form").directive("fieldDirective",["$http","$compile","$rootScope","$templateCache","supportedFields",function($http,$compile,$rootScope,$templateCache,supportedFields){var getTemplateUrl=function(fieldType){var type=fieldType,templateUrl="modules/forms/base/views/directiveViews/field/";return __indexOf.call(supportedFields,type)>=0&&(templateUrl=templateUrl+type+".html"),$templateCache.get(templateUrl)};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&",design:"=",index:"=",forms:"="},link:function(scope,element){$rootScope.chooseDefaultOption=scope.chooseDefaultOption=function(type){"yes_no"===type?scope.field.fieldValue="true":"rating"===type?scope.field.fieldValue=0:"radio"===scope.field.fieldType?(console.log(scope.field),scope.field.fieldValue=scope.field.fieldOptions[0].option_value,console.log(scope.field.fieldValue)):"legal"===type&&(scope.field.fieldValue="true",$rootScope.nextField())},scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType&&(scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0});var fieldType=scope.field.fieldType;if("number"===scope.field.fieldType||"textfield"===scope.field.fieldType||"email"===scope.field.fieldType||"link"===scope.field.fieldType){switch(scope.field.fieldType){case"textfield":scope.field.input_type="text";break;case"email":scope.field.input_type="email",scope.field.placeholder="joesmith@example.com";break;case"number":scope.field.input_type="text",scope.field.validateRegex=/^-?\d+$/;break;default:scope.field.input_type="url",scope.field.placeholder="http://example.com"}fieldType="textfield"}var template=getTemplateUrl(fieldType);element.html(template).show();$compile(element.contents())(scope)}}}]),angular.module("view-form").directive("onEnterKey",["$rootScope",function($rootScope){return{restrict:"A",link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode,onEnterKeyDisabled=!1;null!==$attrs.onEnterKeyDisabled&&(onEnterKeyDisabled=$attrs.onEnterKeyDisabled),13!==keyCode||event.shiftKey||onEnterKeyDisabled||(event.preventDefault(),$rootScope.$apply(function(){$rootScope.$eval($attrs.onEnterKey)}))})}}}]).directive("onTabKey",["$rootScope",function($rootScope){return{restrict:"A",link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode;9!==keyCode||event.shiftKey||(event.preventDefault(),$rootScope.$apply(function(){$rootScope.$eval($attrs.onTabKey)}))})}}}]).directive("onEnterOrTabKey",["$rootScope",function($rootScope){return{restrict:"A",link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode;13!==keyCode&&9!==keyCode||event.shiftKey||(event.preventDefault(),$rootScope.$apply(function(){$rootScope.$eval($attrs.onEnterOrTabKey)}))})}}}]).directive("onTabAndShiftKey",["$rootScope",function($rootScope){return{restrict:"A",link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode;9===keyCode&&event.shiftKey&&(event.preventDefault(),$rootScope.$apply(function(){$rootScope.$eval($attrs.onTabAndShiftKey)}))})}}}]),angular.module("view-form").directive("onFinishRender",["$rootScope","$timeout",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")||element.attr("data-ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$first&&!scope.$last?scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Started")}):scope.$last&&scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Finished")})}}}}]),angular.module("view-form").directive("submitFormDirective",["$http","TimeCounter","$filter","$rootScope","SendVisitorData",function($http,TimeCounter,$filter,$rootScope,SendVisitorData){return{templateUrl:"modules/forms/base/views/directiveViews/form/submit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:["$document","$window","$scope",function($document,$window,$scope){$scope.noscroll=!1,$scope.forms={};var form_fields_count=$scope.myform.visible_form_fields.filter(function(field){return"statement"!==field.fieldType&&"rating"!==field.fieldType}).length,nb_valid=$filter("formValidity")($scope.myform);$scope.translateAdvancementData={done:nb_valid,total:form_fields_count,answers_not_completed:form_fields_count-nb_valid},$scope.reloadForm=function(){$scope.myform.submitted=!1,$scope.myform.form_fields=_.chain($scope.myform.visible_form_fields).map(function(field){return field.fieldValue="",field}).value(),$scope.loading=!1,$scope.error="",$scope.selected={_id:"",index:0},$scope.setActiveField($scope.myform.visible_form_fields[0]._id,0,!1),TimeCounter.restartClock()},$window.onscroll=function(){$scope.scrollPos=document.body.scrollTop||document.documentElement.scrollTop||0;var elemBox=document.getElementsByClassName("activeField")[0].getBoundingClientRect();$scope.fieldTop=elemBox.top,$scope.fieldBottom=elemBox.bottom;var field_id,field_index;$scope.noscroll||($scope.selected.index===$scope.myform.visible_form_fields.length-1&&$scope.fieldBottom<200?(field_index=$scope.selected.index+1,field_id="submit_field",$scope.setActiveField(field_id,field_index,!1)):$scope.selected.index===$scope.myform.visible_form_fields.length?$scope.fieldTop>200&&(field_index=$scope.selected.index-1,field_id=$scope.myform.visible_form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)):$scope.fieldBottom<0?(field_index=$scope.selected.index+1,field_id=$scope.myform.visible_form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)):0!==$scope.selected.index&&$scope.fieldTop>0&&(field_index=$scope.selected.index-1,field_id=$scope.myform.visible_form_fields[field_index]._id,$scope.setActiveField(field_id,field_index,!1)),$scope.$apply())};var getActiveField=function(){if(null===$scope.selected)throw console.error("current active field is null"),new Error("current active field is null");return"submit_field"===$scope.selected._id?$scope.myform.form_fields.length-1:$scope.selected.index};$scope.setActiveField=$rootScope.setActiveField=function(field_id,field_index,animateScroll){if(null!==$scope.selected&&$scope.selected._id!==field_id){$scope.selected._id=field_id,$scope.selected.index=field_index;var nb_valid=$filter("formValidity")($scope.myform);$scope.translateAdvancementData={done:nb_valid,total:form_fields_count,answers_not_completed:form_fields_count-nb_valid},animateScroll?($scope.noscroll=!0,setTimeout(function(){$document.scrollToElement(angular.element(".activeField"),-10,200).then(function(){$scope.noscroll=!1,setTimeout(function(){document.querySelectorAll(".activeField .focusOn").length?document.querySelectorAll(".activeField .focusOn")[0].focus():document.querySelectorAll(".activeField input").length?document.querySelectorAll(".activeField input")[0].focus():document.querySelectorAll(".activeField .selectize-input")[0].focus()})})})):setTimeout(function(){document.querySelectorAll(".activeField .focusOn")[0]?document.querySelectorAll(".activeField .focusOn")[0].focus():document.querySelectorAll(".activeField input")[0].focus()}),SendVisitorData.send($scope.myform,getActiveField(),TimeCounter.getTimeElapsed())}},$rootScope.nextField=$scope.nextField=function(){var selected_index,selected_id;$scope.selected.index<$scope.myform.visible_form_fields.length-1?(selected_index=$scope.selected.index+1,selected_id=$scope.myform.visible_form_fields[selected_index]._id,$rootScope.setActiveField(selected_id,selected_index,!0)):$scope.selected.index===$scope.myform.visible_form_fields.length-1&&(selected_index=$scope.selected.index+1,selected_id="submit_field",$rootScope.setActiveField(selected_id,selected_index,!0))},$rootScope.prevField=$scope.prevField=function(){if($scope.selected.index>0){var selected_index=$scope.selected.index-1,selected_id=$scope.myform.visible_form_fields[selected_index]._id;$scope.setActiveField(selected_id,selected_index,!0)}},$scope.exitStartPage=function(){$scope.myform.startPage.showStart=!1,$scope.myform.visible_form_fields.length>0&&($scope.selected._id=$scope.myform.visible_form_fields[0]._id)},$rootScope.goToInvalid=$scope.goToInvalid=function(){document.querySelectorAll(".ng-invalid.focusOn")[0].focus()},$rootScope.submitForm=$scope.submitForm=function(){var _timeElapsed=TimeCounter.stopClock();$scope.loading=!0;var form=_.cloneDeep($scope.myform);form.timeElapsed=_timeElapsed,form.percentageComplete=$filter("formValidity")($scope.myform)/$scope.myform.visible_form_fields.length*100,delete form.visible_form_fields;for(var i=0;i<$scope.myform.form_fields.length;i++)"dropdown"!==$scope.myform.form_fields[i].fieldType||$scope.myform.form_fields[i].deletePreserved||($scope.myform.form_fields[i].fieldValue=$scope.myform.form_fields[i].fieldValue.option_value);setTimeout(function(){$scope.submitPromise=$http.post("/forms/"+$scope.myform._id,form).success(function(data,status,headers){console.log($scope.myform.form_fields[0]),$scope.myform.submitted=!0,$scope.loading=!1,SendVisitorData.send($scope.myform,getActiveField(),_timeElapsed)}).error(function(error){$scope.loading=!1,console.error(error),$scope.error=error.message})},500)},$scope.reloadForm()}]}}]),angular.module("view-form").service("CurrentForm",function(){var _form={};this.getForm=function(){return _form},this.setForm=function(form){_form=form}}),angular.module("view-form").factory("Forms",["$resource","FORM_URL",function($resource,FORM_URL){return $resource(FORM_URL,{formId:"@_id"},{query:{method:"GET",isArray:!0},get:{method:"GET",transformResponse:function(data,header){var form=angular.fromJson(data);return form.visible_form_fields=_.filter(form.form_fields,function(field){return field.deletePreserved===!1}),form}},update:{method:"PUT"},save:{method:"POST"}})}]),function(){function Socket($timeout,$window){function connect(url){service.socket=io(url,{transports:["websocket","polling"]})}function emit(eventName,data){service.socket&&service.socket.emit(eventName,data)}function on(eventName,callback){service.socket&&service.socket.on(eventName,function(data){$timeout(function(){callback(data)})})}function removeListener(eventName){service.socket&&service.socket.removeListener(eventName)}var service={connect:connect,emit:emit,on:on,removeListener:removeListener,socket:null};return connect(window.location.protocol+"//"+window.location.hostname+":"+$window.socketPort),service}angular.module("view-form").factory("Socket",Socket),Socket.$inject=["$timeout","$window"]}(),angular.module("view-form").service("TimeCounter",[function(){var _startTime,_endTime=null;this.timeSpent=0,this.restartClock=function(){_startTime=Date.now(),_endTime=null},this.getTimeElapsed=function(){return _startTime?Math.abs(Date.now().valueOf()-_startTime.valueOf())/1e3:void 0},this.stopClock=function(){return _startTime&&null===_endTime?(_endTime=Date.now(),this.timeSpent=Math.abs(_endTime.valueOf()-_startTime.valueOf())/1e3,this._startTime=this._endTime=null,this.timeSpent):new Error("Clock has not been started")},this.clockStarted=function(){return!!this._startTime}}]); \ No newline at end of file diff --git a/public/form_modules/forms/tests/unit/controllers/admin-form.client.controller.test.js b/public/form_modules/forms/tests/unit/controllers/admin-form.client.controller.test.js deleted file mode 100644 index 7530812f..00000000 --- a/public/form_modules/forms/tests/unit/controllers/admin-form.client.controller.test.js +++ /dev/null @@ -1,256 +0,0 @@ -'use strict'; - -(function() { - // Forms Controller Spec - describe('AdminForm Controller Tests', function() { - // Initialize global variables - var AdminFormController, - createAdminFormController, - 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, _id:'56340745f59a6fc9e22028e9'}, - {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false, _id:'5c9e22028e907634f45f59a6'}, - {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false, _id:'56e90745f5934fc9e22028a6'} - ], - _id: '525a8422f6d0f87f0e407a33' - }; - - var expectedForm = { - title: 'Form Title', - admin: 'ed873933b1f1dea0ce12fab9', - language: 'english', - form_fields: [ - {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false, _id:'56340745f59a6fc9e22028e9'}, - {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false, _id:'5c9e22028e907634f45f59a6'}, - {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false, _id:'56e90745f5934fc9e22028a6'} - ], - visible_form_fields: [ - {fieldType:'textfield', title:'First Name', fieldValue: '', deletePreserved: false, _id:'56340745f59a6fc9e22028e9'}, - {fieldType:'checkbox', title:'nascar', fieldValue: '', deletePreserved: false, _id:'5c9e22028e907634f45f59a6'}, - {fieldType:'checkbox', title:'hockey', fieldValue: '', deletePreserved: false, _id:'56e90745f5934fc9e22028a6'} - ], - _id: '525a8422f6d0f87f0e407a33' - }; - - var newFakeModal = function(){ - var result = { - opened: true, - result: { - then: function(confirmCallback, cancelCallback) { - //Store the callbacks for later when the user clicks on the OK or Cancel button of the dialog - this.confirmCallBack = confirmCallback; - this.cancelCallback = cancelCallback; - } - }, - close: function( item ) { - //The user clicked OK on the modal dialog, call the stored confirm callback with the selected item - this.opened = false; - this.result.confirmCallBack( item ); - }, - dismiss: function( type ) { - //The user clicked cancel on the modal dialog, call the stored cancel callback - this.opened = false; - this.result.cancelCallback( type ); - } - }; - return result; - }; - - //Mock Users Service - beforeEach(module(function($provide) { - $provide.service('myForm', function($q) { - return sampleForm; - }); - })); - - - // 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; - } - }; - }); - })); - - - //Mock $uibModal - beforeEach(inject(function($uibModal) { - var modal = newFakeModal(); - spyOn($uibModal, 'open').and.returnValue(modal); - //spyOn($uibModal, 'close').and.callFake(modal.close()); - })); - - // 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(); - - //Set CurrentForm - CurrentForm.setForm(sampleForm); - - // 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. - createAdminFormController = function(){ - return $controller('AdminFormController', { $scope: scope }); - }; - })); - - 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.removeCurrentForm() with valid form data should send a DELETE request with the id of form', function() { - var controller = createAdminFormController(); - - //Set $state transition - $state.expectTransitionTo('listForms'); - - // Set DELETE response - $httpBackend.expect('DELETE', /^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm); - - //Run controller functionality - scope.openDeleteModal(); - scope.removeCurrentForm(); - - $httpBackend.flush(); - $state.ensureAllTransitionsHappened(); - }); - - it('$scope.update() should send a PUT request with the id of form', function() { - var controller = createAdminFormController(); - - //Set PUT response - $httpBackend.expect('PUT', /^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm); - - //Run controller functionality - scope.update(false, null); - - $httpBackend.flush(); - }); - - it('$scope.openDeleteModal() should open scope.deleteModal', function() { - var controller = createAdminFormController(); - - //Run controller functionality - scope.openDeleteModal(); - console.log(scope.deleteModal); - expect(scope.deleteModal.opened).toEqual(true); - }); - - it('$scope.cancelDeleteModal() should close $scope.deleteModal', inject(function($uibModal) { - var controller = createAdminFormController(); - - //Run controller functionality - scope.openDeleteModal(); - - //Run controller functionality - scope.cancelDeleteModal(); - expect( scope.deleteModal.opened ).toEqual(false); - })); - }); -}()); \ No newline at end of file diff --git a/public/form_modules/forms/tests/unit/controllers/list-forms.client.controller.test.js b/public/form_modules/forms/tests/unit/controllers/list-forms.client.controller.test.js deleted file mode 100644 index c89e73cf..00000000 --- a/public/form_modules/forms/tests/unit/controllers/list-forms.client.controller.test.js +++ /dev/null @@ -1,224 +0,0 @@ -'use strict'; - -(function() { - // Forms Controller Spec - describe('ListForms Controller Tests', function() { - // Initialize global variables - var ListFormsController, - createListFormsController, - scope, - $httpBackend, - $stateParams, - $location, - $state; - - 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 sampleFormList = [{ - title: 'Form Title1', - 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' - },{ - title: 'Form Title2', - admin: '39223933b1f1dea0ce12fab9', - 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: '52f6d0f87f5a407a384220e3' - },{ - title: 'Form Title3', - admin: '2fab9ed873937f0e1dea0ce1', - 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: '922f6d0f87fed8730e4e1233' - } - ]; - - - // 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('myForm', function($q) { - return sampleForm; - }); - })); - - - // 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(); - - //Set CurrentForm - CurrentForm.setForm(sampleForm); - - // 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. - createListFormsController = function(){ - return $controller('ListFormsController', { $scope: scope }); - }; - })); - - it('$scope.findAll() should query all User\'s Forms', inject(function(Forms) { - - var controller = createListFormsController(); - - // Set GET response - $httpBackend.expectGET(/^(\/forms)$/).respond(200, sampleFormList); - - // Run controller functionality - scope.findAll(); - $httpBackend.flush(); - - // Test scope value - expect( scope.myforms ).toEqualData(sampleFormList); - })); - - it('$scope.duplicateForm() should duplicate a Form', inject(function(Forms) { - - var dupSampleForm = sampleFormList[2], - dupSampleForm_index = 3, - newSampleFormList = _.clone(sampleFormList); - dupSampleForm._id = 'a02df75b44c1d26b6a5e05b8'; - newSampleFormList.splice(3, 0, dupSampleForm); - - var controller = createListFormsController(); - - // Set GET response - $httpBackend.expectGET(/^(\/forms)$/).respond(200, sampleFormList); - // Run controller functionality - scope.findAll(); - $httpBackend.flush(); - - // Set GET response - $httpBackend.expect('POST', '/forms').respond(200, dupSampleForm); - // Run controller functionality - scope.duplicateForm(2); - $httpBackend.flush(); - - // Test scope value - expect( scope.myforms.length ).toEqual(newSampleFormList.length); - for(var i=0; i'); - $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.uploadPDF() should upload a pdf file', function() { - // expect(scope.isInitialized).toBeDefined() - // expect(scope.log).toEqual(''); - - expect(scope.pdfLoading).toBe(false); - - //Set POST response - $httpBackend.when('POST', '/upload/pdf').respond(pdfObj); - - var files = [{}]; - scope.uploadPDF(files); - - $httpBackend.flush(); - expect(scope.myform.pdf).toEqualData(pdfObj); - }); - - it('$scope.removePDF() should removed uploaded pdf file', function() { - // expect(scope.isInitialized).toBeDefined() - // expect(scope.log).toEqual(''); - - scope.myform.pdf = pdfObj; - scope.myform.isGenerated = true; - scope.myform.autofillPDFs = true; - - scope.removePDF(); - - expect(scope.myform.pdf).toEqual(null); - expect(scope.myform.isGenerated).toBe(false); - expect(scope.myform.autofillPDFs).toBe(false); - }); - }); -}()); diff --git a/public/form_modules/forms/tests/unit/directives/edit-form-submissions.client.directive.test.js b/public/form_modules/forms/tests/unit/directives/edit-form-submissions.client.directive.test.js deleted file mode 100644 index 63520f48..00000000 --- a/public/form_modules/forms/tests/unit/directives/edit-form-submissions.client.directive.test.js +++ /dev/null @@ -1,200 +0,0 @@ -'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', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed873933b0ce121f1deafab9'}, - {fieldType:'checkbox', title:'nascar', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed83b0ce121f17393deafab9'}, - {fieldType:'checkbox', title:'hockey', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed8317393deab0ce121ffab9'} - ], - 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('module-templates')); - beforeEach(module('stateMock')); - - 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(''); - $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'); - $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 >',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); - - var originalField = _.cloneDeep(scope.myform.form_fields[0]); - originalField.title += ' copy'; - - delete originalField._id; - var copyField = _.cloneDeep(scope.myform.form_fields[1]); - delete copyField._id; - - expect(scope.myform.form_fields.length).toEqual(sampleForm.form_fields.length+1); - expect(originalField).toEqualData(copyField); - }); - - }); - - describe('> Form Field Button >',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 >',function(){ - it('$scope.addOption() should ADD a new option to a field.fieldOptions', function() { - var originalOptionLen = scope.myform.form_fields[1].fieldOptions.length; - - //Run controller methods - scope.addOption(1); - - expect(originalOptionLen+1).toEqual(scope.myform.form_fields[1].fieldOptions.length); - expect(scope.myform.form_fields[1].fieldOptions[0].option_title).toEqualData('Option 0'); - expect(scope.myform.form_fields[1].fieldOptions[0].option_value).toEqualData('Option 0'); - }); - - it('$scope.deleteOption() should DELETE remove option from field.fieldOptions', function() { - //Run controller methods - scope.deleteOption(1, scope.myform.form_fields[1].fieldOptions[0]); - - expect(scope.myform.form_fields[0].fieldOptions.length).toEqual(0); - expect(scope.myform.form_fields[0].fieldOptions[0]).not.toBeDefined(); - }); - }); - }); -}()); \ No newline at end of file diff --git a/public/form_modules/forms/tests/unit/directives/entry-page.client.directive.test.js b/public/form_modules/forms/tests/unit/directives/entry-page.client.directive.test.js deleted file mode 100644 index e24cfc48..00000000 --- a/public/form_modules/forms/tests/unit/directives/entry-page.client.directive.test.js +++ /dev/null @@ -1,93 +0,0 @@ -// 'use strict'; - -// (function() { -// // Forms Controller Spec -// describe('entryPage Directive Tests', function() { -// // Initialize global variables -// var scope, -// $templateCache, -// $httpBackend, -// $compile; - -// var sampleStartPage = { -// showStart: true, -// introTitle: 'Welcome to Form', -// introParagraph: 'Sample intro paragraph', -// buttons:[ -// { -// url: 'http://google.com', -// action: '', -// text: 'Google', -// bgColor: '#ffffff', -// color: '#000000', -// }, -// { -// url: 'http://facebook.com', -// action: '', -// text: 'Facebook', -// bgColor: '#0000ff', -// color: '#000000', -// } -// ] -// }; - - -// // 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(inject(function($rootScope, _$compile_, _$httpBackend_) { -// scope = $rootScope.$new(); -// $compile = _$compile_; - -// // Point global variables to injected services -// $httpBackend = _$httpBackend_; -// })); - - -// it('should be able to render entryPage in html', function() { -// scope.myStartPage = _.cloneDeep(sampleStartPage); -// console.log(scope.myStartPage); -// var element = angular.element(''); -// $compile(element)(scope); -// scope.$digest(); - -// // console.log(element.html()); -// expect(element.html()).not.toEqual('
Start Page
'); -// }); - -// // it('exitStartPage should work for "startPage" type of entryPage', inject(function($rootScope) { -// // scope.myPage = _.cloneDeep(sampleStartPage); -// // var el = angular.element(''); -// // $compile(el)(scope); -// // scope.$digest(); - -// // $httpBackend.whenGET(/.+\.html$/).respond(''); -// // $httpBackend.whenGET('/users/me/').respond(''); - -// // scope = el.isolateScope() || el.scope(); - -// // scope.exitStartPage(); -// // // expect(scope.myStartPage.showStart).toBe(false); -// // expect(el.html()).not.toEqual('
Start Page
'); -// // })); -// }); -// }()); \ No newline at end of file diff --git a/public/form_modules/forms/tests/unit/directives/field-icon.client.directive.test.js b/public/form_modules/forms/tests/unit/directives/field-icon.client.directive.test.js deleted file mode 100644 index 32784832..00000000 --- a/public/form_modules/forms/tests/unit/directives/field-icon.client.directive.test.js +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; - -(function() { - // Forms Controller Spec - describe('FieldIcon Directive Tests', function() { - // Initialize global variables - var scope, - FormFields, - faClasses = { - 'textfield': 'fa fa-pencil-square-o', - 'dropdown': 'fa fa-th-list', - 'date': 'fa fa-calendar', - 'checkbox': 'fa fa-check-square-o', - 'radio': 'fa fa-dot-circle-o', - 'email': 'fa fa-envelope-o', - 'textarea': 'fa fa-pencil-square', - 'legal': 'fa fa-legal', - 'file': 'fa fa-cloud-upload', - 'rating': 'fa fa-star-half-o', - 'link': 'fa fa-link', - 'scale': 'fa fa-sliders', - 'stripe': 'fa fa-credit-card', - 'statement': 'fa fa-quote-left', - 'yes_no': 'fa fa-toggle-on', - 'number': 'fa fa-slack' - }; - - // Load the main application module - beforeEach(module(ApplicationConfiguration.applicationModuleName)); - - beforeEach(inject(function ($rootScope, _FormFields_) { - scope = $rootScope.$new(); - FormFields = _FormFields_; - })); - - it('should be able render all field-icon types', inject(function($compile) { - var currType, currClass; - - for(var i=0; i')(scope); - scope.$digest(); - - expect(currClass).toBeDefined(); - - expect(element.find('i')).not.toBe(null); - expect(element.find('i').hasClass(currClass)).toBe(true); - } - - })); - }); -}()); \ No newline at end of file diff --git a/public/form_modules/forms/tests/unit/directives/field.client.directive.test.js b/public/form_modules/forms/tests/unit/directives/field.client.directive.test.js deleted file mode 100644 index b5527d62..00000000 --- a/public/form_modules/forms/tests/unit/directives/field.client.directive.test.js +++ /dev/null @@ -1,97 +0,0 @@ -'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:'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: '', 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: '', 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) - }; - } - }; - } - }); - }); - - beforeEach(module(function ($sceProvider) { - $sceProvider.enabled(false); - })); - - // Load the main application module - beforeEach(module(ApplicationConfiguration.applicationModuleName)); - beforeEach(module('stateMock')); - beforeEach(module('module-templates')); - - beforeEach(module('ngSanitize', 'ui.select')); - - 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 i=0; i'); - $compile(element)(scope); - scope.$digest(); - - console.log('Actual: '); - console.log(element.html()); - - console.log('\nExpected: '); - - console.log('
'+field.title+'
'); - } - })); - }); -}()); diff --git a/public/form_modules/forms/tests/unit/directives/on-finish-render.client.directive.test.js b/public/form_modules/forms/tests/unit/directives/on-finish-render.client.directive.test.js deleted file mode 100644 index 274f4acb..00000000 --- a/public/form_modules/forms/tests/unit/directives/on-finish-render.client.directive.test.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; - -(function() { - // Forms Controller Spec - describe('onFinishRender Directive Tests', function() { - // Initialize global variables - var scope, - FormFields; - - // Load the main application module - beforeEach(module(ApplicationConfiguration.applicationModuleName)); - - beforeEach(inject(function ($rootScope, _FormFields_) { - scope = $rootScope.$new(); - FormFields = _FormFields_; - spyOn($rootScope, '$broadcast'); - - })); - - it('should emit Custom "Finished" and "Started" events on ng-repeat', inject(function($compile, $rootScope) { - - scope.myfields = FormFields.types; - - var e = $compile('
{{item.name}}
')(scope); - scope.$digest(); - - //run code to test - expect($rootScope.$broadcast).toHaveBeenCalledWith('editFormFields Started'); - expect(scope.$broadcast).toHaveBeenCalledWith('editFormFields Finished'); - })); - - it('should emit "ngRepeat Finished" and "ngRepeat Started" events on ng-repeat when attr is not set to string', inject(function($compile, $rootScope) { - - // console.log(FormFields.types); - scope.myfields = FormFields.types; - - var e = $compile('
{{item.name}}
')(scope); - scope.$digest(); - - //run code to test - expect($rootScope.$broadcast).toHaveBeenCalledWith('ngRepeat Started'); - expect(scope.$broadcast).toHaveBeenCalledWith('ngRepeat Finished'); - })); - - }); -}()); \ No newline at end of file diff --git a/public/form_modules/forms/tests/unit/directives/submit-form.client.directive.test.js b/public/form_modules/forms/tests/unit/directives/submit-form.client.directive.test.js deleted file mode 100644 index db46b05c..00000000 --- a/public/form_modules/forms/tests/unit/directives/submit-form.client.directive.test.js +++ /dev/null @@ -1,203 +0,0 @@ -'use strict'; - -(function() { - // Forms Controller Spec - describe('SubmitForm Directive-Controller Tests', function() { - // Initialize global variables - var 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, _id: 'ed873933b0ce121f1deafab9'}, - {fieldType:'checkbox', title:'nascar', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed83b0ce121f17393deafab9'}, - {fieldType:'checkbox', title:'hockey', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed8317393deab0ce121ffab9'} ], - visible_form_fields: [ - {fieldType:'textfield', title:'First Name', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed873933b0ce121f1deafab9'}, - {fieldType:'checkbox', title:'nascar', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed83b0ce121f17393deafab9'}, - {fieldType:'checkbox', title:'hockey', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed8317393deab0ce121ffab9'} ], - 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, _id: 'ed873933b0ce121f1deafab9'}, - {fieldType:'yes_no', title:'Do you like nascar', fieldValue: true, deletePreserved: false, _id: 'ed83b0ce121f17393deafab9'}, - {fieldType:'yes_no', title:'Do you like hockey', fieldValue: false, deletePreserved: false, _id: 'ed8317393deab0ce121ffab9'} - ], - 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('module-templates')); - beforeEach(module('stateMock')); - - 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. - var el = angular.element(''); - $compile(el)(tmp_scope); - tmp_scope.$digest(); - $rootScope.$digest(); - - //Grab controller instance - controller = el.controller(); - - //Grab scope. Depends on type of scope. - //See angular.element documentation. - scope = el.isolateScope() || el.scope(); - - console.log(scope); - })); - - var Validator = (function() { - return { - hasMinimumFields: function(entry) { - return !_.isEmpty(entry._id) && !_.isEmpty(entry.title); - }, - isNewForm: function(entry) { - return this.hasMinimumFields(entry); - } - }; - })(); - - - it('$scope.submitForm() 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); - }; - - //Set expected HTTP requests - $httpBackend.expect('POST',/^(\/forms\/)([0-9a-fA-F]{24})$/, data).respond(200); - - //Run Controller Logic to Test - scope.submitForm(); - - $httpBackend.flush(); - - setTimeout(function(){ - expect(scope.myform.submitted).toBe(true); - expect(scope.error).toEqual(''); - }, 25); - }); - - it('$scope.reloadForm() should reset and reload form', function(){ - scope.submitForm(); - scope.reloadForm(); - - expect(scope.myform.submitted).toBe(false); - for(var i=0; i 0){ - var expectedState = this.expectedTransitions.shift(); - if(expectedState !== stateName){ - throw Error('Expected transition to state: ' + expectedState + ' but transitioned to ' + stateName ); - } - }else{ - throw Error('No more transitions were expected! Tried to transition to '+ stateName ); - } - console.log('Mock transition to: ' + stateName); - var deferred = $q.defer(); - var promise = deferred.promise; - deferred.resolve(); - return promise; - }; - - this.go = this.transitionTo; - this.expectTransitionTo = function(stateName){ - this.expectedTransitions.push(stateName); - }; - - this.ensureAllTransitionsHappened = function(){ - if(this.expectedTransitions.length > 0){ - throw Error('Not all transitions happened!'); - } - }; -}); \ No newline at end of file