diff --git a/app/controllers/core.server.controller.js b/app/controllers/core.server.controller.js index 5d5c6e16..eb620c15 100755 --- a/app/controllers/core.server.controller.js +++ b/app/controllers/core.server.controller.js @@ -11,3 +11,10 @@ exports.index = function(req, res) { request: req }); }; + +exports.form = function(req, res) { + res.render('form', { + user: req.user || null, + request: req + }); +}; diff --git a/app/controllers/forms.server.controller.js b/app/controllers/forms.server.controller.js index 0c7b2aa5..d121a098 100644 --- a/app/controllers/forms.server.controller.js +++ b/app/controllers/forms.server.controller.js @@ -285,7 +285,25 @@ exports.read = function(req, res) { var newForm = req.form.toJSON({virtuals : true}); newForm.plugins.oscarhost.settings.validUpdateTypes = validUpdateTypes; - res.json(newForm); + if(newForm){ + return res.json(newForm); + } + + if (req.userId) { + if(req.form.admin._id+'' === req.userId+''){ + return res.json(newForm); + } + return res.status(404).send({ + message: 'Form Does Not Exist' + }); + }else { + if(newForm) return res.json(newForm); + } + + /*return res.status(404).send({ + message: 'Form Does Not Exist' + });*/ + }; /** diff --git a/app/controllers/users/users.authentication.server.controller.js b/app/controllers/users/users.authentication.server.controller.js index e95b3bb4..f7a3002c 100755 --- a/app/controllers/users/users.authentication.server.controller.js +++ b/app/controllers/users/users.authentication.server.controller.js @@ -102,14 +102,12 @@ exports.signup = function(req, res) { // For security measures we remove the roles from the req.body object if (req.body) { delete req.body.roles; - console.log(req.body); // Init Variables var user = new User(req.body); // Add missing user fields user.provider = 'local'; - user.username = user.email; // Then save the temporary user nev.createTempUser(user, function (err, newTempUser) { diff --git a/app/controllers/users/users.profile.server.controller.js b/app/controllers/users/users.profile.server.controller.js index dc2d0132..56089804 100755 --- a/app/controllers/users/users.profile.server.controller.js +++ b/app/controllers/users/users.profile.server.controller.js @@ -24,7 +24,6 @@ exports.update = function(req, res) { // Merge existing user user = _.extend(user, req.body); user.updated = Date.now(); - // user.displayName = user.firstName + ' ' + user.lastName; user.save(function(err) { if (err) { diff --git a/app/models/form.server.model.js b/app/models/form.server.model.js index 44a9b038..6ac9f2d6 100644 --- a/app/models/form.server.model.js +++ b/app/models/form.server.model.js @@ -54,12 +54,10 @@ var VisitorDataSchema = new Schema({ type: Schema.Types.ObjectId }, timeElapsed: { - type: Number, - required: true + type: Number }, isSubmitted: { - type: Boolean, - required: true + type: Boolean }, language: { type: String diff --git a/app/models/user.server.model.js b/app/models/user.server.model.js index de43a8e4..51fa4f0f 100755 --- a/app/models/user.server.model.js +++ b/app/models/user.server.model.js @@ -128,7 +128,6 @@ UserSchema.plugin(mUtilities.timestamp, { //Create folder for user's pdfs UserSchema.pre('save', function (next) { - this.username = this.email; if(process.env.NODE_ENV === 'local-development'){ var newDestination = path.join(config.pdfUploadPath, this.username.replace(/ /g,'')), stat = null; diff --git a/app/routes/core.server.routes.js b/app/routes/core.server.routes.js index 71388226..c8077872 100755 --- a/app/routes/core.server.routes.js +++ b/app/routes/core.server.routes.js @@ -1,7 +1,16 @@ 'use strict'; +/** + * Module dependencies. + */ +var forms = require('../../app/controllers/forms.server.controller'), + core = require('../../app/controllers/core.server.controller'); + module.exports = function(app) { // Root routing - var core = require('../../app/controllers/core.server.controller'); app.route('/').get(core.index); + app.route('/subdomain/([a-zA-Z0-9]+)/').get(core.form); + app.route('/subdomain/*/forms/:formId([a-zA-Z0-9]+)') + .get(forms.read) + .post(forms.createSubmission); }; diff --git a/app/views/form.server.view.html b/app/views/form.server.view.html new file mode 100644 index 00000000..ec1cb129 --- /dev/null +++ b/app/views/form.server.view.html @@ -0,0 +1,133 @@ + + + + + {{title}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% for bowerCssFile in bowerCssFiles %} + + {% endfor %} + + + + + + + + + {% for cssFile in cssFiles %} + + {% endfor %} + + + + + + + + + +
+
+
+ + + + + + + + + + + + +{% for bowerJSFile in bowerJSFiles %} + +{% endfor %} + + + + +{% for jsFile in formJSFiles %} + +{% endfor %} + + +{% if process.env.NODE_ENV === 'development' %} + + +{% endif %} + + + + + + + + + + + + diff --git a/app/views/layout.server.view.html b/app/views/layout.server.view.html index 212a3b84..bbec12de 100755 --- a/app/views/layout.server.view.html +++ b/app/views/layout.server.view.html @@ -31,16 +31,16 @@ - + - + {% for bowerCssFile in bowerCssFiles %} {% endfor %} - - - + + +

View Live Preview Form View Live Preview
"); - $templateCache.put("../public/modules/forms/views/list-forms.client.view.html", - "

Create a new form
Name
Language

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

{{ 'VIEW' | translate }} {{ 'LIVE' | translate }} {{ 'PREVIEW' | translate }} {{ 'FORM' | translate }} View {{ 'LIVE' | translate }} {{ 'PREVIEW' | translate }}
"); + $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("../public/modules/forms/views/adminTabs/analyze.html", + $templateCache.put("modules/forms/admin/views/adminTabs/analyze.html", ""); - $templateCache.put("../public/modules/forms/views/adminTabs/configure.html", + $templateCache.put("modules/forms/admin/views/adminTabs/configure.html", ""); - $templateCache.put("../public/modules/forms/views/adminTabs/create.html", + $templateCache.put("modules/forms/admin/views/adminTabs/create.html", ""); - $templateCache.put("../public/modules/forms/views/adminTabs/design.html", - "

Change how your Form Looks

Change how your Form Looks

Background Color
Question Text Color
Answer Text Color
Button Background Color
Button Text Color
"); - $templateCache.put("../public/modules/forms/views/directiveViews/cgBusy/update-form-message-TypeA.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("../public/modules/forms/views/directiveViews/cgBusy/update-form-message-TypeB.html", + $templateCache.put("modules/forms/admin/views/directiveViews/cgBusy/update-form-message-TypeB.html", "
{{$message}}
"); - $templateCache.put("../public/modules/forms/views/directiveViews/entryPage/startPage.html", - "

{{pageData.introTitle}}

{{pageData.introParagraph}}

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

{{index+1}} {{field.title}} optional

{{field.description}}

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

{{index+1}} {{field.title}} optional

{{field.description}}


"); - $templateCache.put("../public/modules/forms/views/directiveViews/field/hidden.html", + $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("../public/modules/forms/views/directiveViews/field/legal.html", - "

{{index+1}} {{field.title}} optional


{{field.description}}


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

{{index+1}} {{field.title}} optional

{{field.description}}


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

{{index+1}} {{field.title}} optional

{{field.description}}

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

{{field.title}}

{{field.description}}

{{field.description}}


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

{{index+1}} {{field.title}} optional

{{field.description}}

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

{{index+1}} {{field.title}} (optional)

{{field.description}}

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

{{index+1}} {{field.title}} optional

{{field.description}}


"); - $templateCache.put("../public/modules/forms/views/directiveViews/form/configure-form.client.view.html", - "

PDF Generation/EMR

PDF Generation/EMR

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


Advanced Settings

Advanced Settings

Form Name
Form Status
Google Analytics Tracking Code
Language
* required
Display Form Footer?
Display Start Page?
"); - $templateCache.put("../public/modules/forms/views/directiveViews/form/edit-form.client.view.html", - "

Click to Add New Field

Add New Field

Add Field

Start Page

Preview Start Page

    {{myform.startPage.introTitle}}

    {{myform.startPage.introParagraph}}

Edit Start Page


Intro Title:
Intro Paragraph:
\n" + - "
\n" + - "\n" + - "

\n" + - "
\n" + - "
Options:
\n" + - "
\n" + - "
\n" + - " \n" + - "\n" + - " \n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - "\n" + - "\n" + - "

\n" + - "
\n" + - "
Number of Steps:
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "
Shape:
\n" + - "
\n" + - " \n" + - "
\n" + - "
\n" + - "\n" + - "

\n" + - "\n" + - "
\n" + - "
Required:
\n" + - "
\n" + - " \n" + - "\n" + - " \n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - "
Disabled:
\n" + - "
\n" + - " \n" + - "\n" + - " \n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - " \n" + - "\n" + - "
\n" + - "
\n" + - "

\n" + - " Click on Fields to add them here\n" + - "

\n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - " \n" + - "
\n" + - "\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "\n" + - "
\n" + - "
\n" + - "
\n" + - " \n" + - " \n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "
\n" + - "\n" + - ""); - $templateCache.put("../public/modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html", - "
Total Views: {{myform.analytics.views}}
Submissions: {{myform.analytics.submissions}}
Conversion Rate: {{myform.analytics.conversionRate}}%

Field Title
Field Views
User dropoff rate at this field
{{fieldStats.field.title}}
{{fieldStats.totalViews}}
{{fieldStats.dropoffRate}}%

#{{value.title}}OscarEMR User ProfilePercentage CompleteTime ElapsedDeviceLocationIP AddressDate Submitted (UTC)Generated PDF
{{$index+1}}{{field.fieldValue.option_value}} {{field.fieldValue}}User Profile #{{row.oscarDemoNum}}{{row.percentageComplete}}%{{row.timeElapsed}}{{row.device.name}}, {{row.device.type}}{{row.geoLocation.city}}, {{row.geoLocation.country}}{{row.ipAddr}}{{row.created | date:'yyyy-MM-dd HH:mm:ss'}}Generated PDF
"); - $templateCache.put("../public/modules/forms/views/directiveViews/form/submit-form.client.view.html", - "
{{form_fields_count - (myform | formValidity)}} answer(s) need completing
press ENTER

{{myform | formValidity}} out of {{form_fields_count}} answered

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

You need to be logged in to access this page

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

Sign into your account

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

Signup Successful

You've successfully registered an account at TellForm.

But your account is not activated yet



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

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

Signup with your email

Couldn't submit form due to errors:

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

Restore your password

Enter your account email.

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

Password reset is invalid

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

Password successfully reset

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

Reset your password

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

Change your password


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

Edit your profile

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

Language
Email (also your username)
"); - $templateCache.put("../public/modules/users/views/settings/social-accounts.client.view.html", + $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", + "
{{ 'COMPLETING_NEEDED' | translate:translateAdvancementData }}
{{ 'ENTER' | translate }}

{{ 'ADVANCEMENT' | translate:translateAdvancementData }}

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

{{ 'SIGNIN_HEADER_TEXT' | translate }}

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_HEADER_TEXT' | translate }}

{{'SIGNUP_ERROR_TEXT' | translate}}:
{{ '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("../public/modules/users/views/verify/resend-verify-email.client.view.html", - "

Resend your account verification email

Enter your account email.

{{error}}

Verification Email has been Sent

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

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

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

Account successfuly activated

Continue to login page

Verification link is invalid or has expired

Resend your verification email Signin to your account
"); + $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'; @@ -771,6 +482,64 @@ angular.module('core').config(['$stateProvider', '$urlRouterProvider', } ]); +angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', '$state', '$stateParams', + function($rootScope, Auth, $state, $stateParams) { + + $rootScope.$state = $state; + $rootScope.$stateParams = $stateParams; + + // add previous state property + $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) { + $state.previous = fromState; + //console.log('toState: '+toState.name); + + var statesToIgnore = ['home', 'signin', 'resendVerifyEmail', 'verify', 'signup', 'signup-success', 'forgot', 'reset-invalid', 'reset', 'reset-success']; + + //Redirect to listForms if user is authenticated + if(statesToIgnore.indexOf(toState.name) > 0){ + if(Auth.isAuthenticated()){ + event.preventDefault(); // stop current execution + //console.log('go to forms'); + $state.go('listForms'); // go to listForms page + } + } + //Redirect to 'signup' route if user is not authenticated + else if(toState.name !== 'access_denied' && !Auth.isAuthenticated() && toState.name !== 'submitForm'){ + console.log('go to signup'); + event.preventDefault(); // stop current execution + $state.go('listForms'); // go to listForms page + } + + }); + + } +]); + +//Page access/authorization logic +angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', 'User', 'Authorizer', '$state', '$stateParams', + function($rootScope, Auth, User, Authorizer, $state, $stateParams) { + $rootScope.$on('$stateChangeStart', function(event, next) { + var authenticator, permissions, user; + permissions = next && next.data && next.data.permissions ? next.data.permissions : null; + + Auth.ensureHasCurrentUser(User); + user = Auth.currentUser; + + if(user){ + authenticator = new Authorizer(user); + //console.log('access denied: '+!authenticator.canAccess(permissions)); + //console.log(permissions); + if( (permissions !== null) ){ + if( !authenticator.canAccess(permissions) ){ + event.preventDefault(); + //console.log('access denied'); + $state.go('access_denied'); + } + } + } + }); + }]); + 'use strict'; angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User', '$window', '$translate', '$locale', @@ -1057,6 +826,16 @@ angular.module('core').service('Menus', [ 'use strict'; +angular.module('core').factory('subdomain', ['$location', function ($location) { + var host = $location.host(); + if (host.indexOf('.') < 0) + return null; + else + return host.split('.')[0]; +}]); + +'use strict'; + // Configuring the Forms drop-down menus angular.module('forms').run(['Menus', function(Menus) { @@ -1111,22 +890,7 @@ angular.module('forms').config(['$stateProvider', state('listForms', { url: '/forms', templateUrl: 'modules/forms/admin/views/list-forms.client.view.html' - }). - state('submitForm', { - url: '/forms/:formId', - templateUrl: 'modules/forms/base/views/submit-form.client.view.html', - data: { - hideNav: true - }, - resolve: { - Forms: 'Forms', - myForm: ["Forms", "$stateParams", function (Forms, $stateParams) { - return Forms.get({formId: $stateParams.formId}).$promise; - }] - }, - controller: 'SubmitFormController', - controllerAs: 'ctrl' - }).state('viewForm', { + }).state('viewForm', { url: '/forms/:formId/admin', templateUrl: 'modules/forms/admin/views/admin-form.client.view.html', data: { @@ -1437,7 +1201,6 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca $scope.error = ''; $scope.signin = function() { - $scope.credentials.email = $scope.credentials.username; User.login($scope.credentials).then( function(response) { Auth.login(response); @@ -1926,6 +1689,8 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope CurrentForm.setForm($scope.myform); + $scope.formURL = $scope.myform.admin.username + '.' + window.location.host; + $scope.tabData = [ { heading: $filter('translate')('CREATE_TAB'), @@ -2051,7 +1816,7 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope $scope.forms = {}; $scope.showCreateModal = false; - $scope.languageRegExp = $scope.myPt = { + $rootScope.languageRegExp = { regExp: /[@!#$%^&*()\-+={}\[\]|\\/'";:`.,~№?<>]+/i, test: function(val) { return !this.regExp.test(val); @@ -2699,7 +2464,7 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', completion: 0, average_time: 0, total_time: 0 - } + }; }; var stats = { @@ -3559,6 +3324,11 @@ angular.module('users').config(['$translateProvider', function ($translateProvid LANGUAGE_LABEL: 'Language', EMAIL_LABEL: 'Email', + SIGNUP_HEADER_TEXT: 'Sign up with your email', + SIGNIN_HEADER_TEXT: 'Signup in with your email', + + SIGNUP_ERROR_TEXT: 'Couldn\'t complete registration due to errors', + UPDATE_PROFILE_BTN: 'Update Profile', PROFILE_SAVE_SUCCESS: 'Profile saved successfully', PROFILE_SAVE_ERROR: 'Could\'t Save Your Profile.', @@ -3571,10 +3341,10 @@ angular.module('users').config(['$translateProvider', function ($translateProvid SAVE_PASSWORD_BTN: 'Save Password', SUCCESS_HEADER: 'Signup Successful', - SUCCESS_TEXT: 'You\'ve successfully registered an account at TellForm.', + SUCCESS_TEXT: 'You’ve successfully registered an account at TellForm.', VERIFICATION_EMAIL_SENT: 'A verification email has been sent to', NOT_ACTIVATED_YET: 'But your account is not activated yet', - BEFORE_YOU_CONTINUE: 'Before you continue, make sure to check your email for our verification. If you don\'t receive it within 24h drop us a line at ', + BEFORE_YOU_CONTINUE: 'Before you continue, make sure to check your email for our verification. If you don’t receive it within 24h drop us a line at ', CHECK_YOUR_EMAIL: 'Check your email and click on the activation link to activate your account. If you have any questions drop us a line at', PASSWORD_RESTORE_HEADER: 'Restore your password', @@ -3603,49 +3373,49 @@ angular.module('users').config(['$translateProvider', function ($translateProvid angular.module('users').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('en', { - ACCESS_DENIED_TEXT: 'Vouz est pas autorisé pour accese cete page.', - USERNAME_LABEL: 'Nom de Compte', - PASSWORD_LABEL: 'Mot de Pass', - CURRENT_PASSWORD_LABEL: 'Current Password', - NEW_PASSWORD_LABEL: 'Nouveau Mot de Pass Password', - VERIFY_PASSWORD_LABEL: 'Verify Password', - UPDATE_PASSWORD_LABEL: 'Update Password', - FIRST_NAME_LABEL: 'Premiere Nom Name', - LAST_NAME_LABEL: 'Surnom', - LANGUAGE_LABEL: 'Language', + ACCESS_DENIED_TEXT: 'Vouz n’êtes pas autorisé à accéder à cette page.', + USERNAME_LABEL: 'Nom d’utilisateur', + PASSWORD_LABEL: 'Mot de Passe', + CURRENT_PASSWORD_LABEL: 'Mot de passe actuel', + NEW_PASSWORD_LABEL: 'Nouveau Mot de Passe', + VERIFY_PASSWORD_LABEL: 'Vérifier le mot de passe', + UPDATE_PASSWORD_LABEL: 'Mettre à jour le mot de passe', + FIRST_NAME_LABEL: 'Prénom', + LAST_NAME_LABEL: 'Nom', + LANGUAGE_LABEL: 'Langue', EMAIL_LABEL: 'Email', - UPDATE_PROFILE_BTN: 'Modifier Profile', - PROFILE_SAVE_SUCCESS: 'Profile saved successfully', - PROFILE_SAVE_ERROR: 'Erreur: On peux pas enregistré votre Profile.', + UPDATE_PROFILE_BTN: 'Modifier le Profil', + PROFILE_SAVE_SUCCESS: 'Profil enregistré avec succès', + PROFILE_SAVE_ERROR: 'Erreur: impossible d’enregistrer votre Profile.', - FORGOT_PASSWORD_LINK: 'Oublier votre mot de pass?', - REVERIFY_ACCOUNT_LINK: 'Re-envoyez ton email de verification', + FORGOT_PASSWORD_LINK: 'Mot de passe oublié ?', + REVERIFY_ACCOUNT_LINK: 'Re-envoyez un email de vérification', SIGNIN_BTN: 'Connexion', SIGNUP_BTN: 'Créer un compte', - SAVE_PASSWORD_BTN: 'Enregistreé ton nouveau Mot de Pass', + SAVE_PASSWORD_BTN: 'Enregistrer votre nouveau Mot de Passe', - SUCCESS_HEADER: 'Votre Compte a été enregistré!', - SUCCESS_TEXT: 'Vouz a enregistré un compte a TellForm.', - VERIFICATION_EMAIL_SENT: 'Un email de verification a été envoyer a', + SUCCESS_HEADER: 'Votre Compte a été enregistré !', + SUCCESS_TEXT: 'Votre compte Tellform a été crée avec succès.', + VERIFICATION_EMAIL_SENT: 'Un email de verification a été envoyer à', NOT_ACTIVATED_YET: 'Mais votre compte n\'est pas activé', - BEFORE_YOU_CONTINUE: 'Plutôt que vouz continué, vouz devrez voire ton inbox pour notre message de verification. Si tu receivoir-pas un message de verification dan le prochaine 24h, contactez nous a ', - CHECK_YOUR_EMAIL: 'Check your email and click on the activation link to activate your account. If you have any questions drop us a line at', + BEFORE_YOU_CONTINUE: 'Avant de continuer, vous devez valider votre adresse mail. Merci de vérifier votre boite mail. Si vous ne l’avez pas reçu dans les prochaines 24h, contactez-nous a ', + CHECK_YOUR_EMAIL: 'Vérifiez vos emails, et cliquez sur le lien de validation pour activer votre compte. Si vous avez une question contactez-nous à', - PASSWORD_RESTORE_HEADER: 'Restore your password', - ENTER_YOUR_EMAIL: 'Entrer votre email de compte', + PASSWORD_RESTORE_HEADER: 'Mot de passe perdu', + ENTER_YOUR_EMAIL: 'Entrer votre email', SUBMIT_BTN: 'Enregistrer', ASK_FOR_NEW_PASSWORD: 'Demander un nouveau mot de pass ', - PASSWORD_RESET_INVALID: 'Password reset is invalid', - PASSWORD_RESET_SUCCESS: 'Passport successfully reset', - PASSWORD_CHANGE_SUCCESS: 'Passport successfully changed', + PASSWORD_RESET_INVALID: 'Le nouveau mot de passe est invalid', + PASSWORD_RESET_SUCCESS: 'Mot de passe réinitialisé avec succès', + PASSWORD_CHANGE_SUCCESS: 'Mot de passe enregistré avec succès', - CONTINUE_TO_LOGIN: 'Allez au page de connexion', + CONTINUE_TO_LOGIN: 'Allez à la page de connexion', - VERIFY_SUCCESS: 'Compte est activé!', - VERIFY_ERROR: 'Le fléche de verification est invalid ou expireé' + VERIFY_SUCCESS: 'Votre compte est activé !', + VERIFY_ERROR: 'Le lien de vérification est invalide ou à expiré' }); }]); diff --git a/public/dist/application.min.js b/public/dist/application.min.js index 2357d055..5d95d3bf 100644 --- a/public/dist/application.min.js +++ b/public/dist/application.min.js @@ -1,5 +1,5 @@ -"use strict";function removeDateFieldsFunc(o){function eachObject(v,k){"lastModified"!==k&&"created"!==k||delete clone[k]}for(var clone=_.clone(o),i=0;i0?Auth.isAuthenticated()&&(event.preventDefault(),$state.go("listForms")):"access_denied"===toState.name||Auth.isAuthenticated()||"submitForm"===toState.name||(console.log("go to signup"),event.preventDefault(),$state.go("listForms"))})}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","User","Authorizer","$state","$stateParams",function($rootScope,Auth,User,Authorizer,$state,$stateParams){$rootScope.$on("$stateChangeStart",function(event,next){var authenticator,permissions,user;permissions=next&&next.data&&next.data.permissions?next.data.permissions:null,Auth.ensureHasCurrentUser(User),user=Auth.currentUser,user&&(authenticator=new Authorizer(user),null!=permissions&&(authenticator.canAccess(permissions)||(event.preventDefault(),$state.go("access_denied"))))})}]),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),angular.module("NodeForm.templates",[]).run(["$templateCache",function($templateCache){$templateCache.put("../public/modules/core/views/header.client.view.html",''),$templateCache.put("../public/modules/core/views/home.client.view.html",'

Craft beautiful forms in seconds.

Create your next ______.

Tell a story with a form.

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

Create a new form
Name
Language

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

{{pageData.introTitle}}

{{pageData.introParagraph}}

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

{{index+1}} {{field.title}} optional

{{field.description}}

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/dropdown.html",'
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/hidden.html",''),$templateCache.put("../public/modules/forms/views/directiveViews/field/legal.html",'
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/radio.html",'

{{index+1}} {{field.title}} optional

{{field.description}}


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

{{index+1}} {{field.title}} optional

{{field.description}}

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

{{field.title}}

{{field.description}}

{{field.description}}


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

{{index+1}} {{field.title}} optional

{{field.description}}

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

{{index+1}} {{field.title}} (optional)

{{field.description}}

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

{{index+1}} {{field.title}} optional

{{field.description}}


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

Edit Start Page


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

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

\n
\n
Number of Steps:
\n
\n \n
\n
\n
Shape:
\n
\n \n
\n
\n\n

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

\n Click on Fields to add them here\n

\n
\n
\n\n
\n \n
\n\n \n \n\n \n
\n
\n\n'),$templateCache.put("../public/modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html",'
Total Views: {{myform.analytics.views}}
Submissions: {{myform.analytics.submissions}}
Conversion Rate: {{myform.analytics.conversionRate}}%

Field Title
Field Views
User dropoff rate at this field
{{fieldStats.field.title}}
{{fieldStats.totalViews}}
{{fieldStats.dropoffRate}}%

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

You need to be logged in to access this page

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

Sign into your account

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

Restore your password

Enter your account email.

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

Password reset is invalid

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

Password successfully reset

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

Reset your password

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

Change your password

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

Edit your profile

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

Connected social accounts:

Connect other social accounts:

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

Resend your account verification email

Enter your account email.

{{error}}

Verification Email has been Sent

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

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

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

Account successfuly activated

Continue to login page

Verification link is invalid or has expired

Resend your verification email Signin to your account
')}]),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.router.tabs","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("forms").config(["$translateProvider",function($translateProvider){$translateProvider.translations("en",{PDF_GENERATION_EMR:"PDF Generation/EMR",SAVE_PDF_SUBMISSIONS:"Save Submissions as PDFs?",UPLOAD_YOUR_PDF:"Upload Your PDF Template",ADVANCED_SETTINGS:"Advanced Settings",FORM_NAME:"Form Name",FORM_STATUS:"Form Status",PUBLIC:"Public",PRIVATE:"Private",GA_TRACKING_CODE:"Google Analytics Tracking Code",DISPLAY_FOOTER:"Display Form Footer?",SAVE_CHANGES:"Save Changes",CANCEL:"Cancel",CREATE_A_NEW_FORM:"Create a new form",CREATE_FORM:"Create form",CREATED_ON:"Created on",ARE_YOU_SURE:"Are you ABSOLUTELY sure?",READ_WARNING:"Unexpected bad things will happen if you don’t read this!",DELETE_WARNING1:"This action CANNOT be undone.This will permanently delete the",DELETE_WARNING2:"form, form submissions and remove all associated pdfs.",DELETE_CONFIRM:"Please type in the name of the form to confirm",I_UNDERSTAND:"I understand the consequences, delete this form",DELETE_FORM_SM:"Delete",DELETE_FORM_MD:"Delete Form",DELETE:"Delete",FORM:"Form",VIEW:"View",LIVE:"Live",PREVIEW:"Preview",ADD_FIELD_LG:"Click to Add New Field",ADD_FIELD_MD:"Add New Field",ADD_FIELD_SM:"Add Field",PREVIEW_START_PAGE:"Preview Start Page",EDIT_START_PAGE:"Edit Start Page",INTRO_TTILE:"Intro Title",INTRO_PARAGRAPH:"Intro Paragraph",INTRO_BTN:"Intro Button",BUTTONS:"Buttons",BUTTON_TEXT:"Text",BUTTON_LINK:"Link",ADD_BUTTON:"Add Button",PREVIEW_FIELD:"Preview Field",EDIT_FIELD:"Edit Field",QUESTION_TITLE:"Question Title",QUESTION_DESCRIPTION:"Question Description",OPTIONS:"Options",ADD_OPTION:"Add Option",NUM_OF_STEPS:"Number of Steps",CLICK_FIELDS_FOOTER:"Click on fields to add them here",TOTAL_VIEWS:"total unique visits",RESPONSES:"responses",COMPLETION_RATE:"completion rate",AVERAGE_TIME_TO_COMPLETE:"avg. completion time",DESKTOP_AND_LAPTOP:"Desktops",TABLETS:"Tablets",PHONES:"Phones",OTHER:"Other",UNIQUE_VISITS:"Unique Visits",FIELD_TITLE:"Field Title",FIELD_VIEWS:"Field Views",FIELD_DROPOFF:"Field Completion",FIELD_RESPONSES:"Field Responses",DELETE_SELECTED:"Delete Selected",EXPORT_TO_EXCEL:"Export to Excel",EXPORT_TO_CSV:"Export to CSV",EXPORT_TO_JSON:"Export to JSON",PERCENTAGE_COMPLETE:"Percentage Complete",TIME_ELAPSED:"Time Elapsed",DEVICE:"Device",LOCATION:"Location",IP_ADDRESS:"IP Address",DATE_SUBMITTED:"Date Submitted",GENERATED_PDF:"Generated PDF",BACKGROUND_COLOR:"Background Color",DESIGN_HEADER:"Change how your Form Looks",QUESTION_TEXT_COLOR:"Question Text Color",ANSWER_TEXT_COLOR:"Answer Text Color",BTN_BACKGROUND_COLOR:"Button Background Color",BTN_TEXT_COLOR:"Button Text Color",CREATE_TAB:"Create",DESIGN_TAB:"Design",CONFIGURE_TAB:"Configure",ANALYZE_TAB:"Analyze"})}]),angular.module("forms").config(["$translateProvider",function($translateProvider){$translateProvider.translations("en",{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"})}]),angular.module("forms").config(["$translateProvider",function($translateProvider){$translateProvider.translations("fr",{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("forms").config(["$translateProvider",function($translateProvider){$translateProvider.translations("de",{FORM_SUCCESS:"Ihre Angaben wurden gespeichert.",REVIEW:"Unvollständig",BACK_TO_FORM:"Zurück zum Formular",EDIT_FORM:"Bearbeiten Sie diese TellForm",CREATE_FORM:"Erstellen Sie eine TellForm",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:"Ich akzeptiere",LEGAL_NO_ACCEPT:"Ich akzeptiere nicht",DELETE:"Entfernen",CANCEL:"Canceln",SUBMIT:"Speichern",UPLOAD_FILE:"Datei versenden",Y:"J",N:"N"})}]),angular.module("forms").config(["$translateProvider",function($translateProvider){$translateProvider.translations("it",{FORM_SUCCESS:"Il formulario è stato inviato con successo!",REVIEW:"Incompleto",BACK_TO_FORM:"Ritorna al formulario",EDIT_FORM:"Modifica questo Tellform",CREATE_FORM:"Creare un TellForm",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:"Accetto",LEGAL_NO_ACCEPT:"Non accetto",DELETE:"Cancella",CANCEL:"Reset",SUBMIT:"Registra",UPLOAD_FILE:"Invia un file",Y:"S",N:"N"})}]),angular.module("forms").config(["$translateProvider",function($translateProvider){$translateProvider.translations("es",{FORM_SUCCESS:"¡El formulario ha sido enviado con éxito!",REVIEW:"Revisar",BACK_TO_FORM:"Regresar al formulario",EDIT_FORM:"Crear un TellForm",CREATE_FORM:"Editar este TellForm",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:"Acepto",LEGAL_NO_ACCEPT:"No acepto",DELETE:"Eliminar",CANCEL:"Cancelar",SUBMIT:"Registrar",UPLOAD_FILE:"Cargar el archivo",Y:"S",N:"N"})}]),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/forms")}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User","$window","$translate","$locale",function($rootScope,$scope,Menus,$state,Auth,User,$window,$translate,$locale){$rootScope.signupDisabled=$window.signupDisabled,$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["en","fr","es","it","de"],console.log($locale.id),$scope.authentication.isAuthenticated()?$rootScope.language=$scope.user.language:$rootScope.language=$locale.id.substring(0,2),$translate.use($rootScope.language),$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("listForms")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),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("core").factory("Socket",Socket),Socket.$inject=["$timeout","$window"]}(),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("secondsToDateTime",[function(){return function(seconds){return new Date(1970,0,1).setSeconds(seconds)}}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field&&"statement"!==field.fieldType&&"rating"!==field.fieldType?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",["$delegate",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate}])}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/admin/views/list-forms.client.view.html"}).state("submitForm",{url:"/forms/:formId",templateUrl:"modules/forms/base/views/submit-form.client.view.html",data:{hideNav:!0},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"SubmitFormController",controllerAs:"ctrl"}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/admin/views/admin-form.client.view.html",data:{permissions:["editForm"]},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"AdminFormController"}).state("viewForm.configure",{url:"/configure",templateUrl:"modules/forms/admin/views/adminTabs/configure.html"}).state("viewForm.design",{url:"/design",templateUrl:"modules/forms/admin/views/adminTabs/design.html"}).state("viewForm.analyze",{url:"/analyze",templateUrl:"modules/forms/admin/views/adminTabs/analyze.html"}).state("viewForm.create",{url:"/create",templateUrl:"modules/forms/admin/views/adminTabs/create.html"})}]),function(){function SendVisitorData(Socket,$state,$http,deviceDetector){function send(form,lastActiveIndex,timeElapsed){var visitorData={referrer:document.referrer,isSubmitted:form.submitted,formId:form._id,lastActiveField:form.form_fields[lastActiveIndex]._id,timeElapsed:timeElapsed,language:window.navigator.userLanguage||window.navigator.language,ipAddr:"",deviceType:""};$http.get("http://jsonip.com/").success(function(response){visitorData.ipAddr=response.ip+""}).error(function(error){console.error("Could not get users's ip")}).then(function(){visitorData.userAgent=deviceDetector.raw,deviceDetector.isTablet()?visitorData.deviceType="tablet":deviceDetector.isMobile()?visitorData.deviceType="phone":visitorData.deviceType="desktop",console.log(visitorData.deviceType),Socket.emit("form-visitor-data",visitorData)})}function init(){Socket.socket||Socket.connect()}var service={send:send};return init(),service}angular.module("forms").factory("SendVisitorData",SendVisitorData),SendVisitorData.$inject=["Socket","$state","$http","deviceDetector"]}(),angular.module("forms").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("forms").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("users").config(["$httpProvider",function($httpProvider){$httpProvider.interceptors.push(["$q","$location",function($q,$location){return{responseError:function(response){return"/users/me"!==$location.path()&&response.config&&"/users/me"!==response.config.url&&(console.log("intercepted rejection of ",response.config.url,response.status),401===response.status?(console.log($location.path()),$location.nextAfterLogin=$location.path(),$location.path("/signin")):403===response.status&&$location.path("/access_denied")),$q.reject(response)}}}])}]),angular.module("users").config(["$stateProvider",function($stateProvider){var checkLoggedin=function($q,$timeout,$state,User,Auth){var deferred=$q.defer();return Auth.currentUser&&Auth.currentUser.email?$timeout(deferred.resolve):Auth.currentUser=User.getCurrent(function(){Auth.login(),$timeout(deferred.resolve())},function(){Auth.logout(),$timeout(deferred.reject()),$state.go("signin",{reload:!0})}),deferred.promise};checkLoggedin.$inject=["$q","$timeout","$state","User","Auth"];var checkSignupDisabled=function($window,$timeout,$q){var deferred=$q.defer();return $timeout($window.signupDisabled?deferred.reject():deferred.resolve()),deferred.promise};checkSignupDisabled.$inject=["$window","$timeout","$q"],$stateProvider.state("profile",{resolve:{loggedin:checkLoggedin},url:"/settings/profile",templateUrl:"modules/users/views/settings/edit-profile.client.view.html"}).state("password",{resolve:{loggedin:checkLoggedin},url:"/settings/password",templateUrl:"modules/users/views/settings/change-password.client.view.html"}).state("accounts",{resolve:{loggedin:checkLoggedin},url:"/settings/accounts",templateUrl:"modules/users/views/settings/social-accounts.client.view.html"}).state("signup",{resolve:{isDisabled:checkSignupDisabled},url:"/signup",templateUrl:"modules/users/views/authentication/signup.client.view.html"}).state("signup-success",{resolve:{isDisabled:checkSignupDisabled},url:"/signup-success",templateUrl:"modules/users/views/authentication/signup-success.client.view.html"}).state("signin",{url:"/signin",templateUrl:"modules/users/views/authentication/signin.client.view.html"}).state("access_denied",{url:"/access_denied",templateUrl:"modules/users/views/authentication/access-denied.client.view.html"}).state("verify",{resolve:{isDisabled:checkSignupDisabled},url:"/verify/:token",templateUrl:"modules/users/views/verify/verify-account.client.view.html"}).state("resendVerifyEmail",{resolve:{isDisabled:checkSignupDisabled},url:"/verify",templateUrl:"modules/users/views/verify/resend-verify-email.client.view.html"}).state("forgot",{url:"/password/forgot",templateUrl:"modules/users/views/password/forgot-password.client.view.html"}).state("reset-invalid",{url:"/password/reset/invalid",templateUrl:"modules/users/views/password/reset-password-invalid.client.view.html"}).state("reset-success",{url:"/password/reset/success",templateUrl:"modules/users/views/password/reset-password-success.client.view.html"}).state("reset",{url:"/password/reset/:token",templateUrl:"modules/users/views/password/reset-password.client.view.html"})}]),angular.module("users").controller("AuthenticationController",["$scope","$location","$state","$rootScope","User","Auth",function($scope,$location,$state,$rootScope,User,Auth){$scope=$rootScope,$scope.credentials={},$scope.error="",$scope.signin=function(){$scope.credentials.email=$scope.credentials.username,User.login($scope.credentials).then(function(response){Auth.login(response),$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),"home"!==$state.previous.name&&"verify"!==$state.previous.name&&""!==$state.previous.name?$state.go($state.previous.name):$state.go("listForms")},function(error){$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user,$scope.error=error,console.log("loginError: "+error)})},$scope.signup=function(){console.log($scope.credentials),User.signup($scope.credentials).then(function(response){console.log("signup-success"),$state.go("signup-success")},function(error){console.log("Error: "),console.log(error),error?($scope.error=error,console.log(error)):console.log("No response received")})}}]),angular.module("users").controller("PasswordController",["$scope","$stateParams","$state","User",function($scope,$stateParams,$state,User){$scope.error="",$scope.askForPasswordReset=function(){User.askForPasswordReset($scope.credentials).then(function(response){$scope.success=response.message,$scope.credentials=null},function(error){$scope.error=error,$scope.credentials=null})},$scope.resetUserPassword=function(){$scope.success=$scope.error=null,User.resetPassword($scope.passwordDetails,$stateParams.token).then(function(response){$scope.success=response.message,$scope.passwordDetails=null,$state.go("reset-success")},function(error){$scope.error=error.message||error,$scope.passwordDetails=null})}}]),angular.module("users").controller("SettingsController",["$scope","$rootScope","$http","$state","Users",function($scope,$rootScope,$http,$state,Users){$scope.user=$rootScope.user,$scope.hasConnectedAdditionalSocialAccounts=function(provider){for(var i in $scope.user.additionalProvidersData)return!0;return!1},$scope.isConnectedSocialAccount=function(provider){return $scope.user.provider===provider||$scope.user.additionalProvidersData&&$scope.user.additionalProvidersData[provider]},$scope.removeUserSocialAccount=function(provider){$scope.success=$scope.error=null,$http["delete"]("/users/accounts",{params:{provider:provider}}).success(function(response){$scope.success=!0,$scope.user=response}).error(function(response){$scope.error=response.message})},$scope.updateUserProfile=function(isValid){if(isValid){$scope.success=$scope.error=null;var user=new Users($scope.user);user.$update(function(response){$scope.success=!0,$scope.user=response},function(response){$scope.error=response.data.message})}else $scope.submitted=!0},$scope.changeUserPassword=function(){$scope.success=$scope.error=null,$http.post("/users/password",$scope.passwordDetails).success(function(response){$scope.success=!0,$scope.passwordDetails=null}).error(function(response){$scope.error=response.message})}}]),angular.module("users").controller("VerifyController",["$scope","$state","$rootScope","User","Auth","$stateParams",function($scope,$state,$rootScope,User,Auth,$stateParams){$scope.isResetSent=!1,$scope.credentials={},$scope.error="",$scope.resendVerifyEmail=function(){User.resendVerifyEmail($scope.credentials.email).then(function(response){console.log(response),$scope.success=response.message,$scope.credentials=null,$scope.isResetSent=!0},function(error){$scope.error=error,$scope.credentials.email=null,$scope.isResetSent=!1})},$scope.validateVerifyToken=function(){$stateParams.token&&(console.log($stateParams.token),User.validateVerifyToken($stateParams.token).then(function(response){console.log("Success: "+response.message),$scope.success=response.message,$scope.isResetSent=!0,$scope.credentials.email=null},function(error){console.log("Error: "+error.message),$scope.isResetSent=!1,$scope.error=error,$scope.credentials.email=null}))}}]),angular.module("users").factory("Auth",["$window",function($window){var userState={isLoggedIn:!1},service={_currentUser:null,get currentUser(){return this._currentUser},ensureHasCurrentUser:function(User){return service._currentUser&&service._currentUser.username?service._currentUser:$window.user?(service._currentUser=$window.user,service._currentUser):void User.getCurrent().then(function(user){return service._currentUser=user,userState.isLoggedIn=!0,$window.user=service._currentUser,service._currentUser},function(response){return userState.isLoggedIn=!1,service._currentUser=null,$window.user=null,console.log("User.getCurrent() err",response),null})},isAuthenticated:function(){return!!service._currentUser},getUserState:function(){return userState},login:function(new_user){userState.isLoggedIn=!0,service._currentUser=new_user},logout:function(){$window.user=null,userState.isLoggedIn=!1,service._currentUser=null}};return service}]),angular.module("users").service("Authorizer",["APP_PERMISSIONS","USER_ROLES",function(APP_PERMISSIONS,USER_ROLES){return function(user){return{canAccess:function(permissions){var i,len,permission;for(angular.isArray(permissions)||(permissions=[permissions]),i=0,len=permissions.length;len>i;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}]),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){ -deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var validTokenRe=/^([A-Za-z0-9]{48})$/g;if(!validTokenRe.test(token))throw new Error("Error token: "+token+" is not a valid verification token");var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]),angular.module("core").config(["$translateProvider",function($translateProvider){$translateProvider.translations("en",{MENU:"MENU",SIGNUP_TAB:"Sign Up",SIGNIN_TAB:"Sign In",SIGNOUT_TAB:"Signout",EDIT_PROFILE:"Edit Profile",MY_FORMS:"My Forms",MY_SETTINGS:"My Settings",CHANGE_PASSWORD:"Change Password"}),$translateProvider.preferredLanguage("en").fallbackLanguage("en").useSanitizeValueStrategy("escape")}]),angular.module("core").config(["$translateProvider",function($translateProvider){$translateProvider.translations("fr",{MENU:"MENU",SIGNUP_TAB:"Créer un Compte",SIGNIN_TAB:"Connexion",SIGNOUT_TAB:"Créer un compte",EDIT_PROFILE:"Modifier Mon Profil",MY_FORMS:"Mes Formulaires",MY_SETTINGS:"Mes Paramètres",CHANGE_PASSWORD:"Changer mon Mot de Pass"})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$uibModal","myForm","$filter",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$uibModal,myForm,$filter){$scope=$rootScope,$scope.animationsEnabled=!0,$scope.myform=myForm,$rootScope.saveInProgress=!1,CurrentForm.setForm($scope.myform),$scope.tabData=[{heading:$filter("translate")("CREATE_TAB"),route:"viewForm.create"},{heading:$filter("translate")("DESIGN_TAB"),route:"viewForm.design"},{heading:$filter("translate")("CONFIGURE_TAB"),route:"viewForm.configure"},{heading:$filter("translate")("ANALYZE_TAB"),route:"viewForm.analyze"}],$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.openDeleteModal=function(){$scope.deleteModal=$uibModal.open({animation:$scope.animationsEnabled,templateUrl:"myModalContent.html",controller:"AdminFormController",resolve:{myForm:function(){return $scope.myform}}}),$scope.deleteModal.result.then(function(selectedItem){$scope.selected=selectedItem},function(){console.log("Modal dismissed at: "+new Date)})},$scope.cancelDeleteModal=function(){$scope.deleteModal&&$scope.deleteModal.dismiss("cancel")},$scope.removeCurrentForm=function(){if($scope.deleteModal&&$scope.deleteModal.opened){$scope.deleteModal.close();var form_id=$scope.myform._id;if(!form_id)throw new Error("Error - removeCurrentForm(): $scope.myform._id does not exist");$http["delete"]("/forms/"+form_id).success(function(data,status,headers){console.log("form deleted successfully"),$state.go("listForms",{},{reload:!0})}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}},$scope.update=$rootScope.update=function(updateImmediately,cb){var continueUpdate=!0;if(updateImmediately||(continueUpdate=!$rootScope.saveInProgress),continueUpdate){var err=null;updateImmediately||($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),err=response.data})["finally"](function(){return updateImmediately||($rootScope.saveInProgress=!1),"function"==typeof cb?cb(err):void 0})}}}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$scope.forms={},$scope.showCreateModal=!1,$scope.languageRegExp=$scope.myPt={regExp:/[@!#$%^&*()\-+={}\[\]|\\/'";:`.,~№?<>]+/i,test:function(val){return!this.regExp.test(val)}},$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$scope.showCreateModal||($scope.showCreateModal=!0)},$scope.closeCreateModal=function(){$scope.showCreateModal&&($scope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicateForm=function(form_index){var form=_.cloneDeep($scope.myforms[form_index]);delete form._id,$http.post("/forms",{form:form}).success(function(data,status,headers){$scope.myforms.splice(form_index+1,0,data)}).error(function(errorResponse){console.error(errorResponse),null===errorResponse&&($scope.error=errorResponse.data.message)})},$scope.createNewForm=function(){var form={};form.title=$scope.forms.createForm.title.$modelValue,form.language=$scope.forms.createForm.language.$modelValue,$scope.forms.createForm.$valid&&$scope.forms.createForm.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){$scope.goToWithId("viewForm.create",data._id+"")}).error(function(errorResponse){console.error(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeForm=function(form_index){if(form_index>=$scope.myforms.length||0>form_index)throw new Error("Error: form_index in removeForm() must be between 0 and "+$scope.myforms.length-1);$http["delete"]("/forms/"+$scope.myforms[form_index]._id).success(function(data,status,headers){$scope.myforms.splice(form_index,1)}).error(function(error){console.error(error)})}}]),_.mixin({removeDateFields:removeDateFieldsFunc}),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFields Started",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFields Finished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!0,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):($formCtrl.$setPristine(),$formCtrl.$setUntouched())})};$scope.$watch(function(newValue,oldValue){$rootScope.finishedRender&&$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&debounceSave()}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){newValue=angular.copy(newValue),oldValue=angular.copy(oldValue),newValue.form_fields=_.removeDateFields(newValue.form_fields),oldValue.form_fields=_.removeDateFields(oldValue.form_fields);var changedFields=!_.isEqual(oldValue.form_fields,newValue.form_fields)||!_.isEqual(oldValue.startPage,newValue.startPage),changedFieldMap=!1;oldValue.hasOwnProperty("plugins.oscarhost.settings.fieldMap")&&(changedFieldMap=!!oldValue.plugins.oscarhost.settings.fieldMap&&!_.isEqual(oldValue.plugins.oscarhost.settings.fieldMap,newValue.plugins.oscarhost.settings.fieldMap)),(newValue||oldValue)&&oldValue&&(0===oldValue.form_fields.length&&($rootScope.finishedRender=!0),$rootScope.finishedRender&&(changedFields&&!$formCtrl.$dirty||changedFieldMap)&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","CurrentForm",function($rootScope,$http,Upload,CurrentForm){return{templateUrl:"modules/forms/admin/views/directiveViews/form/configure-form.client.view.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:["$scope",function($scope){console.log($scope.myform),CurrentForm.getForm().plugins?CurrentForm.getForm().plugins.oscarhost.baseUrl&&($scope.oscarhostAPI=!0):$scope.oscarhostAPI=!1,$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages,this._current_upload=null,$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update,this._unbindedPdfFields=$scope.pdfFields,$scope.cancelUpload=function(){this._current_upload.abort(),$scope.pdfLoading=!1,$scope.removePDF()},$scope.removePDF=function(){$scope.myform.pdf=null,$scope.myform.isGenerated=!1,$scope.myform.autofillPDFs=!1,console.log("form.pdf: "+$scope.myform.pdf+" REMOVED")},$scope.uploadPDF=function(file){file&&(console.log(file),Upload.upload({url:"/upload/pdf",data:{user:$scope.user,file:file}}).then(function(resp){var data=resp.data;$scope.log="file "+data.originalname+" uploaded as "+data.filename+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()},function(resp){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(resp.status)},function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total,10);$scope.log="progress: "+progressPercentage+"% "+evt.config.data.file.name+"\n"+$scope.log,console.log($scope.log),$scope.pdfLoading=!0}))}}]}}]),angular.module("forms").directive("editFormDirective",["$rootScope","FormFields",function($rootScope,FormFields){return{templateUrl:"modules/forms/admin/views/directiveViews/form/edit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:["$scope",function($scope){console.log($scope.myform);for(var field_ids=_($scope.myform.form_fields).pluck("_id"),i=0;i0){$scope.myform.plugins.oscarhost.settings.fieldMap||($scope.myform.plugins.oscarhost.settings.fieldMap={});var oscarhostFields=$scope.myform.plugins.oscarhost.settings.validFields,currentFields=_($scope.myform.plugins.oscarhost.settings.fieldMap).invert().keys().value();return $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id)&&(currentFields=_(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id])),_(oscarhostFields).difference(currentFields).value()}return[]},$scope.dropzone={handle:".handle",containment:".dropzoneContainer",cursor:"grabbing"},$scope.addNewField=function(modifyForm,fieldType){$scope.addField.lastAddedID++;for(var fieldTitle,i=0;i<$scope.addField.types.length;i++)if($scope.addField.types[i].name===fieldType){$scope.addField.types[i].lastAddedID++,fieldTitle=$scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;break}var newField={title:fieldTitle,fieldType:fieldType,fieldValue:"",required:!0,disabled:!1,deletePreserved:!1};return $scope.showAddOptions(newField)&&(newField.fieldOptions=[],newField.fieldOptions.push({option_id:Math.floor(1e5*Math.random()),option_title:"Option 0",option_value:"Option 0"})),modifyForm&&$scope.myform.form_fields.push(newField),newField},$scope.deleteField=function(field_index){var currFieldId=$scope.myform.form_fields[field_index]._id;$scope.myform.hasOwnProperty("plugins.oscarhost.baseUrl")&&delete $scope.myform.plugins.oscarhost.settings.fieldMap[currFieldId],$scope.myform.form_fields.splice(field_index,1)},$scope.duplicateField=function(field_index){var currField=_.cloneDeep($scope.myform.form_fields[field_index]);currField._id="cloned"+_.uniqueId(),currField.title+=" copy",$scope.myform.form_fields.splice(field_index+1,0,currField)},$scope.addButton=function(){var newButton={};newButton.bgColor="#ddd",newButton.color="#ffffff",newButton.text="Button",newButton._id=Math.floor(1e5*Math.random()),$scope.myform.startPage.buttons.push(newButton)},$scope.deleteButton=function(button){for(var currID,i=0;i<$scope.myform.startPage.buttons.length;i++)if(currID=$scope.myform.startPage.buttons[i]._id,console.log(currID),currID===button._id){$scope.myform.startPage.buttons.splice(i,1);break}},$scope.addOption=function(field_index){var currField=$scope.myform.form_fields[field_index];if("checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType){currField.fieldOptions||($scope.myform.form_fields[field_index].fieldOptions=[]);var lastOptionID=$scope.myform.form_fields[field_index].fieldOptions.length+1,newOption={option_id:Math.floor(1e5*Math.random()),option_title:"Option "+lastOptionID,option_value:"Option "+lastOptionID};$scope.myform.form_fields[field_index].fieldOptions.push(newOption)}},$scope.deleteOption=function(field_index,option){var currField=$scope.myform.form_fields[field_index];if("checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType)for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:["$scope",function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}]}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope","$templateCache","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("forms").directive("onEnterKey",["$rootScope",function($rootScope){return{restrict:"A",link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode,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("forms").directive("onFinishRender",["$rootScope","$timeout",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")||element.attr("data-ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$first&&!scope.$last?scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Started")}):scope.$last&&scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Finished")})}}}}]),angular.module("forms").directive("submitFormDirective",["$http","TimeCounter","$filter","$rootScope","Auth","SendVisitorData",function($http,TimeCounter,$filter,$rootScope,Auth,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.authentication=$rootScope.authentication,$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("forms").service("CurrentForm",function(){var _form={};this.getForm=function(){return _form},this.setForm=function(form){_form=form}}),angular.module("forms").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"}})}]),angular.module("forms").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}}]),angular.module("users").config(["$translateProvider",function($translateProvider){$translateProvider.translations("en",{ACCESS_DENIED_TEXT:"You need to be logged in to access this page",USERNAME_LABEL:"Username",PASSWORD_LABEL:"Password",CURRENT_PASSWORD_LABEL:"Current Password",NEW_PASSWORD_LABEL:"New Password",VERIFY_PASSWORD_LABEL:"Verify Password",UPDATE_PASSWORD_LABEL:"Update Password",FIRST_NAME_LABEL:"First Name",LAST_NAME_LABEL:"Last Name",LANGUAGE_LABEL:"Language",EMAIL_LABEL:"Email",UPDATE_PROFILE_BTN:"Update Profile",PROFILE_SAVE_SUCCESS:"Profile saved successfully",PROFILE_SAVE_ERROR:"Could't Save Your Profile.",FORGOT_PASSWORD_LINK:"Forgot your password?",REVERIFY_ACCOUNT_LINK:"Resend your verification email",SIGNIN_BTN:"Sign in",SIGNUP_BTN:"Sign up",SAVE_PASSWORD_BTN:"Save Password", -SUCCESS_HEADER:"Signup Successful",SUCCESS_TEXT:"You've successfully registered an account at TellForm.",VERIFICATION_EMAIL_SENT:"A verification email has been sent to",NOT_ACTIVATED_YET:"But your account is not activated yet",BEFORE_YOU_CONTINUE:"Before you continue, make sure to check your email for our verification. If you don't receive it within 24h drop us a line at ",CHECK_YOUR_EMAIL:"Check your email and click on the activation link to activate your account. If you have any questions drop us a line at",PASSWORD_RESTORE_HEADER:"Restore your password",ENTER_YOUR_EMAIL:"Enter your account email.",SUBMIT_BTN:"Submit",ASK_FOR_NEW_PASSWORD:"Ask for new password reset",PASSWORD_RESET_INVALID:"Password reset is invalid",PASSWORD_RESET_SUCCESS:"Passport successfully reset",PASSWORD_CHANGE_SUCCESS:"Passport successfully changed",CONTINUE_TO_LOGIN:"Continue to login page",VERIFY_SUCCESS:"Account successfully activated",VERIFY_ERROR:"Verification link is invalid or has expired"}),$translateProvider.preferredLanguage("en").fallbackLanguage("en").useSanitizeValueStrategy("escape")}]),angular.module("users").config(["$translateProvider",function($translateProvider){$translateProvider.translations("en",{ACCESS_DENIED_TEXT:"Vouz est pas autorisé pour accese cete page.",USERNAME_LABEL:"Nom de Compte",PASSWORD_LABEL:"Mot de Pass",CURRENT_PASSWORD_LABEL:"Current Password",NEW_PASSWORD_LABEL:"Nouveau Mot de Pass Password",VERIFY_PASSWORD_LABEL:"Verify Password",UPDATE_PASSWORD_LABEL:"Update Password",FIRST_NAME_LABEL:"Premiere Nom Name",LAST_NAME_LABEL:"Surnom",LANGUAGE_LABEL:"Language",EMAIL_LABEL:"Email",UPDATE_PROFILE_BTN:"Modifier Profile",PROFILE_SAVE_SUCCESS:"Profile saved successfully",PROFILE_SAVE_ERROR:"Erreur: On peux pas enregistré votre Profile.",FORGOT_PASSWORD_LINK:"Oublier votre mot de pass?",REVERIFY_ACCOUNT_LINK:"Re-envoyez ton email de verification",SIGNIN_BTN:"Connexion",SIGNUP_BTN:"Créer un compte",SAVE_PASSWORD_BTN:"Enregistreé ton nouveau Mot de Pass",SUCCESS_HEADER:"Votre Compte a été enregistré!",SUCCESS_TEXT:"Vouz a enregistré un compte a TellForm.",VERIFICATION_EMAIL_SENT:"Un email de verification a été envoyer a",NOT_ACTIVATED_YET:"Mais votre compte n'est pas activé",BEFORE_YOU_CONTINUE:"Plutôt que vouz continué, vouz devrez voire ton inbox pour notre message de verification. Si tu receivoir-pas un message de verification dan le prochaine 24h, contactez nous a ",CHECK_YOUR_EMAIL:"Check your email and click on the activation link to activate your account. If you have any questions drop us a line at",PASSWORD_RESTORE_HEADER:"Restore your password",ENTER_YOUR_EMAIL:"Entrer votre email de compte",SUBMIT_BTN:"Enregistrer",ASK_FOR_NEW_PASSWORD:"Demander un nouveau mot de pass ",PASSWORD_RESET_INVALID:"Password reset is invalid",PASSWORD_RESET_SUCCESS:"Passport successfully reset",PASSWORD_CHANGE_SUCCESS:"Passport successfully changed",CONTINUE_TO_LOGIN:"Allez au page de connexion",VERIFY_SUCCESS:"Compte est activé!",VERIFY_ERROR:"Le fléche de verification est invalid ou expireé"})}]); \ No newline at end of file +"use strict";function removeDateFieldsFunc(o){function eachObject(v,k){"lastModified"!==k&&"created"!==k||delete clone[k]}for(var clone=_.clone(o),i=0;i'),$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",'
{{ \'COMPLETING_NEEDED\' | translate:translateAdvancementData }}
'),$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","

{{ 'SIGNIN_HEADER_TEXT' | translate }}

Error:
  or  {{ 'SIGNUP_BTN' | translate }}
"),$templateCache.put("modules/users/views/authentication/signup-success.client.view.html",''),$templateCache.put("modules/users/views/authentication/signup.client.view.html",''),$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("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.router.tabs","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("forms").config(["$translateProvider",function($translateProvider){$translateProvider.translations("en",{PDF_GENERATION_EMR:"PDF Generation/EMR",SAVE_PDF_SUBMISSIONS:"Save Submissions as PDFs?",UPLOAD_YOUR_PDF:"Upload Your PDF Template",ADVANCED_SETTINGS:"Advanced Settings",FORM_NAME:"Form Name",FORM_STATUS:"Form Status",PUBLIC:"Public",PRIVATE:"Private",GA_TRACKING_CODE:"Google Analytics Tracking Code",DISPLAY_FOOTER:"Display Form Footer?",SAVE_CHANGES:"Save Changes",CANCEL:"Cancel",CREATE_A_NEW_FORM:"Create a new form",CREATE_FORM:"Create form",CREATED_ON:"Created on",ARE_YOU_SURE:"Are you ABSOLUTELY sure?",READ_WARNING:"Unexpected bad things will happen if you don’t read this!",DELETE_WARNING1:"This action CANNOT be undone.This will permanently delete the",DELETE_WARNING2:"form, form submissions and remove all associated pdfs.",DELETE_CONFIRM:"Please type in the name of the form to confirm",I_UNDERSTAND:"I understand the consequences, delete this form",DELETE_FORM_SM:"Delete",DELETE_FORM_MD:"Delete Form",DELETE:"Delete",FORM:"Form",VIEW:"View",LIVE:"Live",PREVIEW:"Preview",ADD_FIELD_LG:"Click to Add New Field",ADD_FIELD_MD:"Add New Field",ADD_FIELD_SM:"Add Field",PREVIEW_START_PAGE:"Preview Start Page",EDIT_START_PAGE:"Edit Start Page",INTRO_TTILE:"Intro Title",INTRO_PARAGRAPH:"Intro Paragraph",INTRO_BTN:"Intro Button",BUTTONS:"Buttons",BUTTON_TEXT:"Text",BUTTON_LINK:"Link",ADD_BUTTON:"Add Button",PREVIEW_FIELD:"Preview Field",EDIT_FIELD:"Edit Field",QUESTION_TITLE:"Question Title",QUESTION_DESCRIPTION:"Question Description",OPTIONS:"Options",ADD_OPTION:"Add Option",NUM_OF_STEPS:"Number of Steps",CLICK_FIELDS_FOOTER:"Click on fields to add them here",TOTAL_VIEWS:"total unique visits",RESPONSES:"responses",COMPLETION_RATE:"completion rate",AVERAGE_TIME_TO_COMPLETE:"avg. completion time",DESKTOP_AND_LAPTOP:"Desktops",TABLETS:"Tablets",PHONES:"Phones",OTHER:"Other",UNIQUE_VISITS:"Unique Visits",FIELD_TITLE:"Field Title",FIELD_VIEWS:"Field Views",FIELD_DROPOFF:"Field Completion",FIELD_RESPONSES:"Field Responses",DELETE_SELECTED:"Delete Selected",EXPORT_TO_EXCEL:"Export to Excel",EXPORT_TO_CSV:"Export to CSV",EXPORT_TO_JSON:"Export to JSON",PERCENTAGE_COMPLETE:"Percentage Complete",TIME_ELAPSED:"Time Elapsed",DEVICE:"Device",LOCATION:"Location",IP_ADDRESS:"IP Address",DATE_SUBMITTED:"Date Submitted",GENERATED_PDF:"Generated PDF",BACKGROUND_COLOR:"Background Color",DESIGN_HEADER:"Change how your Form Looks",QUESTION_TEXT_COLOR:"Question Text Color",ANSWER_TEXT_COLOR:"Answer Text Color",BTN_BACKGROUND_COLOR:"Button Background Color",BTN_TEXT_COLOR:"Button Text Color",CREATE_TAB:"Create",DESIGN_TAB:"Design",CONFIGURE_TAB:"Configure",ANALYZE_TAB:"Analyze"})}]),angular.module("forms").config(["$translateProvider",function($translateProvider){$translateProvider.translations("en",{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"})}]),angular.module("forms").config(["$translateProvider",function($translateProvider){$translateProvider.translations("fr",{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("forms").config(["$translateProvider",function($translateProvider){$translateProvider.translations("de",{FORM_SUCCESS:"Ihre Angaben wurden gespeichert.",REVIEW:"Unvollständig",BACK_TO_FORM:"Zurück zum Formular",EDIT_FORM:"Bearbeiten Sie diese TellForm",CREATE_FORM:"Erstellen Sie eine TellForm",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:"Ich akzeptiere",LEGAL_NO_ACCEPT:"Ich akzeptiere nicht",DELETE:"Entfernen",CANCEL:"Canceln",SUBMIT:"Speichern",UPLOAD_FILE:"Datei versenden",Y:"J",N:"N"})}]),angular.module("forms").config(["$translateProvider",function($translateProvider){$translateProvider.translations("it",{FORM_SUCCESS:"Il formulario è stato inviato con successo!",REVIEW:"Incompleto",BACK_TO_FORM:"Ritorna al formulario",EDIT_FORM:"Modifica questo Tellform",CREATE_FORM:"Creare un TellForm",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:"Accetto",LEGAL_NO_ACCEPT:"Non accetto",DELETE:"Cancella",CANCEL:"Reset",SUBMIT:"Registra",UPLOAD_FILE:"Invia un file",Y:"S",N:"N"})}]),angular.module("forms").config(["$translateProvider",function($translateProvider){$translateProvider.translations("es",{FORM_SUCCESS:"¡El formulario ha sido enviado con éxito!",REVIEW:"Revisar",BACK_TO_FORM:"Regresar al formulario",EDIT_FORM:"Crear un TellForm",CREATE_FORM:"Editar este TellForm",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:"Acepto",LEGAL_NO_ACCEPT:"No acepto",DELETE:"Eliminar",CANCEL:"Cancelar",SUBMIT:"Registrar",UPLOAD_FILE:"Cargar el archivo",Y:"S",N:"N"})}]),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/forms")}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","$state","$stateParams",function($rootScope,Auth,$state,$stateParams){$rootScope.$state=$state,$rootScope.$stateParams=$stateParams,$rootScope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState){$state.previous=fromState;var statesToIgnore=["home","signin","resendVerifyEmail","verify","signup","signup-success","forgot","reset-invalid","reset","reset-success"];statesToIgnore.indexOf(toState.name)>0?Auth.isAuthenticated()&&(event.preventDefault(),$state.go("listForms")):"access_denied"===toState.name||Auth.isAuthenticated()||"submitForm"===toState.name||(console.log("go to signup"),event.preventDefault(),$state.go("listForms"))})}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","User","Authorizer","$state","$stateParams",function($rootScope,Auth,User,Authorizer,$state,$stateParams){$rootScope.$on("$stateChangeStart",function(event,next){var authenticator,permissions,user;permissions=next&&next.data&&next.data.permissions?next.data.permissions:null,Auth.ensureHasCurrentUser(User),user=Auth.currentUser,user&&(authenticator=new Authorizer(user),null!==permissions&&(authenticator.canAccess(permissions)||(event.preventDefault(),$state.go("access_denied"))))})}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User","$window","$translate","$locale",function($rootScope,$scope,Menus,$state,Auth,User,$window,$translate,$locale){$rootScope.signupDisabled=$window.signupDisabled,$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["en","fr","es","it","de"],console.log($locale.id),$scope.authentication.isAuthenticated()?$rootScope.language=$scope.user.language:$rootScope.language=$locale.id.substring(0,2),$translate.use($rootScope.language),$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("listForms")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),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("core").factory("Socket",Socket),Socket.$inject=["$timeout","$window"]}(),angular.module("core").factory("subdomain",["$location",function($location){var host=$location.host();return host.indexOf(".")<0?null:host.split(".")[0]}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("secondsToDateTime",[function(){return function(seconds){return new Date(1970,0,1).setSeconds(seconds)}}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field&&"statement"!==field.fieldType&&"rating"!==field.fieldType?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",["$delegate",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate}])}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/admin/views/list-forms.client.view.html"}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/admin/views/admin-form.client.view.html",data:{permissions:["editForm"]},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"AdminFormController"}).state("viewForm.configure",{url:"/configure",templateUrl:"modules/forms/admin/views/adminTabs/configure.html"}).state("viewForm.design",{url:"/design",templateUrl:"modules/forms/admin/views/adminTabs/design.html"}).state("viewForm.analyze",{url:"/analyze",templateUrl:"modules/forms/admin/views/adminTabs/analyze.html"}).state("viewForm.create",{url:"/create",templateUrl:"modules/forms/admin/views/adminTabs/create.html"})}]),function(){function SendVisitorData(Socket,$state,$http,deviceDetector){function send(form,lastActiveIndex,timeElapsed){var visitorData={referrer:document.referrer,isSubmitted:form.submitted,formId:form._id,lastActiveField:form.form_fields[lastActiveIndex]._id,timeElapsed:timeElapsed,language:window.navigator.userLanguage||window.navigator.language,ipAddr:"",deviceType:""};$http.get("http://jsonip.com/").success(function(response){visitorData.ipAddr=response.ip+""}).error(function(error){console.error("Could not get users's ip")}).then(function(){visitorData.userAgent=deviceDetector.raw,deviceDetector.isTablet()?visitorData.deviceType="tablet":deviceDetector.isMobile()?visitorData.deviceType="phone":visitorData.deviceType="desktop",console.log(visitorData.deviceType),Socket.emit("form-visitor-data",visitorData)})}function init(){Socket.socket||Socket.connect()}var service={send:send};return init(),service}angular.module("forms").factory("SendVisitorData",SendVisitorData),SendVisitorData.$inject=["Socket","$state","$http","deviceDetector"]}(),angular.module("forms").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("forms").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("users").config(["$httpProvider",function($httpProvider){$httpProvider.interceptors.push(["$q","$location",function($q,$location){return{responseError:function(response){return"/users/me"!==$location.path()&&response.config&&"/users/me"!==response.config.url&&(console.log("intercepted rejection of ",response.config.url,response.status),401===response.status?(console.log($location.path()),$location.nextAfterLogin=$location.path(),$location.path("/signin")):403===response.status&&$location.path("/access_denied")),$q.reject(response)}}}])}]),angular.module("users").config(["$stateProvider",function($stateProvider){var checkLoggedin=function($q,$timeout,$state,User,Auth){var deferred=$q.defer();return Auth.currentUser&&Auth.currentUser.email?$timeout(deferred.resolve):Auth.currentUser=User.getCurrent(function(){Auth.login(),$timeout(deferred.resolve())},function(){Auth.logout(),$timeout(deferred.reject()),$state.go("signin",{reload:!0})}),deferred.promise};checkLoggedin.$inject=["$q","$timeout","$state","User","Auth"];var checkSignupDisabled=function($window,$timeout,$q){var deferred=$q.defer();return $timeout($window.signupDisabled?deferred.reject():deferred.resolve()),deferred.promise};checkSignupDisabled.$inject=["$window","$timeout","$q"],$stateProvider.state("profile",{resolve:{loggedin:checkLoggedin},url:"/settings/profile",templateUrl:"modules/users/views/settings/edit-profile.client.view.html"}).state("password",{resolve:{loggedin:checkLoggedin},url:"/settings/password",templateUrl:"modules/users/views/settings/change-password.client.view.html"}).state("accounts",{resolve:{loggedin:checkLoggedin},url:"/settings/accounts",templateUrl:"modules/users/views/settings/social-accounts.client.view.html"}).state("signup",{resolve:{isDisabled:checkSignupDisabled},url:"/signup",templateUrl:"modules/users/views/authentication/signup.client.view.html"}).state("signup-success",{resolve:{isDisabled:checkSignupDisabled},url:"/signup-success",templateUrl:"modules/users/views/authentication/signup-success.client.view.html"}).state("signin",{url:"/signin",templateUrl:"modules/users/views/authentication/signin.client.view.html"}).state("access_denied",{url:"/access_denied",templateUrl:"modules/users/views/authentication/access-denied.client.view.html"}).state("verify",{resolve:{isDisabled:checkSignupDisabled},url:"/verify/:token",templateUrl:"modules/users/views/verify/verify-account.client.view.html"}).state("resendVerifyEmail",{resolve:{isDisabled:checkSignupDisabled},url:"/verify",templateUrl:"modules/users/views/verify/resend-verify-email.client.view.html"}).state("forgot",{url:"/password/forgot",templateUrl:"modules/users/views/password/forgot-password.client.view.html"}).state("reset-invalid",{url:"/password/reset/invalid",templateUrl:"modules/users/views/password/reset-password-invalid.client.view.html"}).state("reset-success",{url:"/password/reset/success",templateUrl:"modules/users/views/password/reset-password-success.client.view.html"}).state("reset",{url:"/password/reset/:token",templateUrl:"modules/users/views/password/reset-password.client.view.html"})}]),angular.module("users").controller("AuthenticationController",["$scope","$location","$state","$rootScope","User","Auth",function($scope,$location,$state,$rootScope,User,Auth){$scope=$rootScope,$scope.credentials={},$scope.error="",$scope.signin=function(){User.login($scope.credentials).then(function(response){Auth.login(response),$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),"home"!==$state.previous.name&&"verify"!==$state.previous.name&&""!==$state.previous.name?$state.go($state.previous.name):$state.go("listForms")},function(error){$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user,$scope.error=error,console.log("loginError: "+error)})},$scope.signup=function(){console.log($scope.credentials),User.signup($scope.credentials).then(function(response){console.log("signup-success"),$state.go("signup-success")},function(error){console.log("Error: "),console.log(error),error?($scope.error=error,console.log(error)):console.log("No response received")})}}]),angular.module("users").controller("PasswordController",["$scope","$stateParams","$state","User",function($scope,$stateParams,$state,User){$scope.error="",$scope.askForPasswordReset=function(){User.askForPasswordReset($scope.credentials).then(function(response){$scope.success=response.message,$scope.credentials=null},function(error){$scope.error=error,$scope.credentials=null})},$scope.resetUserPassword=function(){$scope.success=$scope.error=null,User.resetPassword($scope.passwordDetails,$stateParams.token).then(function(response){$scope.success=response.message,$scope.passwordDetails=null,$state.go("reset-success")},function(error){$scope.error=error.message||error,$scope.passwordDetails=null})}}]),angular.module("users").controller("SettingsController",["$scope","$rootScope","$http","$state","Users",function($scope,$rootScope,$http,$state,Users){$scope.user=$rootScope.user,$scope.hasConnectedAdditionalSocialAccounts=function(provider){for(var i in $scope.user.additionalProvidersData)return!0;return!1},$scope.isConnectedSocialAccount=function(provider){return $scope.user.provider===provider||$scope.user.additionalProvidersData&&$scope.user.additionalProvidersData[provider]},$scope.removeUserSocialAccount=function(provider){$scope.success=$scope.error=null,$http["delete"]("/users/accounts",{params:{provider:provider}}).success(function(response){$scope.success=!0,$scope.user=response}).error(function(response){$scope.error=response.message})},$scope.updateUserProfile=function(isValid){if(isValid){$scope.success=$scope.error=null;var user=new Users($scope.user);user.$update(function(response){$scope.success=!0,$scope.user=response},function(response){$scope.error=response.data.message})}else $scope.submitted=!0},$scope.changeUserPassword=function(){$scope.success=$scope.error=null,$http.post("/users/password",$scope.passwordDetails).success(function(response){$scope.success=!0,$scope.passwordDetails=null}).error(function(response){$scope.error=response.message})}}]),angular.module("users").controller("VerifyController",["$scope","$state","$rootScope","User","Auth","$stateParams",function($scope,$state,$rootScope,User,Auth,$stateParams){$scope.isResetSent=!1,$scope.credentials={},$scope.error="",$scope.resendVerifyEmail=function(){User.resendVerifyEmail($scope.credentials.email).then(function(response){console.log(response),$scope.success=response.message,$scope.credentials=null,$scope.isResetSent=!0},function(error){$scope.error=error,$scope.credentials.email=null,$scope.isResetSent=!1})},$scope.validateVerifyToken=function(){$stateParams.token&&(console.log($stateParams.token),User.validateVerifyToken($stateParams.token).then(function(response){console.log("Success: "+response.message),$scope.success=response.message,$scope.isResetSent=!0,$scope.credentials.email=null},function(error){console.log("Error: "+error.message),$scope.isResetSent=!1,$scope.error=error,$scope.credentials.email=null}))}}]),angular.module("users").factory("Auth",["$window",function($window){var userState={isLoggedIn:!1},service={_currentUser:null,get currentUser(){return this._currentUser},ensureHasCurrentUser:function(User){return service._currentUser&&service._currentUser.username?service._currentUser:$window.user?(service._currentUser=$window.user,service._currentUser):void User.getCurrent().then(function(user){return service._currentUser=user,userState.isLoggedIn=!0,$window.user=service._currentUser,service._currentUser},function(response){return userState.isLoggedIn=!1,service._currentUser=null,$window.user=null,console.log("User.getCurrent() err",response),null})},isAuthenticated:function(){return!!service._currentUser},getUserState:function(){return userState},login:function(new_user){userState.isLoggedIn=!0,service._currentUser=new_user},logout:function(){$window.user=null,userState.isLoggedIn=!1,service._currentUser=null}};return service}]),angular.module("users").service("Authorizer",["APP_PERMISSIONS","USER_ROLES",function(APP_PERMISSIONS,USER_ROLES){return function(user){return{canAccess:function(permissions){var i,len,permission;for(angular.isArray(permissions)||(permissions=[permissions]),i=0,len=permissions.length;len>i;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}]),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var validTokenRe=/^([A-Za-z0-9]{48})$/g;if(!validTokenRe.test(token))throw new Error("Error token: "+token+" is not a valid verification token"); +var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]),angular.module("core").config(["$translateProvider",function($translateProvider){$translateProvider.translations("en",{MENU:"MENU",SIGNUP_TAB:"Sign Up",SIGNIN_TAB:"Sign In",SIGNOUT_TAB:"Signout",EDIT_PROFILE:"Edit Profile",MY_FORMS:"My Forms",MY_SETTINGS:"My Settings",CHANGE_PASSWORD:"Change Password"}),$translateProvider.preferredLanguage("en").fallbackLanguage("en").useSanitizeValueStrategy("escape")}]),angular.module("core").config(["$translateProvider",function($translateProvider){$translateProvider.translations("fr",{MENU:"MENU",SIGNUP_TAB:"Créer un Compte",SIGNIN_TAB:"Connexion",SIGNOUT_TAB:"Créer un compte",EDIT_PROFILE:"Modifier Mon Profil",MY_FORMS:"Mes Formulaires",MY_SETTINGS:"Mes Paramètres",CHANGE_PASSWORD:"Changer mon Mot de Pass"})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$uibModal","myForm","$filter",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$uibModal,myForm,$filter){$scope=$rootScope,$scope.animationsEnabled=!0,$scope.myform=myForm,$rootScope.saveInProgress=!1,CurrentForm.setForm($scope.myform),$scope.formURL=$scope.myform.admin.username+"."+window.location.host,$scope.tabData=[{heading:$filter("translate")("CREATE_TAB"),route:"viewForm.create"},{heading:$filter("translate")("DESIGN_TAB"),route:"viewForm.design"},{heading:$filter("translate")("CONFIGURE_TAB"),route:"viewForm.configure"},{heading:$filter("translate")("ANALYZE_TAB"),route:"viewForm.analyze"}],$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.openDeleteModal=function(){$scope.deleteModal=$uibModal.open({animation:$scope.animationsEnabled,templateUrl:"myModalContent.html",controller:"AdminFormController",resolve:{myForm:function(){return $scope.myform}}}),$scope.deleteModal.result.then(function(selectedItem){$scope.selected=selectedItem},function(){console.log("Modal dismissed at: "+new Date)})},$scope.cancelDeleteModal=function(){$scope.deleteModal&&$scope.deleteModal.dismiss("cancel")},$scope.removeCurrentForm=function(){if($scope.deleteModal&&$scope.deleteModal.opened){$scope.deleteModal.close();var form_id=$scope.myform._id;if(!form_id)throw new Error("Error - removeCurrentForm(): $scope.myform._id does not exist");$http["delete"]("/forms/"+form_id).success(function(data,status,headers){console.log("form deleted successfully"),$state.go("listForms",{},{reload:!0})}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}},$scope.update=$rootScope.update=function(updateImmediately,cb){var continueUpdate=!0;if(updateImmediately||(continueUpdate=!$rootScope.saveInProgress),continueUpdate){var err=null;updateImmediately||($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),err=response.data})["finally"](function(){return updateImmediately||($rootScope.saveInProgress=!1),"function"==typeof cb?cb(err):void 0})}}}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$scope.forms={},$scope.showCreateModal=!1,$rootScope.languageRegExp={regExp:/[@!#$%^&*()\-+={}\[\]|\\/'";:`.,~№?<>]+/i,test:function(val){return!this.regExp.test(val)}},$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$scope.showCreateModal||($scope.showCreateModal=!0)},$scope.closeCreateModal=function(){$scope.showCreateModal&&($scope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicateForm=function(form_index){var form=_.cloneDeep($scope.myforms[form_index]);delete form._id,$http.post("/forms",{form:form}).success(function(data,status,headers){$scope.myforms.splice(form_index+1,0,data)}).error(function(errorResponse){console.error(errorResponse),null===errorResponse&&($scope.error=errorResponse.data.message)})},$scope.createNewForm=function(){var form={};form.title=$scope.forms.createForm.title.$modelValue,form.language=$scope.forms.createForm.language.$modelValue,$scope.forms.createForm.$valid&&$scope.forms.createForm.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){$scope.goToWithId("viewForm.create",data._id+"")}).error(function(errorResponse){console.error(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeForm=function(form_index){if(form_index>=$scope.myforms.length||0>form_index)throw new Error("Error: form_index in removeForm() must be between 0 and "+$scope.myforms.length-1);$http["delete"]("/forms/"+$scope.myforms[form_index]._id).success(function(data,status,headers){$scope.myforms.splice(form_index,1)}).error(function(error){console.error(error)})}}]),_.mixin({removeDateFields:removeDateFieldsFunc}),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFields Started",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFields Finished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!0,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):($formCtrl.$setPristine(),$formCtrl.$setUntouched())})};$scope.$watch(function(newValue,oldValue){$rootScope.finishedRender&&$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&debounceSave()}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){newValue=angular.copy(newValue),oldValue=angular.copy(oldValue),newValue.form_fields=_.removeDateFields(newValue.form_fields),oldValue.form_fields=_.removeDateFields(oldValue.form_fields);var changedFields=!_.isEqual(oldValue.form_fields,newValue.form_fields)||!_.isEqual(oldValue.startPage,newValue.startPage),changedFieldMap=!1;oldValue.hasOwnProperty("plugins.oscarhost.settings.fieldMap")&&(changedFieldMap=!!oldValue.plugins.oscarhost.settings.fieldMap&&!_.isEqual(oldValue.plugins.oscarhost.settings.fieldMap,newValue.plugins.oscarhost.settings.fieldMap)),(newValue||oldValue)&&oldValue&&(0===oldValue.form_fields.length&&($rootScope.finishedRender=!0),$rootScope.finishedRender&&(changedFields&&!$formCtrl.$dirty||changedFieldMap)&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","CurrentForm",function($rootScope,$http,Upload,CurrentForm){return{templateUrl:"modules/forms/admin/views/directiveViews/form/configure-form.client.view.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:["$scope",function($scope){console.log($scope.myform),CurrentForm.getForm().plugins?CurrentForm.getForm().plugins.oscarhost.baseUrl&&($scope.oscarhostAPI=!0):$scope.oscarhostAPI=!1,$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages,this._current_upload=null,$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update,this._unbindedPdfFields=$scope.pdfFields,$scope.cancelUpload=function(){this._current_upload.abort(),$scope.pdfLoading=!1,$scope.removePDF()},$scope.removePDF=function(){$scope.myform.pdf=null,$scope.myform.isGenerated=!1,$scope.myform.autofillPDFs=!1,console.log("form.pdf: "+$scope.myform.pdf+" REMOVED")},$scope.uploadPDF=function(file){file&&(console.log(file),Upload.upload({url:"/upload/pdf",data:{user:$scope.user,file:file}}).then(function(resp){var data=resp.data;$scope.log="file "+data.originalname+" uploaded as "+data.filename+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()},function(resp){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(resp.status)},function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total,10);$scope.log="progress: "+progressPercentage+"% "+evt.config.data.file.name+"\n"+$scope.log,console.log($scope.log),$scope.pdfLoading=!0}))}}]}}]),angular.module("forms").directive("editFormDirective",["$rootScope","FormFields",function($rootScope,FormFields){return{templateUrl:"modules/forms/admin/views/directiveViews/form/edit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:["$scope",function($scope){console.log($scope.myform);for(var field_ids=_($scope.myform.form_fields).pluck("_id"),i=0;i0){$scope.myform.plugins.oscarhost.settings.fieldMap||($scope.myform.plugins.oscarhost.settings.fieldMap={});var oscarhostFields=$scope.myform.plugins.oscarhost.settings.validFields,currentFields=_($scope.myform.plugins.oscarhost.settings.fieldMap).invert().keys().value();return $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id)&&(currentFields=_(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id])),_(oscarhostFields).difference(currentFields).value()}return[]},$scope.dropzone={handle:".handle",containment:".dropzoneContainer",cursor:"grabbing"},$scope.addNewField=function(modifyForm,fieldType){$scope.addField.lastAddedID++;for(var fieldTitle,i=0;i<$scope.addField.types.length;i++)if($scope.addField.types[i].name===fieldType){$scope.addField.types[i].lastAddedID++,fieldTitle=$scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;break}var newField={title:fieldTitle,fieldType:fieldType,fieldValue:"",required:!0,disabled:!1,deletePreserved:!1};return $scope.showAddOptions(newField)&&(newField.fieldOptions=[],newField.fieldOptions.push({option_id:Math.floor(1e5*Math.random()),option_title:"Option 0",option_value:"Option 0"})),modifyForm&&$scope.myform.form_fields.push(newField),newField},$scope.deleteField=function(field_index){var currFieldId=$scope.myform.form_fields[field_index]._id;$scope.myform.hasOwnProperty("plugins.oscarhost.baseUrl")&&delete $scope.myform.plugins.oscarhost.settings.fieldMap[currFieldId],$scope.myform.form_fields.splice(field_index,1)},$scope.duplicateField=function(field_index){var currField=_.cloneDeep($scope.myform.form_fields[field_index]);currField._id="cloned"+_.uniqueId(),currField.title+=" copy",$scope.myform.form_fields.splice(field_index+1,0,currField)},$scope.addButton=function(){var newButton={};newButton.bgColor="#ddd",newButton.color="#ffffff",newButton.text="Button",newButton._id=Math.floor(1e5*Math.random()),$scope.myform.startPage.buttons.push(newButton)},$scope.deleteButton=function(button){for(var currID,i=0;i<$scope.myform.startPage.buttons.length;i++)if(currID=$scope.myform.startPage.buttons[i]._id,console.log(currID),currID===button._id){$scope.myform.startPage.buttons.splice(i,1);break}},$scope.addOption=function(field_index){var currField=$scope.myform.form_fields[field_index];if("checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType){currField.fieldOptions||($scope.myform.form_fields[field_index].fieldOptions=[]);var lastOptionID=$scope.myform.form_fields[field_index].fieldOptions.length+1,newOption={option_id:Math.floor(1e5*Math.random()),option_title:"Option "+lastOptionID,option_value:"Option "+lastOptionID};$scope.myform.form_fields[field_index].fieldOptions.push(newOption)}},$scope.deleteOption=function(field_index,option){var currField=$scope.myform.form_fields[field_index];if("checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType)for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:["$scope",function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}]}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope","$templateCache","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("forms").directive("onEnterKey",["$rootScope",function($rootScope){return{restrict:"A",link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode,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("forms").directive("onFinishRender",["$rootScope","$timeout",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")||element.attr("data-ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$first&&!scope.$last?scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Started")}):scope.$last&&scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Finished")})}}}}]),angular.module("forms").directive("submitFormDirective",["$http","TimeCounter","$filter","$rootScope","Auth","SendVisitorData",function($http,TimeCounter,$filter,$rootScope,Auth,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.authentication=$rootScope.authentication,$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("forms").service("CurrentForm",function(){var _form={};this.getForm=function(){return _form},this.setForm=function(form){_form=form}}),angular.module("forms").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"}})}]),angular.module("forms").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}}]),angular.module("users").config(["$translateProvider",function($translateProvider){$translateProvider.translations("en",{ACCESS_DENIED_TEXT:"You need to be logged in to access this page",USERNAME_LABEL:"Username",PASSWORD_LABEL:"Password",CURRENT_PASSWORD_LABEL:"Current Password",NEW_PASSWORD_LABEL:"New Password",VERIFY_PASSWORD_LABEL:"Verify Password",UPDATE_PASSWORD_LABEL:"Update Password",FIRST_NAME_LABEL:"First Name",LAST_NAME_LABEL:"Last Name",LANGUAGE_LABEL:"Language",EMAIL_LABEL:"Email",SIGNUP_HEADER_TEXT:"Sign up with your email",SIGNIN_HEADER_TEXT:"Signup in with your email",SIGNUP_ERROR_TEXT:"Couldn't complete registration due to errors",UPDATE_PROFILE_BTN:"Update Profile",PROFILE_SAVE_SUCCESS:"Profile saved successfully",PROFILE_SAVE_ERROR:"Could't Save Your Profile.",FORGOT_PASSWORD_LINK:"Forgot your password?",REVERIFY_ACCOUNT_LINK:"Resend your verification email",SIGNIN_BTN:"Sign in",SIGNUP_BTN:"Sign up",SAVE_PASSWORD_BTN:"Save Password",SUCCESS_HEADER:"Signup Successful",SUCCESS_TEXT:"You’ve successfully registered an account at TellForm.",VERIFICATION_EMAIL_SENT:"A verification email has been sent to",NOT_ACTIVATED_YET:"But your account is not activated yet",BEFORE_YOU_CONTINUE:"Before you continue, make sure to check your email for our verification. If you don’t receive it within 24h drop us a line at ",CHECK_YOUR_EMAIL:"Check your email and click on the activation link to activate your account. If you have any questions drop us a line at",PASSWORD_RESTORE_HEADER:"Restore your password",ENTER_YOUR_EMAIL:"Enter your account email.",SUBMIT_BTN:"Submit",ASK_FOR_NEW_PASSWORD:"Ask for new password reset",PASSWORD_RESET_INVALID:"Password reset is invalid",PASSWORD_RESET_SUCCESS:"Passport successfully reset", +PASSWORD_CHANGE_SUCCESS:"Passport successfully changed",CONTINUE_TO_LOGIN:"Continue to login page",VERIFY_SUCCESS:"Account successfully activated",VERIFY_ERROR:"Verification link is invalid or has expired"}),$translateProvider.preferredLanguage("en").fallbackLanguage("en").useSanitizeValueStrategy("escape")}]),angular.module("users").config(["$translateProvider",function($translateProvider){$translateProvider.translations("en",{ACCESS_DENIED_TEXT:"Vouz n’êtes pas autorisé à accéder à cette page.",USERNAME_LABEL:"Nom d’utilisateur",PASSWORD_LABEL:"Mot de Passe",CURRENT_PASSWORD_LABEL:"Mot de passe actuel",NEW_PASSWORD_LABEL:"Nouveau Mot de Passe",VERIFY_PASSWORD_LABEL:"Vérifier le mot de passe",UPDATE_PASSWORD_LABEL:"Mettre à jour le mot de passe",FIRST_NAME_LABEL:"Prénom",LAST_NAME_LABEL:"Nom",LANGUAGE_LABEL:"Langue",EMAIL_LABEL:"Email",UPDATE_PROFILE_BTN:"Modifier le Profil",PROFILE_SAVE_SUCCESS:"Profil enregistré avec succès",PROFILE_SAVE_ERROR:"Erreur: impossible d’enregistrer votre Profile.",FORGOT_PASSWORD_LINK:"Mot de passe oublié ?",REVERIFY_ACCOUNT_LINK:"Re-envoyez un email de vérification",SIGNIN_BTN:"Connexion",SIGNUP_BTN:"Créer un compte",SAVE_PASSWORD_BTN:"Enregistrer votre nouveau Mot de Passe",SUCCESS_HEADER:"Votre Compte a été enregistré !",SUCCESS_TEXT:"Votre compte Tellform a été crée avec succès.",VERIFICATION_EMAIL_SENT:"Un email de verification a été envoyer à",NOT_ACTIVATED_YET:"Mais votre compte n'est pas activé",BEFORE_YOU_CONTINUE:"Avant de continuer, vous devez valider votre adresse mail. Merci de vérifier votre boite mail. Si vous ne l’avez pas reçu dans les prochaines 24h, contactez-nous a ",CHECK_YOUR_EMAIL:"Vérifiez vos emails, et cliquez sur le lien de validation pour activer votre compte. Si vous avez une question contactez-nous à",PASSWORD_RESTORE_HEADER:"Mot de passe perdu",ENTER_YOUR_EMAIL:"Entrer votre email",SUBMIT_BTN:"Enregistrer",ASK_FOR_NEW_PASSWORD:"Demander un nouveau mot de pass ",PASSWORD_RESET_INVALID:"Le nouveau mot de passe est invalid",PASSWORD_RESET_SUCCESS:"Mot de passe réinitialisé avec succès",PASSWORD_CHANGE_SUCCESS:"Mot de passe enregistré avec succès",CONTINUE_TO_LOGIN:"Allez à la page de connexion",VERIFY_SUCCESS:"Votre compte est activé !",VERIFY_ERROR:"Le lien de vérification est invalide ou à expiré"})}]); \ No newline at end of file diff --git a/public/dist/form-application.js b/public/dist/form-application.js new file mode 100644 index 00000000..28db55ce --- /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", + "
{{ 'COMPLETING_NEEDED' | translate:translateAdvancementData }}
{{ 'ENTER' | translate }}

{{ 'ADVANCEMENT' | translate:translateAdvancementData }}

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

{{ 'SIGNIN_HEADER_TEXT' | translate }}

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_HEADER_TEXT' | translate }}

{{'SIGNUP_ERROR_TEXT' | translate}}:
{{ '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..255c25ff --- /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",'
{{ \'COMPLETING_NEEDED\' | translate:translateAdvancementData }}
'),$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","

{{ 'SIGNIN_HEADER_TEXT' | translate }}

Error:
  or  {{ 'SIGNUP_BTN' | translate }}
"),$templateCache.put("modules/users/views/authentication/signup-success.client.view.html",''),$templateCache.put("modules/users/views/authentication/signup.client.view.html",''),$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/base/config/forms.client.config.js b/public/form_modules/forms/base/config/forms.client.config.js new file mode 100644 index 00000000..c4ccc1c4 --- /dev/null +++ b/public/form_modules/forms/base/config/forms.client.config.js @@ -0,0 +1,45 @@ +'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' +]); diff --git a/public/form_modules/forms/base/config/i18n/english.js b/public/form_modules/forms/base/config/i18n/english.js new file mode 100644 index 00000000..6d670c03 --- /dev/null +++ b/public/form_modules/forms/base/config/i18n/english.js @@ -0,0 +1,37 @@ +'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'); + +}]); diff --git a/public/form_modules/forms/base/config/i18n/french.js b/public/form_modules/forms/base/config/i18n/french.js new file mode 100644 index 00000000..ebefc7e5 --- /dev/null +++ b/public/form_modules/forms/base/config/i18n/french.js @@ -0,0 +1,35 @@ +'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', + }); + +}]); diff --git a/public/form_modules/forms/base/config/i18n/german.js b/public/form_modules/forms/base/config/i18n/german.js new file mode 100644 index 00000000..24be68b7 --- /dev/null +++ b/public/form_modules/forms/base/config/i18n/german.js @@ -0,0 +1,35 @@ +'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', + }); + +}]); diff --git a/public/form_modules/forms/base/config/i18n/italian.js b/public/form_modules/forms/base/config/i18n/italian.js new file mode 100644 index 00000000..06cddc67 --- /dev/null +++ b/public/form_modules/forms/base/config/i18n/italian.js @@ -0,0 +1,35 @@ +'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', + }); + +}]); diff --git a/public/form_modules/forms/base/config/i18n/spanish.js b/public/form_modules/forms/base/config/i18n/spanish.js new file mode 100644 index 00000000..ab73d18d --- /dev/null +++ b/public/form_modules/forms/base/config/i18n/spanish.js @@ -0,0 +1,35 @@ +'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' + }); + +}]); diff --git a/public/form_modules/forms/base/controllers/submit-form.client.controller.js b/public/form_modules/forms/base/controllers/submit-form.client.controller.js new file mode 100644 index 00000000..d4f62249 --- /dev/null +++ b/public/form_modules/forms/base/controllers/submit-form.client.controller.js @@ -0,0 +1,12 @@ +'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); + + } +]); diff --git a/public/form_modules/forms/base/css/form.css b/public/form_modules/forms/base/css/form.css new file mode 100644 index 00000000..eb54f1ff --- /dev/null +++ b/public/form_modules/forms/base/css/form.css @@ -0,0 +1,557 @@ +.panel-default.startPage { + border-style: dashed; + border-color: #a9a9a9; + border-width:3px; +} + +.busy-updating-wrapper { + text-align: center; + font-size: 20px; + position: fixed; + bottom: 0; + right: 55px; + z-index: 1; +} + +.busy-submitting-wrapper { + position: fixed; + top: 50%; + left: 0; + right: 0; + bottom: 0; +} + +.dropzone h4.panel-title { + height: 17px; + overflow: hidden; +} + +.container.admin-form { + margin-top: 70px; +} + +.public-form input, .public-form textarea { + background-color: #000000; + background-color: rgba(0,0,0,0); + border: 2px dashed #ddd!important; +} + +.public-form input:focus, .public-form textarea:focus { + border: 2px dashed #ddd!important; + outline: none; +} + +/*.public-form input.no-border.ng-invalid, .public-form textarea.no-border { + border-color: none; +}*/ +.public-form input.ng-valid, .public-form textarea.ng-valid { + border-color: #20FF20!important; + border-style: solid!important; + border-width: 3px!important; +} + +.public-form input.ng-invalid.ng-dirty, .public-form textarea.ng-invalid.ng-dirty { + border-color: #FA787E!important; + border-style: solid!important; + border-width: 3px!important; +} + +section.content p.breakwords { + word-break: break-all; +} + +.btn { + border: 1px solid #c6c6c6; +} + +.btn[type='submit'] { + font-size: 1.5em; + padding: 0.35em 1.2em 0.35em 1.2em; +} + +section.content > section > section.container { + margin-top: 70px; +} + +/* +** Modal CSS Styles +*/ +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; + font-size: 18px; + font-weight: normal; +} +.input-block { + display: block; + width: 100%; +} +.modal-footer input[type='text'] { + min-height: 34px; + padding: 7px 8px; + font-size: 13px; + color: #333; + vertical-align: middle; + background-color: #fff; + background-repeat: no-repeat; + background-position: right 8px center; + border: 1px solid #ccc; + border-radius: 3px; + box-shadow: inset 0 1px 2px rgba(0,0,0,0.075); +} +.modal-footer input[type='text']:focus { + outline: 0; +} +.modal-body > .modal-body-alert { + color: #796620; + background-color: #f8eec7; + border-color: #f2e09a; + margin: -16px -15px 15px; + padding: 10px 15px; + border-style: solid; + border-width: 1px 0; +} + +div.form-fields { + position: relative; + padding-top: 35vh; +} +.letter { + position: relative; + display: -moz-inline-stack; + display: inline-block; + vertical-align: top; + zoom: 1; + width: 16px; + padding: 0; + height: 17px; + font-size: 12px; + line-height: 19px; + border: 1px solid #000; + border: 1px solid rgba(0,0,0,.2); + margin-right: 7px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + text-align: center; + font-weight: 700; +} + +div.form-submitted > .field.row { + padding-bottom: 2%; + margin-top: 35vh; +} +div.form-submitted > .field.row > div { + font-size: 1.7em; +} + +/* Styles for accordion */ +form .accordion-edit { + width: inherit; +} + +/*Styles for ui-datepicker*/ +.ui-datepicker.ui-widget { + z-index: 99!important; +} + +form .row.field .field-number { + margin-right: 0.5em; +} + +/* Styles for form submission view (/forms/:formID) */ +form .row.field { + padding: 1em 0 0 0; + width: inherit; +} + form .row.field > .field-title { + margin-top:0.5em; + font-size:1.2em; + padding-bottom: 1.8em; + width: inherit; + } + form .row.field > .field-input { + font-size: 1.4em; + color: #777; + } + form.submission-form .row.field.statement > .field-title { + font-size:1.7em; + } + form.submission-form .row.field.statement > .field-input { + font-size:1em; + color:#ddd; + } + + form.submission-form .select.radio > .field-input input, form.submission-form .select > .field-input input { + width:20%; + } + + form.submission-form .field.row.radio .btn.activeBtn { + background-color: rgb(0,0,0)!important; + background-color: rgba(0,0,0,0.7)!important; + color: white; + } + form.submission-form .field.row.radio .btn { + margin-right:1.2em; + } + + form.submission-form .select > .field-input .btn { + text-align: left; + margin-bottom:0.7em; + } + form.submission-form .select > .field-input .btn > span { + font-size: 1.10em; + } + + /*form.submission-form .field-input > input:focus { + font-size:1em; + }*/ + + form .field-input > textarea{ + padding: 0.45em 0.9em; + width: 100%; + line-height: 160%; + } + + form .field-input > input.hasDatepicker{ + padding: 0.45em 0.9em; + width: 50%; + line-height: 160%; + } + form .field-input > input.text-field-input{ + padding: 0.45em 0.9em; + width: 100%; + line-height: 160%; + } + form .required-error{ + color: #ddd; + font-size:0.8em; + } + + form .row.field.dropdown > .field-input input { + height: 34px; + border-width: 0 0 2px 0; + border-radius: 5px; + } + + form .row.field.dropdown > .field-input input:focus { + border: none; + } + + form .dropdown > .field-input .ui-select-choices-row-inner { + border-radius: 3px; + margin: 5px; + padding: 10px; + background-color: #000000; + background-color: rgba(0,0,0,0.05); + } + + form .dropdown > .field-input .ui-select-choices-row-inner.active, form .dropdown > .field-input .ui-select-choices-row-inner.active:focus { + background-color: #000000; + background-color: rgba(0,0,0,0.1); + } +.config-form { + max-width: 100%; +} + +.config-form > .row { + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} + +div.config-form .row.field { + padding-top:1.5em; +} + + div.config-form > .row > .container:nth-of-type(odd){ + border-right: 1px #ddd solid; + } + div.config-form.design > .row > .container:nth-of-type(odd){ + border-right: none; + } + + div.config-form .row > .field-input { + padding-left:0.1em; + } + div.config-form .row > .field-input label { + padding-left:1.3em; + display: block; + } + + +/* Styles for form admin view (/forms/:formID/admin) */ +.admin-form > .page-header { + padding-bottom: 0; + margin-bottom: 40px; +} + .admin-form > .page-header h1 { + margin-bottom: 0; + margin-top: 0; + } + .admin-form > .page-header > .col-xs-3 { + padding-top: 1.4em; + } +.admin-form .form-controls .row { + padding: 5px; +} +.admin-form .page-header { + border: none; +} + +/*Styles for admin view tabs */ +.admin-form .tab-content { + padding-top: 3em; +} + +.admin-form .panel-heading { + background-color: #f1f1f1; + position: relative!important; +} + .admin-form .panel-heading:hover { + background-color: #fff; + cursor: pointer; + } + .admin-form .panel-heading a:hover { + text-decoration: none; + } + +.current-fields .panel-body .row.question input[type='text'], .current-fields .panel-body .row.description textarea{ + width: 100%; +} +.current-fields .panel-body .row.options input[type='text'] { + width: 80%; +} + +/*Override Select2 UI*/ +.ui-select-choices.ui-select-dropdown { + top:2.5em!important; +} +.ui-select-toggle { + box-shadow:none!important; + border:none!important; +} + +.current-fields .tool-panel > .panel-default:hover { + border-color: #9d9d9d; + cursor: pointer; +} + +.current-fields .tool-panel > .panel-default .panel-heading { + background-color: #fff; + color: #9d9d9d!important; +} + .current-fields .tool-panel > .panel-default .panel-heading:hover { + background-color: #eee; + color: #000!important; + cursor: pointer; + } +.current-fields .tool-panel > .panel-default .panel-heading a { + color: inherit; +} +.current-fields .tool-panel > .panel-default .panel-heading a:hover{ + text-decoration: none; +} + +/*Styles for submission table*/ +.submissions-table .table-outer.row { + margin: 1.5em 0 2em 0!important; +} +.submissions-table .table-outer .col-xs-12 { + padding-left: 0!important; + border:1px solid #ddd; + overflow-x: scroll; + border-radius:3px; +} +.submissions-table .table > thead > tr > th { + min-width:8em; +} +.submissions-table .table > tbody > tr.selected { + background-color:#efefef; +} + + +/*Styles for add fields tab*/ +.admin-form .add-field { + background-color: #ddd; + padding: 0 2% 0 2%; + border-radius: 3px; +} + .admin-form .add-field .col-xs-6 { + padding: 0.25em 0.4em; + } + .admin-form .add-field .col-xs-6 .panel-heading { + border-width: 1px; + border-style: solid; + border-color: #bbb; + border-radius: 4px; + } + + .admin-form .oscar-field-select { + margin: 10px 0 10px; + } + +.view-form-btn.span { + padding-right:0.6em; +} +.status-light.status-light-off { + color: #BE0000; +} +.status-light.status-light-on { + color: #33CC00; +} + +/* Styles for form list view (/forms) */ +section.public-form { + padding: 0 10% 0 10%; +} +section.public-form .form-submitted { + height: 100vh; +} + +section.public-form .btn { + border: 1px solid; +} + +.form-item { + text-align: center; + border-bottom: 6px inset #ccc; + background-color: #eee; + width: 180px; + /*width:100%;*/ + position: relative; + height: 215px; + /*padding-bottom: 25%;*/ + margin-bottom: 45px; +} +.form-item.create-new input[type='text']{ + width: inherit; + color:black; + border:none; +} + +.form-item.create-new { + background-color: rgb(131,131,131); + color: white; +} + +/*CREATE-NEW FORM MODAL*/ +.form-item.create-new.new-form { + background-color: rgb(300,131,131); + z-index: 11; +} +.form-item.create-new.new-form:hover { + background-color: rgb(300,100,100); +} + .form-item.new-form input[type='text'] { + margin-top:0.2em; + width: inherit; + color:black; + border:none; + padding: 0.3em 0.6em 0.3em 0.6em; + } + .form-item.new-form .custom-select { + margin-top: 0.2em + } + .form-item.new-form .custom-select select { + background-color: white; + } + + + .form-item.new-form .details-row { + margin-top: 1em; + } + .form-item.new-form .details-row.submit { + margin-top: 1.7em; + } + .form-item.new-form .details-row.submit .btn { + font-size: 0.95em; + } + + .form-item.new-form .title-row { + margin-top: 1em; + top:0; + } + +/*Modal overlay (for lightbox effect)*/ +.overlay { + position: fixed; + top: 0; + left: 0; + height: 100%; + width: 100%; + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,0.5); + z-index: 10; +} +.overlay.submitform { + background-color: rgb(256,256,256); + background-color: rgba(256,256,256,0.8); +} +.field-directive { + z-index: 9; + padding: 10% 10% 10% 0; + border: 25px transparent solid; + position: relative; +} +.activeField { + z-index: 11; + position: relative; + background-color: transparent; +} +.activeField.field-directive { + display: inline-block; + border-radius: 7px; + width: 100%; + border: 25px transparent solid; +} + .activeField input { + background-color: transparent; + } + +.form-item:hover, .form-item.create-new:hover { + border-bottom: 8px inset #ccc; + background-color: #d9d9d9; +} + +.form-item.create-new:hover { + background-color: rgb(81,81,81); +} + +.form-item > .row.footer { + position: absolute; + bottom: 0; + left: 30%; +} + +.form-item .title-row{ + position: relative; + top: 15px; + padding-top:3em; + padding-bottom:3.65em; +} + .form-item .title-row h4 { + font-size: 1.3em; + } + +.form-item.create-new .title-row{ + padding: 0; +} + .form-item.create-new .title-row h4 { + font-size: 7em; + } + +.form-item .details-row{ + margin-top: 3.2em; +} + .form-item .details-row small { + font-size: 0.6em; + } + .form-item.create-new .details-row small { + font-size: 0.95em; + } diff --git a/public/form_modules/forms/base/directives/field-icon.client.directive.js b/public/form_modules/forms/base/directives/field-icon.client.directive.js new file mode 100644 index 00000000..23e0cd5c --- /dev/null +++ b/public/form_modules/forms/base/directives/field-icon.client.directive.js @@ -0,0 +1,33 @@ +'use strict'; + +angular.module('view-form').directive('fieldIconDirective', function() { + + return { + template: '', + restrict: 'E', + scope: { + typeName: '@' + }, + controller: 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]; + } + }; +}); diff --git a/public/form_modules/forms/base/directives/field.client.directive.js b/public/form_modules/forms/base/directives/field.client.directive.js new file mode 100644 index 00000000..ccaa3dc7 --- /dev/null +++ b/public/form_modules/forms/base/directives/field.client.directive.js @@ -0,0 +1,108 @@ +'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); + } + }; +}]); diff --git a/public/form_modules/forms/base/directives/on-enter-key.client.directive.js b/public/form_modules/forms/base/directives/on-enter-key.client.directive.js new file mode 100644 index 00000000..afb9e135 --- /dev/null +++ b/public/form_modules/forms/base/directives/on-enter-key.client.directive.js @@ -0,0 +1,76 @@ +'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); + }); + } + }); + } + }; +}]); diff --git a/public/form_modules/forms/base/directives/on-finish-render.client.directive.js b/public/form_modules/forms/base/directives/on-finish-render.client.directive.js new file mode 100644 index 00000000..991ffbca --- /dev/null +++ b/public/form_modules/forms/base/directives/on-finish-render.client.directive.js @@ -0,0 +1,27 @@ +'use strict'; + +angular.module('view-form').directive('onFinishRender', 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'); + }); + } + } + }; +}); diff --git a/public/form_modules/forms/base/directives/submit-form.client.directive.js b/public/form_modules/forms/base/directives/submit-form.client.directive.js new file mode 100644 index 00000000..cd73a32a --- /dev/null +++ b/public/form_modules/forms/base/directives/submit-form.client.directive.js @@ -0,0 +1,239 @@ +'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: 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(); + } + }; + } +]); diff --git a/public/form_modules/forms/base/services/current-form.client.service.js b/public/form_modules/forms/base/services/current-form.client.service.js new file mode 100644 index 00000000..c264f717 --- /dev/null +++ b/public/form_modules/forms/base/services/current-form.client.service.js @@ -0,0 +1,18 @@ +'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; + }; + } +); diff --git a/public/form_modules/forms/base/services/forms.client.service.js b/public/form_modules/forms/base/services/forms.client.service.js new file mode 100644 index 00000000..fd15a9e0 --- /dev/null +++ b/public/form_modules/forms/base/services/forms.client.service.js @@ -0,0 +1,42 @@ +'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' + } + }); + } +]); diff --git a/public/form_modules/forms/base/services/socket.io.client.service.js b/public/form_modules/forms/base/services/socket.io.client.service.js new file mode 100644 index 00000000..f72e325b --- /dev/null +++ b/public/form_modules/forms/base/services/socket.io.client.service.js @@ -0,0 +1,54 @@ +(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); + } + } + } +}()); diff --git a/public/form_modules/forms/base/services/time-counter.client.service.js b/public/form_modules/forms/base/services/time-counter.client.service.js new file mode 100644 index 00000000..bf2f63b8 --- /dev/null +++ b/public/form_modules/forms/base/services/time-counter.client.service.js @@ -0,0 +1,38 @@ +'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/form_modules/forms/base/views/directiveViews/entryPage/startPage.html b/public/form_modules/forms/base/views/directiveViews/entryPage/startPage.html new file mode 100644 index 00000000..d13f1715 --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/entryPage/startPage.html @@ -0,0 +1,24 @@ +
+
+

{{pageData.introTitle}}

+
+
+

{{pageData.introParagraph}}

+
+
+ + diff --git a/public/form_modules/forms/base/views/directiveViews/field/date.html b/public/form_modules/forms/base/views/directiveViews/field/date.html new file mode 100755 index 00000000..e7f02391 --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/field/date.html @@ -0,0 +1,33 @@ +
+
+

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

+

+ {{field.description}} +

+
+
+
+ +
+
+
diff --git a/public/form_modules/forms/base/views/directiveViews/field/dropdown.html b/public/form_modules/forms/base/views/directiveViews/field/dropdown.html new file mode 100755 index 00000000..ec5cba2c --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/field/dropdown.html @@ -0,0 +1,36 @@ + +
diff --git a/public/form_modules/forms/base/views/directiveViews/field/dropdown.html~HEAD b/public/form_modules/forms/base/views/directiveViews/field/dropdown.html~HEAD new file mode 100755 index 00000000..c0e98b75 --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/field/dropdown.html~HEAD @@ -0,0 +1,27 @@ + +
diff --git a/public/form_modules/forms/base/views/directiveViews/field/file.html b/public/form_modules/forms/base/views/directiveViews/field/file.html new file mode 100644 index 00000000..70c7f9e2 --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/field/file.html @@ -0,0 +1,38 @@ +
+
+

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

+
+
+
+
+ +
+ {{field.file.originalname}} +
+
+
+ + + + +
+ + {{ UPLOAD_FILE | translate }} +
+
+
+
+
diff --git a/public/form_modules/forms/base/views/directiveViews/field/hidden.html b/public/form_modules/forms/base/views/directiveViews/field/hidden.html new file mode 100755 index 00000000..6aae485a --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/field/hidden.html @@ -0,0 +1 @@ + diff --git a/public/form_modules/forms/base/views/directiveViews/field/legal.html b/public/form_modules/forms/base/views/directiveViews/field/legal.html new file mode 100644 index 00000000..0ee6e101 --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/field/legal.html @@ -0,0 +1,55 @@ + +
diff --git a/public/form_modules/forms/base/views/directiveViews/field/radio.html b/public/form_modules/forms/base/views/directiveViews/field/radio.html new file mode 100755 index 00000000..92c50a7e --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/field/radio.html @@ -0,0 +1,42 @@ +
+
+

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

+

+ {{field.description}} +

+
+
+ +
+ +
+
+
+
diff --git a/public/form_modules/forms/base/views/directiveViews/field/rating.html b/public/form_modules/forms/base/views/directiveViews/field/rating.html new file mode 100644 index 00000000..23a6c0b0 --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/field/rating.html @@ -0,0 +1,34 @@ +
+
+

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

+

+ {{field.description}} +

+
+
+ + + +
+
diff --git a/public/form_modules/forms/base/views/directiveViews/field/statement.html b/public/form_modules/forms/base/views/directiveViews/field/statement.html new file mode 100644 index 00000000..99e8045e --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/field/statement.html @@ -0,0 +1,24 @@ +
+
+
+

{{field.title}}

+

+ {{field.description}} +

+
+
+

{{field.description}}

+
+
+ +
+
+
diff --git a/public/form_modules/forms/base/views/directiveViews/field/textarea.html b/public/form_modules/forms/base/views/directiveViews/field/textarea.html new file mode 100755 index 00000000..b9641100 --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/field/textarea.html @@ -0,0 +1,49 @@ +
+
+

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

+ {{ 'NEWLINE' | translate }} +

+ {{field.description}} +

+
+
+ Press SHIFT+ENTER to add a newline + +
+
+ +
+ +
diff --git a/public/form_modules/forms/base/views/directiveViews/field/textfield.html b/public/form_modules/forms/base/views/directiveViews/field/textfield.html new file mode 100755 index 00000000..fc281d65 --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/field/textfield.html @@ -0,0 +1,65 @@ +
+
+

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

+ +

+ {{field.description}} +

+
+
+ +
+
+ +
+
+
+ +
diff --git a/public/form_modules/forms/base/views/directiveViews/field/yes_no.html b/public/form_modules/forms/base/views/directiveViews/field/yes_no.html new file mode 100644 index 00000000..ff4640f6 --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/field/yes_no.html @@ -0,0 +1,63 @@ +
+
+

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

+

+ {{field.description}} +

+
+ +
+
+ +
+ +
+ +
+
+
+
diff --git a/public/form_modules/forms/base/views/directiveViews/form/submit-form.client.view.html b/public/form_modules/forms/base/views/directiveViews/form/submit-form.client.view.html new file mode 100755 index 00000000..3cd3f7dd --- /dev/null +++ b/public/form_modules/forms/base/views/directiveViews/form/submit-form.client.view.html @@ -0,0 +1,156 @@ +
+ + +
+
+
+

+{{myform.startPage.introTitle}} +

+
+
+

+{{myform.startPage.introParagraph}} +

+
+
+ +
+ +
+ +
+ + +
+ +
+
+ +
+ + + +
+ + +
+
+ + +
+ +
+ {{ 'COMPLETING_NEEDED' | translate:translateAdvancementData }} +
+ + + + + + +
+ + +
+ + + diff --git a/public/form_modules/forms/base/views/submit-form.client.view.html b/public/form_modules/forms/base/views/submit-form.client.view.html new file mode 100644 index 00000000..edd50e58 --- /dev/null +++ b/public/form_modules/forms/base/views/submit-form.client.view.html @@ -0,0 +1,17 @@ + + +
+ +
+ + + + diff --git a/public/form_modules/forms/config/forms.client.config.js b/public/form_modules/forms/config/forms.client.config.js new file mode 100644 index 00000000..188c56e5 --- /dev/null +++ b/public/form_modules/forms/config/forms.client.config.js @@ -0,0 +1,29 @@ +'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; + }; +}); diff --git a/public/form_modules/forms/config/forms.client.routes.js b/public/form_modules/forms/config/forms.client.routes.js new file mode 100644 index 00000000..b0e0efb5 --- /dev/null +++ b/public/form_modules/forms/config/forms.client.routes.js @@ -0,0 +1,22 @@ +'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: function (Forms, $stateParams) { + return Forms.get({formId: $stateParams.formId}).$promise; + } + }, + controller: 'SubmitFormController', + controllerAs: 'ctrl' + }) + } +]); diff --git a/public/form_modules/forms/directives/analytics-service.client.directive.js b/public/form_modules/forms/directives/analytics-service.client.directive.js new file mode 100644 index 00000000..2015eb2e --- /dev/null +++ b/public/form_modules/forms/directives/analytics-service.client.directive.js @@ -0,0 +1,43 @@ +(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; + + } +}()); + diff --git a/public/form_modules/forms/directives/key-to-option.client.directive.js b/public/form_modules/forms/directives/key-to-option.client.directive.js new file mode 100644 index 00000000..2a4a7de8 --- /dev/null +++ b/public/form_modules/forms/directives/key-to-option.client.directive.js @@ -0,0 +1,26 @@ +'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; + }); + } + + }); + } + }; +}); diff --git a/public/form_modules/forms/directives/key-to-truthy.client.directive.js b/public/form_modules/forms/directives/key-to-truthy.client.directive.js new file mode 100644 index 00000000..175bf36d --- /dev/null +++ b/public/form_modules/forms/directives/key-to-truthy.client.directive.js @@ -0,0 +1,30 @@ +'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'; + }); + } + }); + } + }; +}]); + diff --git a/public/form_modules/forms/forms.client.module.js b/public/form_modules/forms/forms.client.module.js new file mode 100644 index 00000000..c56beb5f --- /dev/null +++ b/public/form_modules/forms/forms.client.module.js @@ -0,0 +1,7 @@ +'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 diff --git a/public/humans.txt b/public/humans.txt index 08d7ac69..3600069a 100755 --- a/public/humans.txt +++ b/public/humans.txt @@ -4,13 +4,13 @@ # TEAM David Baldwynn -- Developer -- @davidbaldwynn + Samuel Laulhau -- Developer -- @_samuel_ # THANKS Grace Lam - # TECHNOLOGY COLOPHON HTML5, CSS3, AngularJS - jQuery, Modernizr, ExpressJS + jQuery, ExpressJS, NodeJS diff --git a/public/modules/core/config/core.client.routes.js b/public/modules/core/config/core.client.routes.js index 765db68f..6a84af0e 100755 --- a/public/modules/core/config/core.client.routes.js +++ b/public/modules/core/config/core.client.routes.js @@ -7,3 +7,61 @@ angular.module('core').config(['$stateProvider', '$urlRouterProvider', $urlRouterProvider.otherwise('/forms'); } ]); + +angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', '$state', '$stateParams', + function($rootScope, Auth, $state, $stateParams) { + + $rootScope.$state = $state; + $rootScope.$stateParams = $stateParams; + + // add previous state property + $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) { + $state.previous = fromState; + //console.log('toState: '+toState.name); + + var statesToIgnore = ['home', 'signin', 'resendVerifyEmail', 'verify', 'signup', 'signup-success', 'forgot', 'reset-invalid', 'reset', 'reset-success']; + + //Redirect to listForms if user is authenticated + if(statesToIgnore.indexOf(toState.name) > 0){ + if(Auth.isAuthenticated()){ + event.preventDefault(); // stop current execution + //console.log('go to forms'); + $state.go('listForms'); // go to listForms page + } + } + //Redirect to 'signup' route if user is not authenticated + else if(toState.name !== 'access_denied' && !Auth.isAuthenticated() && toState.name !== 'submitForm'){ + console.log('go to signup'); + event.preventDefault(); // stop current execution + $state.go('listForms'); // go to listForms page + } + + }); + + } +]); + +//Page access/authorization logic +angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', 'User', 'Authorizer', '$state', '$stateParams', + function($rootScope, Auth, User, Authorizer, $state, $stateParams) { + $rootScope.$on('$stateChangeStart', function(event, next) { + var authenticator, permissions, user; + permissions = next && next.data && next.data.permissions ? next.data.permissions : null; + + Auth.ensureHasCurrentUser(User); + user = Auth.currentUser; + + if(user){ + authenticator = new Authorizer(user); + //console.log('access denied: '+!authenticator.canAccess(permissions)); + //console.log(permissions); + if( (permissions !== null) ){ + if( !authenticator.canAccess(permissions) ){ + event.preventDefault(); + //console.log('access denied'); + $state.go('access_denied'); + } + } + } + }); + }]); diff --git a/public/modules/core/services/subdomain.client.service.js b/public/modules/core/services/subdomain.client.service.js new file mode 100644 index 00000000..eaa9c90b --- /dev/null +++ b/public/modules/core/services/subdomain.client.service.js @@ -0,0 +1,9 @@ +'use strict'; + +angular.module('core').factory('subdomain', ['$location', function ($location) { + var host = $location.host(); + if (host.indexOf('.') < 0) + return null; + else + return host.split('.')[0]; +}]); diff --git a/public/modules/forms/admin/controllers/admin-form.client.controller.js b/public/modules/forms/admin/controllers/admin-form.client.controller.js index a024b2e8..74bb4001 100644 --- a/public/modules/forms/admin/controllers/admin-form.client.controller.js +++ b/public/modules/forms/admin/controllers/admin-form.client.controller.js @@ -11,6 +11,8 @@ angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope CurrentForm.setForm($scope.myform); + $scope.formURL = $scope.myform.admin.username + '.' + window.location.host; + $scope.tabData = [ { heading: $filter('translate')('CREATE_TAB'), diff --git a/public/modules/forms/admin/controllers/list-forms.client.controller.js b/public/modules/forms/admin/controllers/list-forms.client.controller.js index 57cc26dc..11ce5268 100644 --- a/public/modules/forms/admin/controllers/list-forms.client.controller.js +++ b/public/modules/forms/admin/controllers/list-forms.client.controller.js @@ -8,7 +8,7 @@ angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope $scope.forms = {}; $scope.showCreateModal = false; - $scope.languageRegExp = $scope.myPt = { + $rootScope.languageRegExp = { regExp: /[@!#$%^&*()\-+={}\[\]|\\/'";:`.,~№?<>]+/i, test: function(val) { return !this.regExp.test(val); diff --git a/public/modules/forms/admin/directives/edit-submissions-form.client.directive.js b/public/modules/forms/admin/directives/edit-submissions-form.client.directive.js index c02b8c70..bafc342f 100644 --- a/public/modules/forms/admin/directives/edit-submissions-form.client.directive.js +++ b/public/modules/forms/admin/directives/edit-submissions-form.client.directive.js @@ -63,7 +63,7 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', completion: 0, average_time: 0, total_time: 0 - } + }; }; var stats = { diff --git a/public/modules/forms/admin/views/admin-form.client.view.html b/public/modules/forms/admin/views/admin-form.client.view.html index 47943672..8ebfea38 100644 --- a/public/modules/forms/admin/views/admin-form.client.view.html +++ b/public/modules/forms/admin/views/admin-form.client.view.html @@ -43,7 +43,7 @@
- +