'use strict'; // Init the application configuration module for AngularJS application var ApplicationConfiguration = (function() { // Init module configuration options var applicationModuleName = 'TellForm'; var applicationModuleVendorDependencies = ['duScroll', 'ui.select', 'ngSanitize', 'vButton', 'ngResource', 'TellForm.templates', 'ui.router', 'ui.bootstrap', 'ui.utils', 'pascalprecht.translate', 'view-form']; // 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('TellForm.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", "

{{ 'TELLFORM_URL' | translate }}
{{ 'COPY_AND_PASTE' | 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/list-forms.client.view.html", "

{{ 'CREATE_A_NEW_FORM' | translate }}
{{ 'NAME' | translate }}
{{ 'LANGUAGE' | translate }}

{{ form.numberOfResponses }} {{ 'RESPONSES' | translate }}

{{ 'FORM_PAUSED' | translate }}
"); $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/directiveViews/form/configure-form.client.view.html", "
{{ 'FORM_NAME' | translate }}
{{ 'FORM_STATUS' | translate }}
{{ 'LANGUAGE' | translate }}
* {{ 'REQUIRED_FIELD' | translate }}
{{ 'GA_TRACKING_CODE' | translate }}
{{ 'DISPLAY_FOOTER' | translate }}
{{ 'DISPLAY_START_PAGE' | translate }}
{{ 'DISPLAY_END_PAGE' | translate }}
"); $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 }}

{{ 'WELCOME_SCREEN' | translate }}


{{field.title}} *

{{ 'CLICK_FIELDS_FOOTER' | translate }}


{{ 'END_SCREEN' | translate }}

"); $templateCache.put("modules/forms/admin/views/directiveViews/form/edit-submissions-form.client.view.html", "
{{ 'TOTAL_VIEWS' | translate }}
{{ 'RESPONSES' | translate }}
{{ 'COMPLETION_RATE' | translate }}
{{ 'AVERAGE_TIME_TO_COMPLETE' | translate }}
{{myform.analytics.visitors.length}}
{{myform.analytics.submissions}}
{{myform.analytics.conversionRate | number:0}}%
{{ AverageTimeElapsed | secondsToDateTime | date:'mm:ss'}}
{{ '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_TITLE' | translate }}
{{ 'FIELD_VIEWS' | translate }}
{{ 'FIELD_RESPONSES' | translate }}
{{ 'FIELD_DROPOFF' | translate }}
{{fieldStats.field.title}}
{{fieldStats.totalViews}}
{{fieldStats.responses}}
{{fieldStats.continueRate}}%

#{{value.title}}{{ 'PERCENTAGE_COMPLETE' | translate }}{{ 'TIME_ELAPSED' | translate }}{{ 'DEVICE' | translate }}{{ 'LOCATION' | translate }}{{ 'IP_ADDRESS' | translate }}{{ 'DATE_SUBMITTED' | translate }} (UTC)
{{$index+1}}{{field.fieldValue}}{{row.percentageComplete}}%{{row.timeElapsed | secondsToDateTime | date:'mm:ss'}}{{row.device.name}}, {{row.device.type}}{{row.geoLocation.City}}, {{row.geoLocation.Country}}{{row.ipAddr}}{{row.created | date:'yyyy-MM-dd HH:mm:ss'}}
"); $templateCache.put("modules/users/views/authentication/access-denied.client.view.html", "

{{ 'ACCESS_DENIED_TEXT' | translate }}

"); $templateCache.put("modules/users/views/authentication/signin.client.view.html", "
{{ 'ERROR' | 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 }} team@tellform.com

"); $templateCache.put("modules/users/views/authentication/signup.client.view.html", "
{{'SIGNUP_ERROR_TEXT' | translate}}:
"); $templateCache.put("modules/users/views/password/forgot-password.client.view.html", "
{{ 'ERROR' | translate }}: {{error}}
{{success}}
"); $templateCache.put("modules/users/views/password/reset-password-invalid.client.view.html", "

{{ 'PASSWORD_RESET_INVALID' | translate }}

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

{{ 'PASSWORD_RESET_SUCCESS' | translate }}

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

{{ 'RESET_PASSWORD' | translate }}

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

{{ 'CHANGE_PASSWORD' | translate }}


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

{{ 'EDIT_PROFILE' | translate }}

{{ 'PROFILE_SAVE_SUCCESS' | translate }}
{{ 'PROFILE_SAVE_ERROR' | translate }}
{{ 'FIRST_NAME_LABEL' | translate }}
{{ 'LAST_NAME_LABEL' | translate }}

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

{{ 'CONNECTED_SOCIAL_ACCOUNTS' | translate }}:

{{ 'CONNECT_OTHER_SOCIAL_ACCOUNTS' | translate }}

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

{{ 'VERIFICATION_EMAIL_SENT' | translate }}

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

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

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

{{ 'VERIFY_SUCCESS' | translate }}

"); $templateCache.put("form_modules/forms/base/views/directiveViews/entryPage/startPage.html", "

{{pageData.introTitle}}

{{pageData.introParagraph}}

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

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

{{field.description}}

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

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

{{field.description}}


"); $templateCache.put("form_modules/forms/base/views/directiveViews/field/hidden.html", ""); $templateCache.put("form_modules/forms/base/views/directiveViews/field/legal.html", "

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


{{field.description}}


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

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

{{field.description}}


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

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

{{field.description}}

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

{{field.title}}

{{field.description}}

{{field.description}}


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

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

{{ 'NEWLINE' | translate }}

{{field.description}}

{{ 'ADD_NEW_LINE_INSTR' | translate }}
{{ 'ENTER' | translate }}
"); $templateCache.put("form_modules/forms/base/views/directiveViews/field/textfield.html", "

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

{{field.description}}

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

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

{{field.description}}


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

{{myform.startPage.introTitle}}

{{myform.startPage.introParagraph}}

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

{{ 'ADVANCEMENT' | translate:translateAdvancementData }}

{{ 'FORM_SUCCESS' | translate }}

{{myform.endPage.title}}

{{myform.endPage.paragraph}}

"); $templateCache.put("form_modules/forms/base/views/form-not-found.client.view.html", "

{{ 'FORM_404_HEADER' | translate }}

{{ 'FORM_404_BODY' | translate }}
"); $templateCache.put("form_modules/forms/base/views/form-unauthorized.client.view.html", "

{{ 'FORM_UNAUTHORIZED_HEADER' | translate }}

{{ 'FORM_UNAUTHORIZED_BODY1' | translate }}
{{ 'FORM_UNAUTHORIZED_BODY2' | translate }}
"); $templateCache.put("form_modules/forms/base/views/submit-form.client.view.html", "
"); }]); 'use strict'; // Use Application configuration module to register a new module ApplicationConfiguration.registerModule('core', ['users']); 'use strict'; // Use Application configuration module to register a new module ApplicationConfiguration.registerModule('forms', [ 'ngFileUpload', 'ui.router.tabs', 'ui.date', 'ui.sortable', 'angular-input-stars', 'users', 'ngclipboard' ]);//, 'colorpicker.module' @TODO reactivate this module 'use strict'; // Use Application configuration module to register a new module ApplicationConfiguration.registerModule('users'); 'use strict'; // Setting up route angular.module('core').config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider, Authorization) { // Redirect to home view when route not found $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; 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 $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'){ 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); if( (permissions !== null) ){ if( !authenticator.canAccess(permissions) ){ event.preventDefault(); $state.go('access_denied'); } } } }); }]); 'use strict'; angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User', '$window', '$translate', function ($rootScope, $scope, Menus, $state, Auth, User, $window, $translate) { $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']; //Set global app language $rootScope.language = $scope.user.language; $translate.use($scope.user.language); $scope.isCollapsed = false; $rootScope.hideNav = false; $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'); //Refresh view $state.reload(); }, function(reason) { console.error('Logout Failed: ' + reason); }); }; $scope.toggleCollapsibleMenu = function() { $scope.isCollapsed = !$scope.isCollapsed; }; // Collapsing the menu after navigation $scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) { $scope.isCollapsed = false; $rootScope.hideNav = false; if ( angular.isDefined( toState.data ) ) { if ( angular.isDefined( toState.data.hideNav ) ) { $rootScope.hideNav = toState.data.hideNav; } } }); } ]); 'use strict'; //Menu service used for managing menus angular.module('core').service('Menus', [ function() { // Define a set of default roles this.defaultRoles = ['*']; // Define the menus object this.menus = {}; // A private function for rendering decision var shouldRender = function(user) { if (user) { if (~this.roles.indexOf('*')) { return true; } for (var userRoleIndex in user.roles) { for (var roleIndex in this.roles) { if (this.roles[roleIndex] === user.roles[userRoleIndex]) { return true; } } } return false; } return this.isPublic; }; // Validate menu existance this.validateMenuExistance = function(menuId) { if (menuId && menuId.length) { if (this.menus[menuId]) { return true; } else { throw new Error('Menu does not exists'); } } else { throw new Error('MenuId was not provided'); } }; // Get the menu object by menu id this.getMenu = function(menuId) { // Validate that the menu exists this.validateMenuExistance(menuId); // Return the menu object return this.menus[menuId]; }; // Add new menu object by menu id this.addMenu = function(menuId, isPublic, roles) { // Create the new menu this.menus[menuId] = { isPublic: isPublic || false, roles: roles || this.defaultRoles, items: [], shouldRender: shouldRender }; // Return the menu object return this.menus[menuId]; }; // Remove existing menu object by menu id this.removeMenu = function(menuId) { // Validate that the menu exists this.validateMenuExistance(menuId); // Return the menu object delete this.menus[menuId]; }; // Add menu item object this.addMenuItem = function(menuId, menuItemTitle, menuItemURL, menuItemType, menuItemUIRoute, isPublic, roles, position) { // Validate that the menu exists this.validateMenuExistance(menuId); // Push new menu item this.menus[menuId].items.push({ title: menuItemTitle, link: menuItemURL, menuItemType: menuItemType || 'item', menuItemClass: menuItemType, uiRoute: menuItemUIRoute || ('/' + menuItemURL), isPublic: ((isPublic === null || typeof isPublic === 'undefined') ? this.menus[menuId].isPublic : isPublic), roles: ((roles === null || typeof roles === 'undefined') ? this.menus[menuId].roles : roles), position: position || 0, items: [], shouldRender: shouldRender }); // Return the menu object return this.menus[menuId]; }; // Add submenu item object this.addSubMenuItem = function(menuId, rootMenuItemURL, menuItemTitle, menuItemURL, menuItemUIRoute, isPublic, roles, position) { // Validate that the menu exists this.validateMenuExistance(menuId); // Search for menu item for (var itemIndex in this.menus[menuId].items) { if (this.menus[menuId].items[itemIndex].link === rootMenuItemURL) { // Push new submenu item this.menus[menuId].items[itemIndex].items.push({ title: menuItemTitle, link: menuItemURL, uiRoute: menuItemUIRoute || ('/' + menuItemURL), isPublic: ((isPublic === null || typeof isPublic === 'undefined') ? this.menus[menuId].items[itemIndex].isPublic : isPublic), roles: ((roles === null || typeof roles === 'undefined') ? this.menus[menuId].items[itemIndex].roles : roles), position: position || 0, shouldRender: shouldRender }); } } // Return the menu object return this.menus[menuId]; }; // Remove existing menu object by menu id this.removeMenuItem = function(menuId, menuItemURL) { // Validate that the menu exists this.validateMenuExistance(menuId); // Search for menu item to remove for (var itemIndex in this.menus[menuId].items) { if (this.menus[menuId].items[itemIndex].link === menuItemURL) { this.menus[menuId].items.splice(itemIndex, 1); } } // Return the menu object return this.menus[menuId]; }; // Remove existing menu object by menu id this.removeSubMenuItem = function(menuId, submenuItemURL) { // Validate that the menu exists this.validateMenuExistance(menuId); // Search for menu item to remove for (var itemIndex in this.menus[menuId].items) { for (var subitemIndex in this.menus[menuId].items[itemIndex].items) { if (this.menus[menuId].items[itemIndex].items[subitemIndex].link === submenuItemURL) { this.menus[menuId].items[itemIndex].items.splice(subitemIndex, 1); } } } // Return the menu object return this.menus[menuId]; }; //Adding the topbar menu this.addMenu('topbar', false, ['*']); //Adding the bottombar menu for the Form-Footer view this.addMenu('bottombar', false, ['*']); } ]); 'use strict'; angular.module('core').factory('subdomain', ['$location', function ($location) { var host = $location.host(); if (host.indexOf('.') < 0) { return null; } return host.split('.')[0]; }]); 'use strict'; // Configuring the Forms drop-down menus angular.module('forms').run(['Menus', function(Menus) { // Set top bar menu items Menus.addMenuItem('topbar', 'My Forms', 'forms', '', '/forms', false); } ]).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){ //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); } else if(field.fieldType === 'rating'){ return true; } }).length; return valid_count - (formObj.form_fields.length - formObj.visible_form_fields.length); } return 0; }; }]).filter('trustSrc', ['$sce', function($sce){ return function(formUrl){ return $sce.trustAsResourceUrl(formUrl); }; }]).config(['$provide', function ($provide){ $provide.decorator('accordionDirective', ["$delegate", function($delegate) { var directive = $delegate[0]; directive.replace = true; return $delegate; }]); }]); 'use strict'; // Setting up route angular.module('forms').config(['$stateProvider', function($stateProvider) { // Forms state routing $stateProvider. state('listForms', { url: '/forms', templateUrl: 'modules/forms/admin/views/list-forms.client.view.html', resolve: { Forms: 'GetForms', myForms: ["GetForms", "$q", function (GetForms, $q) { var deferred = $q.defer(); GetForms.query(function(forms){ deferred.resolve(forms); }); return deferred.promise; }] }, controller: 'ListFormsController', controllerAs: 'ctrl' }).state('submitForm', { url: '/forms/:formId', templateUrl: '/static/form_modules/forms/base/views/submit-form.client.view.html', data: { hideNav: true }, resolve: { Forms: 'GetForms', myForm: ["GetForms", "$stateParams", "$q", function (GetForms, $stateParams, $q) { var deferred = $q.defer(); GetForms.get({formId: $stateParams.formId}, function(resolvedForm){ deferred.resolve(resolvedForm); }); return deferred.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: { GetForms: 'GetForms', myForm: ["GetForms", "$stateParams", "$q", function (GetForms, $stateParams, $q) { var deferred = $q.defer(); GetForms.get({formId: $stateParams.formId}, function(resolvedForm){ deferred.resolve(resolvedForm); }); return deferred.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' }); } ]); 'use strict'; //Forms service used for communicating with the forms REST endpoints angular.module('forms').factory('GetForms', ['$resource', 'FORM_URL', function($resource, FORM_URL) { return $resource(FORM_URL, { formId: '@_id' }, { 'query' : { method: 'GET', isArray: true }, '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' } }); } ]); 'use strict'; // Config HTTP Error Handling angular.module('users').config(['$httpProvider', function($httpProvider) { $httpProvider.interceptors.push(["$q", "$location", function($q, $location) { return { responseError: function(response) { if( $location.path() !== '/users/me' && response.config){ if(response.config.url !== '/users/me'){ if (response.status === 401) { // save the current location so that login can redirect back $location.nextAfterLogin = $location.path(); $location.path('/signin'); }else if(response.status === 403){ $location.path('/access_denied'); } } } return $q.reject(response); } }; }]); }]); 'use strict'; // Setting up route angular.module('users').config(['$stateProvider', function($stateProvider) { var checkLoggedin = function($q, $timeout, $state, User, Auth) { var deferred = $q.defer(); if (Auth.currentUser && Auth.currentUser.email) { $timeout(deferred.resolve); } else { Auth.currentUser = User.getCurrent( function() { Auth.login(); $timeout(deferred.resolve()); }, function() { Auth.logout(); $timeout(deferred.reject()); $state.go('signin', {reload: true}); }); } return deferred.promise; }; checkLoggedin.$inject = ["$q", "$timeout", "$state", "User", "Auth"]; var checkSignupDisabled = function($window, $timeout, $q) { var deferred = $q.defer(); if($window.signupDisabled) { $timeout(deferred.reject()); } else { $timeout(deferred.resolve()); } return deferred.promise; }; checkSignupDisabled.$inject = ["$window", "$timeout", "$q"]; // Users state routing $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' }); } ]); 'use strict'; angular.module('users').controller('AuthenticationController', ['$scope', '$location', '$state', '$rootScope', 'User', 'Auth', '$translate', '$window', function($scope, $location, $state, $rootScope, User, Auth, $translate, $window) { $scope = $rootScope; $scope.credentials = {}; $scope.error = ''; $scope.forms = {}; $scope.signin = function() { if(!$scope.forms.signinForm.$invalid){ User.login($scope.credentials).then( function(response) { Auth.login(response); $scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User); if($state.previous.name !== 'home' && $state.previous.name !== 'verify' && $state.previous.name !== '') { $state.go($state.previous.name); } else { $state.go('listForms'); } }, function(error) { $rootScope.user = Auth.ensureHasCurrentUser(User); $scope.user = $rootScope.user; $scope.error = error; console.error('loginError: '+error); } ); } }; $scope.signup = function() { if($scope.credentials === 'admin'){ $scope.error = 'Username cannot be \'admin\'. Please pick another username.'; return; } if(!$scope.forms.signupForm.$invalid){ User.signup($scope.credentials).then( function(response) { $state.go('signup-success'); }, function(error) { console.error(error); if(error) { $scope.error = error; console.error(error); } else { console.error('No response received'); } } ); } }; } ]); 'use strict'; angular.module('users').controller('PasswordController', ['$scope', '$stateParams', '$state', 'User', '$translate', '$window', function($scope, $stateParams, $state, User, $translate, $window) { $translate.use($window.locale); $scope.error = ''; $scope.forms = {}; // Submit forgotten password account id $scope.askForPasswordReset = function() { User.askForPasswordReset($scope.credentials).then( function(response){ $scope.success = response.message; $scope.error = null; $scope.credentials = null; }, function(error){ $scope.error = error; $scope.success = null; $scope.credentials = null; } ); }; // Change user password $scope.resetUserPassword = function() { if(!$scope.forms.resetPasswordForm.$invalid){ $scope.success = $scope.error = null; User.resetPassword($scope.passwordDetails, $stateParams.token).then( function(response){ // If successful show success message and clear form $scope.success = response.message; $scope.error = null; $scope.passwordDetails = null; // And redirect to the index page $state.go('reset-success'); }, function(error){ $scope.error = error.message || error; $scope.success = null; $scope.passwordDetails = null; } ); } }; } ]); 'use strict'; angular.module('users').controller('SettingsController', ['$scope', '$rootScope', '$http', '$state', 'Users', 'Auth', function($scope, $rootScope, $http, $state, Users, Auth) { $scope.user = Auth.currentUser; // Check if there are additional accounts $scope.hasConnectedAdditionalSocialAccounts = function(provider) { for (var i in $scope.user.additionalProvidersData) { return true; } return false; }; $scope.cancel = function(){ $scope.user = Auth.currentUser; }; // Check if provider is already in use with current user $scope.isConnectedSocialAccount = function(provider) { return $scope.user.provider === provider || ($scope.user.additionalProvidersData && $scope.user.additionalProvidersData[provider]); }; // Remove a user social account $scope.removeUserSocialAccount = function(provider) { $scope.success = $scope.error = null; $http.delete('/users/accounts', { params: { provider: provider } }).success(function(response) { // If successful show success message and clear form $scope.success = true; $scope.error = null; $scope.user = response; }).error(function(response) { $scope.success = null; $scope.error = response.message; }); }; // Update a user profile $scope.updateUserProfile = function(isValid) { if (isValid) { $scope.success = $scope.error = null; var user = new Users($scope.user); user.$update(function(response) { $scope.success = true; $scope.error = null; $scope.user = response; }, function(response) { $scope.success = null; $scope.error = response.data.message; }); } else { $scope.submitted = true; } }; // Change user password $scope.changeUserPassword = function() { $scope.success = $scope.error = null; $http.post('/users/password', $scope.passwordDetails).success(function(response) { // If successful show success message and clear form $scope.success = true; $scope.error = null; $scope.passwordDetails = null; }).error(function(response) { $scope.success = null; $scope.error = response.message; }); }; } ]); 'use strict'; angular.module('users').controller('VerifyController', ['$scope', '$state', '$rootScope', 'User', 'Auth', '$stateParams', '$translate', '$window', function($scope, $state, $rootScope, User, Auth, $stateParams, $translate, $window) { $translate.use($window.locale); $scope.isResetSent = false; $scope.credentials = {}; $scope.error = ''; // Submit forgotten password account id $scope.resendVerifyEmail = function() { User.resendVerifyEmail($scope.credentials.email).then( function(response){ $scope.success = response.message; $scope.error = null; $scope.credentials = null; $scope.isResetSent = true; }, function(error){ $scope.error = error; $scope.success = null; $scope.credentials.email = null; $scope.isResetSent = false; } ); }; //Validate Verification Token $scope.validateVerifyToken = function() { if($stateParams.token){ console.log($stateParams.token); User.validateVerifyToken($stateParams.token).then( function(response){ $scope.success = response.message; $scope.error = null; $scope.isResetSent = true; $scope.credentials.email = null; }, function(error){ $scope.isResetSent = false; $scope.success = null; $scope.error = error; $scope.credentials.email = null; } ); } }; } ]); 'use strict'; angular.module('users').factory('Auth', ['$window', function($window) { var userState = { isLoggedIn: false }; var service = { _currentUser: null, get currentUser(){ return this._currentUser; }, // Note: we can't make the User a dependency of Auth // because that would create a circular dependency // Auth <- $http <- $resource <- LoopBackResource <- User <- Auth ensureHasCurrentUser: function(User) { if (service._currentUser && service._currentUser.username) { return service._currentUser; } else if ($window.user){ service._currentUser = $window.user; return service._currentUser; } else{ User.getCurrent().then(function(user) { // success service._currentUser = user; userState.isLoggedIn = true; $window.user = service._currentUser; return service._currentUser; }, function(response) { userState.isLoggedIn = false; service._currentUser = null; $window.user = null; return null; }); } }, isAuthenticated: function() { return !!service._currentUser; }, getUserState: function() { return userState; }, login: function(new_user) { userState.isLoggedIn = true; service._currentUser = new_user; }, logout: function() { $window.user = null; userState.isLoggedIn = false; service._currentUser = null; } }; return service; } ]); 'use strict'; 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; if (!angular.isArray(permissions)) { permissions = [permissions]; } for (i = 0, len = permissions.length; i < len; i++) { permission = permissions[i]; if (APP_PERMISSIONS[permission] === null) { throw 'Bad permission value'; } if (user && user.roles) { 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; } } else { return false; } } return false; } }; }; }]); 'use strict'; angular.module('users').factory('User', ['$window', '$q', '$timeout', '$http', '$state', function($window, $q, $timeout, $http, $state) { var userService = { getCurrent: function() { var deferred = $q.defer(); $http.get('/users/me') .success(function(response) { deferred.resolve(response); }) .error(function() { deferred.reject('User\'s session has expired'); }); return deferred.promise; }, login: function(credentials) { var deferred = $q.defer(); $http.post('/auth/signin', credentials).then(function(response) { deferred.resolve(response.data); }, function(error) { deferred.reject(error.data.message || error.data); }); return deferred.promise; }, logout: function() { var deferred = $q.defer(); $http.get('/auth/signout').then(function(response) { deferred.resolve(null); }, function(error) { deferred.reject(error.data.message || error.data); }); return deferred.promise; }, signup: function(credentials) { var deferred = $q.defer(); $http.post('/auth/signup', credentials).then(function(response) { // If successful we assign the response to the global user model deferred.resolve(response.data); }, function(error) { deferred.reject(error.data.message || error.data); }); return deferred.promise; }, resendVerifyEmail: function(_email) { var deferred = $q.defer(); $http.post('/auth/verify', {email: _email}).then(function(response) { deferred.resolve(response.data); }, function(error) { deferred.reject(error.data.message || error.data); }); return deferred.promise; }, validateVerifyToken: function(token) { //DAVID: TODO: The valid length of a token should somehow be linked to server config values //DAVID: TODO: SEMI-URGENT: Should we even be doing this? var validTokenRe = /^([A-Za-z0-9]{48})$/g; if( !validTokenRe.test(token) ) throw new Error('Error token: '+token+' is not a valid verification token'); var deferred = $q.defer(); $http.get('/auth/verify/'+token).then(function(response) { deferred.resolve(response.data); }, function(error) { deferred.reject(error.data); }); return deferred.promise; }, resetPassword: function(passwordDetails, token) { var deferred = $q.defer(); $http.post('/auth/reset/'+token, passwordDetails).then(function(response) { deferred.resolve(response); }, function(error) { deferred.reject(error.data.message || error.data); }); return deferred.promise; }, // Submit forgotten password account id askForPasswordReset: function(credentials) { var deferred = $q.defer(); $http.post('/auth/forgot', credentials).then(function(response) { // Show user success message and clear form deferred.resolve(response.data); }, function(error) { // Show user error message deferred.reject(error.data.message || error.data); }); return deferred.promise; } }; return userService; } ]); 'use strict'; // Users service used for communicating with the users REST endpoint angular.module('users').factory('Users', ['$resource', function($resource) { return $resource('users', {}, { update: { method: 'PUT' } }); } ]); 'use strict'; 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_SETTINGS: 'My Settings', CHANGE_PASSWORD: 'Change Password', TOGGLE_NAVIGATION: 'Toggle navigation' }); $translateProvider.preferredLanguage('en') .fallbackLanguage('en') .useSanitizeValueStrategy('escape'); }]); 'use strict'; 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_SETTINGS: 'Mes Paramètres', CHANGE_PASSWORD: 'Changer mon Mot de Pass', TOGGLE_NAVIGATION: 'Basculer la navigation', }); }]); 'use strict'; angular.module('core').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('de', { MENU: 'MENÜ', SIGNUP_TAB: 'Anmelden', SIGNIN_TAB: 'Anmeldung', SIGNOUT_TAB: 'Abmelden', EDIT_PROFILE: 'Profil bearbeiten', MY_SETTINGS: 'Meine Einstellungen', CHANGE_PASSWORD: 'Passwort ändern', TOGGLE_NAVIGATION: 'Navigation umschalten' }); }]); 'use strict'; angular.module('core').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('it', { MENU: 'MENÜ', SIGNUP_TAB: 'Vi Phrasal', SIGNIN_TAB: 'Accedi', SIGNOUT_TAB: 'Esci', EDIT_PROFILE: 'Modifica Profilo', MY_SETTINGS: 'Mie Impostazioni', CHANGE_PASSWORD: 'Cambia la password', TOGGLE_NAVIGATION: 'Attiva la navigazione' }); }]); 'use strict'; angular.module('core').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('es', { MENU: 'MENU', SIGNUP_TAB: 'Registrarse', SIGNIN_TAB: 'Entrar', SIGNOUT_TAB: 'Salir', EDIT_PROFILE: 'Editar Perfil', MY_SETTINGS: 'Mis configuraciones', CHANGE_PASSWORD: 'Cambiar contraseña', TOGGLE_NAVIGATION: 'Navegación de palanca' }); }]); 'use strict'; // Forms controller angular.module('forms').controller('AdminFormController', ['$rootScope', '$window', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm', '$http', '$uibModal', 'myForm', '$filter', '$translate', function($rootScope, $window, $scope, $stateParams, $state, Forms, CurrentForm, $http, $uibModal, myForm, $filter, $translate) { //Set active tab to Create $scope.activePill = 0; $scope.copied = false; $scope.onCopySuccess = function (e) { $scope.copied = true; }; $scope = $rootScope; $scope.animationsEnabled = true; $scope.myform = myForm; $rootScope.saveInProgress = false; $scope.oldForm = _.cloneDeep($scope.myform); CurrentForm.setForm($scope.myform); $scope.formURL = '/#!/forms/' + $scope.myform._id; if ($scope.myform.isLive) { if ($window.subdomainsDisabled === true) { $scope.actualFormURL = window.location.protocol + '//' + window.location.host + '/view' + $scope.formURL; } else { if (window.location.host.split('.').length < 3) { $scope.actualFormURL = window.location.protocol + '//' + $scope.myform.admin.username + '.' + window.location.host + $scope.formURL; } else { $scope.actualFormURL = window.location.protocol + '//' + $scope.myform.admin.username + '.' + window.location.host.split('.').slice(1, 3).join('.') + $scope.formURL; } } } else { $scope.actualFormURL = window.location.protocol + '//' + window.location.host + $scope.formURL; } var refreshFrame = $scope.refreshFrame = function(){ if(document.getElementById('iframe')) { document.getElementById('iframe').contentWindow.location.reload(); } }; $scope.tabData = [ { heading: $filter('translate')('CONFIGURE_TAB'), templateName: 'configure' } ]; $scope.designTabActive = false $scope.deactivateDesignTab = function(){ $scope.designTabActive = false } $scope.activateDesignTab = function(){ $scope.designTabActive = true } $scope.setForm = function(form){ $scope.myform = form; }; $rootScope.resetForm = function(){ $scope.myform = Forms.get({ formId: $stateParams.formId }); }; /* ** DeleteModal Functions */ $scope.openDeleteModal = function(){ $scope.deleteModal = $uibModal.open({ animation: $scope.animationsEnabled, templateUrl: 'formDeleteModal.html', controller: 'AdminFormController', resolve: { myForm: function(){ return $scope.myform; } } }); $scope.deleteModal.result.then(function (selectedItem) { $scope.selected = selectedItem; }); }; $scope.cancelDeleteModal = function(){ if($scope.deleteModal){ $scope.deleteModal.dismiss('cancel'); } }; // Remove existing Form $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) .then(function(response){ $state.go('listForms', {}, {reload: true}) }, function(error){ console.error(error); }); } }; $scope.updateDesign = function(updateImmediately, data, shouldDiff, refreshAfterUpdate){ $scope.update(updateImmediately, data, shouldDiff, refreshAfterUpdate, function(){ refreshFrame(); }); } // Update existing Form $scope.update = $rootScope.update = function(updateImmediately, data, shouldDiff, refreshAfterUpdate, cb){ var continueUpdate = true; if(!updateImmediately){ continueUpdate = !$rootScope.saveInProgress; } //Update form **if we are not in the middle of an update** or if **shouldUpdateNow flag is set** if(continueUpdate) { var err = null; if (!updateImmediately) { $rootScope.saveInProgress = true; } if (shouldDiff) { //Do this so we can create duplicate fields var checkForValidId = new RegExp('^[0-9a-fA-F]{24}$'); for(var i=0; i < $scope.myform.form_fields.length; i++){ var field = $scope.myform.form_fields[i]; if(!checkForValidId.exec(field._id+'')){ delete $scope.myform.form_fields[i]._id; delete $scope.myform.form_fields[i].id; } } var data = DeepDiff.diff($scope.oldForm, $scope.myform); $scope.updatePromise = $http.put('/forms/' + $scope.myform._id, {changes: data}) .then(function (response) { if (refreshAfterUpdate) { $rootScope.myform = $scope.myform = response.data; $scope.oldForm = _.cloneDeep($scope.myform); } }).catch(function (response) { err = response.data; console.error(err); }).finally(function () { if (!updateImmediately) { $rootScope.saveInProgress = false; } if ((typeof cb) === 'function') { return cb(err); } }); } else { var dataToSend = data; if(dataToSend.analytics && dataToSend.analytics.visitors){ delete dataToSend.analytics.visitors; } if(dataToSend.submissions){ delete dataToSend.submissions; } if(dataToSend.visible_form_fields){ delete dataToSend.visible_form_fields; } if(dataToSend.analytics){ delete dataToSend.analytics.visitors; delete dataToSend.analytics.fields; delete dataToSend.analytics.submissions; delete dataToSend.analytics.views; delete dataToSend.analytics.conversionRate; } delete dataToSend.created; delete dataToSend.lastModified; delete dataToSend.__v; $scope.updatePromise = $http.put('/forms/' + $scope.myform._id, {form: dataToSend}) .then(function (response) { if (refreshAfterUpdate) { $rootScope.myform = $scope.myform = response.data; } }).catch(function (response) { err = response.data; console.error(err); }).finally(function () { if (!updateImmediately) { $rootScope.saveInProgress = false; } if ((typeof cb) === 'function') { return cb(err); } }); } } }; } ]); 'use strict'; // Forms controller angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope', '$stateParams', '$state', 'GetForms', 'CurrentForm', '$http', '$uibModal', 'myForms', function($rootScope, $scope, $stateParams, $state, GetForms, CurrentForm, $http, $uibModal, myForms) { $scope = $rootScope; $scope.forms = {}; $scope.showCreateModal = false; $scope.myforms = myForms $rootScope.languageRegExp = { regExp: /[@!#$%^&*()\-+={}\[\]|\\/'";:`.,~№?<>]+/i, test: function(val) { return !this.regExp.test(val); } }; /* ** DeleteModal Functions */ $scope.openDeleteModal = function(index){ $scope.deleteModal = $uibModal.open({ animation: $scope.animationsEnabled, templateUrl: 'deleteModalListForms.html', controller: ["$uibModalInstance", "items", "$scope", function($uibModalInstance, items, $scope) { $scope.content = items; $scope.cancel = $scope.cancelDeleteModal; $scope.deleteForm = function() { $scope.$parent.removeForm(items.formIndex); }; }], resolve: { items: function() { return { currFormTitle: $scope.myforms[index].title, formIndex: index }; } } }); }; $scope.cancelDeleteModal = function(){ if($scope.deleteModal){ $scope.deleteModal.dismiss('cancel'); } }; //Modal functions $scope.openCreateModal = function(){ if(!$scope.showCreateModal){ $scope.showCreateModal = true; } }; $scope.closeCreateModal = function(){ if($scope.showCreateModal){ $scope.showCreateModal = false; } }; $scope.setForm = function (form) { $scope.myform = form; }; $scope.goToWithId = function(route, id) { $state.go(route, {'formId': id}, {reload: true}); }; $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); if(errorResponse === null){ $scope.error = errorResponse.data.message; } }); }; // Create new Form $scope.createNewForm = function(){ var form = {}; form.title = $scope.forms.createForm.title.$modelValue; form.language = $scope.forms.createForm.language.$modelValue; if($scope.forms.createForm.$valid && $scope.forms.createForm.$dirty){ $http.post('/forms', {form: form}) .success(function(data, status, headers){ // Redirect after save $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 || form_index < 0){ 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); $scope.cancelDeleteModal(); }).error(function(error){ console.error(error); }); }; } ]); 'use strict'; 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){ $scope.log = ''; $scope.languages = $rootScope.languages; $scope.resetForm = $rootScope.resetForm; $scope.update = $rootScope.update; }] }; } ]); 'use strict'; angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormFields', '$uibModal', function ($rootScope, FormFields, $uibModal) { return { templateUrl: 'modules/forms/admin/views/directiveViews/form/edit-form.client.view.html', restrict: 'E', transclude: true, scope: { myform:'=' }, controller: ["$scope", function($scope){ /* ** Initialize scope with variables */ var newField; //Setup UI-Sortable $scope.sortableOptions = { appendTo: '.dropzone', //helper: 'clone', forceHelperSize: true, forcePlaceholderSize: true, update: function(e, ui) { $scope.update(false, $scope.myform, true, false, function(err){ }); }, }; /* ** EditModal Functions */ $scope.openEditModal = function(curr_field, isEdit, field_index){ $scope.editFieldModal = $uibModal.open({ animation: true, templateUrl: 'editFieldModal.html', windowClass: 'edit-modal-window', controller: ["$uibModalInstance", "$scope", function($uibModalInstance, $scope) { $scope.field = curr_field; $scope.showLogicJump = false; $scope.isEdit = isEdit; // decides whether field options block will be shown (true for dropdown and radio fields) $scope.showAddOptions = function (field){ if($scope.field.fieldType === 'dropdown' || $scope.field.fieldType === 'checkbox' || $scope.field.fieldType === 'radio'){ return true; } else { return false; } }; $scope.validShapes = [ 'Heart', 'Star', 'thumbs-up', 'thumbs-down', 'Circle', 'Square', 'Check Circle', 'Smile Outlined', 'Hourglass', 'bell', 'Paper Plane', 'Comment', 'Trash' ]; // add new option to the field $scope.addOption = function(){ if($scope.field.fieldType === 'checkbox' || $scope.field.fieldType === 'dropdown' || $scope.field.fieldType === 'radio'){ if(!$scope.field.fieldOptions){ $scope.field.fieldOptions = []; } var lastOptionID = $scope.field.fieldOptions.length+1; // new option's id var newOption = { 'option_id' : Math.floor(100000*Math.random()), 'option_title' : 'Option '+lastOptionID, 'option_value' : 'Option ' +lastOptionID }; // put new option into fieldOptions array $scope.field.fieldOptions.push(newOption); } }; // delete particular option $scope.deleteOption = function (option){ if($scope.field.fieldType === 'checkbox' || $scope.field.fieldType === 'dropdown' || $scope.field.fieldType === 'radio'){ for(var i = 0; i < $scope.field.fieldOptions.length; i++){ if($scope.field.fieldOptions[i].option_id === option.option_id){ $scope.field.fieldOptions.splice(i, 1); break; } } } }; //Populate Name to Font-awesomeName Conversion Map $scope.select2FA = { 'Heart': 'Heart', 'Star': 'Star', 'thumbs-up': 'Thumbs Up', 'thumbs-down':'Thumbs Down', 'Circle': 'Circle', 'Square':'Square', 'Check Circle': 'Checkmark', 'Smile Outlined': 'Smile', 'Hourglass': 'Hourglass', 'bell': 'Bell', 'Paper Plane': 'Paper Plane', 'Comment': 'Chat Bubble', 'Trash': 'Trash Can' }; // decides whether field options block will be shown (true for dropdown and radio fields) $scope.showRatingOptions = function (){ if($scope.field.fieldType === 'rating'){ return true; } else { return false; } }; $scope.saveField = function(){ if($scope.isEdit){ $scope.myform.form_fields[field_index] = $scope.field; } else { $scope.myform.form_fields.push(curr_field); } $scope.$parent.update(false, $scope.$parent.myform, true, true, function(){ $uibModalInstance.close(); }); }; $scope.cancel = function(){ $uibModalInstance.close(); }; }] }); }; /* ** EditStartPageModal Functions */ $scope.openEditStartPageModal = function(){ $scope.editStartPageModal = $uibModal.open({ animation: true, templateUrl: 'editStartPageModal.html', windowClass: 'edit-modal-window', controller: ["$uibModalInstance", "$scope", function($uibModalInstance, $scope) { /* ** startPage Button Methods */ $scope.showButtons = false; $scope.lastButtonID = 0; // add new Button to the startPage $scope.addButton = function(){ var newButton = {}; newButton.bgColor = '#ddd'; newButton.color = '#ffffff'; newButton.text = 'Button'; newButton._id = Math.floor(100000*Math.random()); $scope.myform.startPage.buttons.push(newButton); }; // delete particular Button from startPage $scope.deleteButton = function(button){ var currID; for(var i = 0; i < $scope.myform.startPage.buttons.length; i++){ currID = $scope.myform.startPage.buttons[i]._id; if(currID === button._id){ $scope.myform.startPage.buttons.splice(i, 1); break; } } }; $scope.saveStartPage = function(){ $scope.$parent.update(false, $scope.$parent.myform, true, true, function(){ $uibModalInstance.close(); }); }; $scope.cancel = function(){ $uibModalInstance.close(); }; }] }); }; /* ** EditEndPageModal Functions */ $scope.openEditEndPageModal = function(){ $scope.editEndPageModal = $uibModal.open({ animation: true, templateUrl: 'editEndPageModal.html', windowClass: 'edit-modal-window', controller: ["$uibModalInstance", "$scope", function($uibModalInstance, $scope) { /* ** startPage Button Methods */ $scope.showButtons = false; $scope.lastButtonID = 0; // add new Button to the startPage $scope.addButton = function(){ var newButton = {}; newButton.bgColor = '#ddd'; newButton.color = '#ffffff'; newButton.text = 'Button'; newButton._id = Math.floor(100000*Math.random()); $scope.myform.endPage.buttons.push(newButton); }; // delete particular Button from startPage $scope.deleteButton = function(button){ var currID; for(var i = 0; i < $scope.myform.endPage.buttons.length; i++){ currID = $scope.myform.endPage.buttons[i]._id; if(currID === button._id){ $scope.myform.endPage.buttons.splice(i, 1); break; } } }; $scope.saveEndPage = function(){ $scope.$parent.update(false, $scope.$parent.myform, true, true, function(){ $uibModalInstance.close(); }); }; $scope.cancel = function(){ $uibModalInstance.close(); }; }] }); }; //Populate local scope with rootScope methods/variables $scope.update = $rootScope.update; /* ** FormFields (ui-sortable) drag-and-drop configuration */ $scope.dropzone = { handle: '.handle', containment: '.dropzoneContainer', cursor: 'grabbing' }; /* ** Field CRUD Methods */ // Add a new field $scope.addNewField = function(fieldType){ // increment lastAddedID counter $scope.addField.lastAddedID++; var fieldTitle = fieldType; for(var 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; } } newField = { title: fieldTitle, fieldType: fieldType, fieldValue: '', required: true, disabled: false, deletePreserved: false, logicJump: {} }; if(fieldType === 'rating'){ newField.ratingOptions = { steps: 5, shape: 'Heart' }; newField.fieldValue = 0; } if($scope.showAddOptions(newField)){ newField.fieldOptions = []; newField.fieldOptions.push({ 'option_id' : Math.floor(100000*Math.random()), //Generate pseudo-random option id 'option_title' : 'Option 0', 'option_value' : 'Option 0' }); } $scope.openEditModal(newField, false, $scope.myform.form_fields.length); }; // decides whether field options block will be shown (true for dropdown and radio fields) $scope.showAddOptions = function (field){ if(field.fieldType === 'dropdown' || field.fieldType === 'checkbox' || field.fieldType === 'radio'){ return true; } else { return false; } }; // decides whether field options block will be shown (true for dropdown and radio fields) $scope.showRatingOptions = function (field){ if(field.fieldType === 'rating'){ return true; } else { return false; } }; // Delete particular field on button click $scope.deleteField = function (field_index) { $scope.myform.form_fields.splice(field_index, 1); $scope.update(false, $scope.myform, false, true, null); }; $scope.duplicateField = function(field_index){ var currField = angular.copy($scope.myform.form_fields[field_index]); currField._id = 'cloned'+_.uniqueId(); currField.title += ' copy'; //Insert field at selected index $scope.myform.form_fields.push(currField); $scope.update(false, $scope.myform, false, true, null); }; //Populate AddField with all available form field types $scope.addField = {}; $scope.addField.types = FormFields.types; $scope.addField.types.forEach(function(type){ type.lastAddedID = 1; return type; }); }] }; } ]); 'use strict'; angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', '$http', 'Forms', '$stateParams', '$interval', function ($rootScope, $http, Forms, $stateParams, $interval) { return { templateUrl: 'modules/forms/admin/views/directiveViews/form/edit-submissions-form.client.view.html', restrict: 'E', scope: { user:'=', myform: '=' }, controller: ["$scope", function($scope){ $scope.table = { masterChecker: false, rows: [] }; var initController = function(){ $http({ method: 'GET', url: '/forms/'+$scope.myform._id+'/submissions' }).then(function successCallback(response) { var defaultFormFields = _.cloneDeep($scope.myform.form_fields); var submissions = response.data || []; //Iterate through form's submissions for(var i = 0; i < submissions.length; i++){ for(var x = 0; x < submissions[i].form_fields.length; x++){ if(submissions[i].form_fields[x].fieldType === 'dropdown'){ submissions[i].form_fields[x].fieldValue = submissions[i].form_fields[x].fieldValue.option_value; } //var oldValue = submissions[i].form_fields[x].fieldValue || ''; //submissions[i].form_fields[x] = _.merge(defaultFormFields, submissions[i].form_fields); //submissions[i].form_fields[x].fieldValue = oldValue; } submissions[i].selected = false; } $scope.table.rows = submissions; }); }; initController(); /* ** Analytics Functions */ $scope.AverageTimeElapsed = (function(){ var totalTime = 0; var numSubmissions = $scope.table.rows.length; for(var i=0; i<$scope.table.rows.length; i++){ totalTime += $scope.table.rows[i].timeElapsed; } if(numSubmissions === 0) { return 0; } return (totalTime/numSubmissions).toFixed(0); })(); $scope.DeviceStatistics = (function(){ var newStatItem = function(){ return { visits: 0, responses: 0, completion: 0, average_time: 0, total_time: 0 }; }; var stats = { desktop: newStatItem(), tablet: newStatItem(), phone: newStatItem(), other: newStatItem() }; if($scope.myform.analytics && $scope.myform.analytics.visitors) { var visitors = $scope.myform.analytics.visitors; for (var i = 0; i < visitors.length; i++) { var visitor = visitors[i]; var deviceType = visitor.deviceType; stats[deviceType].visits++; if (visitor.isSubmitted) { stats[deviceType].total_time = stats[deviceType].total_time + visitor.timeElapsed; stats[deviceType].responses++; } if(stats[deviceType].visits) { stats[deviceType].completion = 100*(stats[deviceType].responses / stats[deviceType].visits).toFixed(2); } if(stats[deviceType].responses){ stats[deviceType].average_time = (stats[deviceType].total_time / stats[deviceType].responses).toFixed(0); } } } return stats; })(); var updateFields = $interval(initController, 1000000); $scope.$on('$destroy', function() { if (updateFields) { $interval.cancel($scope.updateFields); } }); /* ** Table Functions */ $scope.isAtLeastOneChecked = function(){ for(var i=0; i<$scope.table.rows.length; i++){ if($scope.table.rows[i].selected) return true; } return false; }; $scope.toggleAllCheckers = function(){ for(var i=0; i<$scope.table.rows.length; i++){ $scope.table.rows[i].selected = $scope.table.masterChecker; } }; $scope.toggleObjSelection = function($event) { $event.stopPropagation(); }; $scope.rowClicked = function(row_index) { $scope.table.rows[row_index].selected = !$scope.table.rows[row_index].selected; }; /* * Form Submission Methods */ //Delete selected submissions of Form $scope.deleteSelectedSubmissions = function(){ var delete_ids = _.chain($scope.table.rows).filter(function(row){ return !!row.selected; }).pluck('_id').value(); $http({ url: '/forms/'+$scope.myform._id+'/submissions', method: 'DELETE', data: {deleted_submissions: delete_ids}, headers: {'Content-Type': 'application/json;charset=utf-8'} }).success(function(data, status){ //Remove deleted ids from table var tmpArray = []; for(var i=0; i<$scope.table.rows.length; i++){ if(!$scope.table.rows[i].selected){ tmpArray.push($scope.table.rows[i]); } } $scope.table.rows = tmpArray; }) .error(function(err){ console.error(err); }); }; //Export selected submissions of Form $scope.exportSubmissions = function(type){ angular.element('#table-submission-data').tableExport({type: type, escape:false, ignoreColumn: [0]}); }; }] }; } ]); 'use strict'; //TODO: DAVID: URGENT: Make this a $resource that fetches valid field types from server angular.module('forms').service('FormFields', [ '$rootScope', '$translate', '$window', function($rootScope, $translate, $window) { $translate.use($window.user.language); console.log($translate.instant('SHORT_TEXT')); this.types = [ { name : 'textfield', value : $translate.instant('SHORT_TEXT'), }, { name : 'email', value : $translate.instant('EMAIL'), }, { name : 'radio', value : $translate.instant('MULTIPLE_CHOICE'), }, { name : 'dropdown', value : $translate.instant('DROPDOWN'), }, { name : 'date', value : $translate.instant('DATE'), }, { name : 'textarea', value : $translate.instant('PARAGRAPH'), }, { name : 'yes_no', value : $translate.instant('YES_NO'), }, { name : 'legal', value : $translate.instant('LEGAL'), }, // { // name : 'sig', // value : $translate.instant('SIGNATURE'), // }, // { // name : 'file', // value : $translate.instant('FILE_UPLOAD'), // }, { name : 'rating', value : $translate.instant('RATING'), }, { name : 'link', value : $translate.instant('LINK'), }, { name : 'number', value : $translate.instant('NUMBERS'), }, // { // name : 'scale', // value : $translate.instant('OPINION SCALE'), // }, // { // name : 'stripe', // value : $translate.instant('PAYMENT'), // }, { name : 'statement', value : $translate.instant('STATEMENT') } ]; } ]); 'use strict'; //Submissions service used for communicating with the forms REST endpoints angular.module('forms').factory('Submissions', ['$resource', function($resource) { return $resource('forms/:formID/submissions/:submissionId', { submissionId: '@_id', formId: '@_id' }, { 'query' : { method: 'GET', isArray: true, }, 'update': { method: 'PUT' }, 'save': { method: 'POST' } }); } ]); 'use strict'; angular.module('users').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('en', { ACCESS_DENIED_TEXT: 'You need to be logged in to access this page', USERNAME_OR_EMAIL_LABEL: 'Username or Email', 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_ACCOUNT_LINK: 'Don\'t have an account? Sign up here', SIGN_IN_ACCOUNT_LINK: 'Already have an account? Sign in here', SIGNUP_HEADER_TEXT: 'Sign up', SIGNIN_HEADER_TEXT: 'Sign in', SIGNUP_ERROR_TEXT: 'Couldn\'t complete registration due to errors', ENTER_ACCOUNT_EMAIL: 'Enter your account email.', RESEND_VERIFICATION_EMAIL: 'Resend Verification Email', SAVE_CHANGES: 'Save Changes', CANCEL_BTN: 'Cancel', EDIT_PROFILE: 'Edit your profile', UPDATE_PROFILE_BTN: 'Update Profile', PROFILE_SAVE_SUCCESS: 'Profile saved successfully', PROFILE_SAVE_ERROR: 'Could\'t Save Your Profile.', CONNECTED_SOCIAL_ACCOUNTS: 'Connected social accounts', CONNECT_OTHER_SOCIAL_ACCOUNTS: 'Connect other social accounts', 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: 'Verification Email has been Sent', VERIFICATION_EMAIL_SENT_TO: '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', CONTINUE: 'Continue', 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 link is invalid', PASSWORD_RESET_SUCCESS: 'Password successfully reset', PASSWORD_CHANGE_SUCCESS: 'Password successfully changed', RESET_PASSWORD: 'Reset your password', CHANGE_PASSWORD: 'Change your password', CONTINUE_TO_LOGIN: 'Continue to login page', VERIFY_SUCCESS: 'Account successfully activated', VERIFY_ERROR: 'Verification link is invalid or has expired', ERROR: 'Error' }); $translateProvider.preferredLanguage('en') .fallbackLanguage('en') .useSanitizeValueStrategy('escape'); }]); 'use strict'; angular.module('users').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('fr', { 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: 'Ce lien de réinitialisation de mot de passe a déjà expiré', 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é', ERROR: 'Erreur' }); }]); 'use strict'; angular.module('users').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('de', { ACCESS_DENIED_TEXT: 'Sie müssen eingeloggt sein, um auf diese Seite zugreifen zu können', USERNAME_OR_EMAIL_LABEL: 'Benutzername oder E-Mail', USERNAME_LABEL: 'Benutzername', PASSWORD_LABEL: 'Passwort', CURRENT_PASSWORD_LABEL: 'Aktuelles Passwort', NEW_PASSWORD_LABEL: 'Neues Passwort', VERIFY_PASSWORD_LABEL: 'Passwort bestätigen', UPDATE_PASSWORD_LABEL: 'Passwort aktualisieren', FIRST_NAME_LABEL: 'Vorname', LAST_NAME_LABEL: 'Nachname', LANGUAGE_LABEL: 'Sprache', EMAIL_LABEL: 'Email', SIGNUP_ACCOUNT_LINK: 'Haben Sie kein Konto? Hier registrieren', SIGN_IN_ACCOUNT_LINK: 'Haben Sie bereits ein Konto? Hier anmelden', SIGNUP_HEADER_TEXT: 'Registrieren', SIGNIN_HEADER_TEXT: 'Anmelden', SIGNUP_ERROR_TEXT: 'Konnte die Registrierung aufgrund von Fehlern nicht abschließen', ENTER_ACCOUNT_EMAIL: 'Geben Sie Ihre Konto-E-Mail ein.', RESEND_VERIFICATION_EMAIL: 'Bestätigungs-E-Mail erneut senden', SAVE_CHANGES: 'Änderungen speichern', CANCEL_BTN: 'Abbrechen', EDIT_PROFILE: 'Bearbeiten Sie Ihr Profil', UPDATE_PROFILE_BTN: 'Profil aktualisieren', PROFILE_SAVE_SUCCESS: 'Profil wurde erfolgreich gespeichert', PROFILE_SAVE_ERROR: 'Könnte Ihr Profil nicht speichern.', CONNECTED_SOCIAL_ACCOUNTS: 'Verbundene Sozialkonten', CONNECT_OTHER_SOCIAL_ACCOUNTS: 'Andere soziale Konten verbinden', FORGOT_PASSWORD_LINK: 'Passwort vergessen?', REVERIFY_ACCOUNT_LINK: 'Bestätige deine Bestätigungs-E-Mail erneut', SIGNIN_BTN: "Anmelden", SIGNUP_BTN: 'Registrieren', SAVE_PASSWORD_BTN: 'Passwort speichern', SUCCESS_HEADER: 'Anmeldung erfolgreich', SUCCESS_TEXT: 'Sie haben ein Konto erfolgreich bei TellForm registriert.', VERIFICATION_EMAIL_SENT: 'Bestätigungs-E-Mail wurde gesendet', VERIFICATION_EMAIL_SENT_TO: 'Es wurde eine Bestätigungs-E-Mail gesendet.', NOT_ACTIVATED_YET: 'Dein Account ist noch nicht aktiviert', BEFORE_YOU_CONTINUE: 'Bevor Sie fortfahren, überprüfen Sie bitte Ihre E-Mail-Adresse auf Überprüfung. Wenn Sie nicht innerhalb von 24 Stunden erhalten Sie uns eine Zeile bei ', CHECK_YOUR_EMAIL: 'Überprüfe deine E-Mail und klicke auf den Aktivierungslink, um deinen Account zu aktivieren. Wenn Sie irgendwelche Fragen haben, lassen Sie uns eine Zeile bei ', WEITER: 'Weiter', PASSWORD_RESTORE_HEADER: 'Wiederherstellen Ihres Passworts', ENTER_YOUR_EMAIL: 'Geben Sie Ihre E-Mail-Adresse ein.', SUBMIT_BTN: 'Senden', ASK_FOR_NEW_PASSWORD: 'Neues Passwort zurücksetzen', PASSWORD_RESET_INVALID: 'Dieser Link zum Zurücksetzen des Passworts ist bereits abgelaufen', PASSWORD_RESET_SUCCESS: 'Passport erfolgreich zurückgesetzt', PASSWORD_CHANGE_SUCCESS: 'Pass wurde erfolgreich geändert', RESET_PASSWORD: 'Passwort zurücksetzen', CHANGE_PASSWORD: 'Ändern Sie Ihr Passwort', CONTINUE_TO_LOGIN: 'Weiter zur Anmeldeseite', VERIFY_SUCCESS: 'Konto erfolgreich aktiviert', VERIFY_ERROR: 'Überprüfungslink ist ungültig oder abgelaufen', ERROR: 'Fehler' }); }]); 'use strict'; angular.module('users').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('it', { ACCESS_DENIED_TEXT: 'Devi aver effettuato l\'accesso per accedere a questa pagina', USERNAME_OR_EMAIL_LABEL: 'Nome utente o posta elettronica', USERNAME_LABEL: 'Nome utente', PASSWORD_LABEL: 'Password', CURRENT_PASSWORD_LABEL: 'Current Password', NEW_PASSWORD_LABEL: 'Nuova password', VERIFY_PASSWORD_LABEL: 'Verifica password', UPDATE_PASSWORD_LABEL: 'Aggiorna password', FIRST_NAME_LABEL: 'Nome', LAST_NAME_LABEL: 'Cognome', LANGUAGE_LABEL: 'Lingua', EMAIL_LABEL: 'Email', SIGNUP_ACCOUNT_LINK: 'Non hai un account? Iscriviti qui ', SIGN_IN_ACCOUNT_LINK: 'Hai già un account? Accedi qui ', SIGNUP_HEADER_TEXT: 'Iscriviti', SIGNIN_HEADER_TEXT: 'Accedi', SIGNUP_ERROR_TEXT: 'Impossibile completare la registrazione a causa di errori', ENTER_ACCOUNT_EMAIL: "Inserisci l'email del tuo account.", RESEND_VERIFICATION_EMAIL: 'Ripeti l\'email di verifica', SAVE_CHANGES: 'Salva modifiche', CANCEL_BTN: 'Annulla', EDIT_PROFILE: 'Modifica il tuo profilo', UPDATE_PROFILE_BTN: 'Aggiorna profilo', PROFILE_SAVE_SUCCESS: 'Profilo salvato con successo', PROFILE_SAVE_ERROR: 'Impossibile salvare il tuo profilo.', CONNECTED_SOCIAL_ACCOUNTS: 'Conti sociali connessi', CONNECT_OTHER_SOCIAL_ACCOUNTS: 'Connetti altri account sociali', FORGOT_PASSWORD_LINK: 'Hai dimenticato la password?', REVERIFY_ACCOUNT_LINK: 'Ripeti la tua email di verifica', SIGNIN_BTN: 'Accedi', SIGNUP_BTN: 'Iscriviti', SAVE_PASSWORD_BTN: 'Salva password', SUCCESS_HEADER: 'Registra il successo', SUCCESS_TEXT: 'Hai registrato un account con TellForm.', VERIFICATION_EMAIL_SENT: 'L\'email di verifica è stata inviata', VERIFICATION_EMAIL_SENT_TO: 'E\' stata inviata un\'email di verifica a ', NOT_ACTIVATED_YET: 'Ma il tuo account non è ancora attivato', BEFORE_YOU_CONTINUE: 'Prima di continuare, assicurati di controllare la tua email per la nostra verifica. Se non lo ricevi entro 24 ore ci cali una linea a ', CHECK_YOUR_EMAIL: 'Controlla la tua email e fai clic sul link di attivazione per attivare il tuo account. Se hai domande, fai una linea a ', CONTINUA: 'Continua', PASSWORD_RESTORE_HEADER: 'Ripristina password', ENTER_YOUR_EMAIL: 'Inserisci l\'email del tuo account', SUBMIT_BTN: 'Invia', ASK_FOR_NEW_PASSWORD: 'Richiedi nuova password reimpostata', PASSWORD_RESET_INVALID: 'Questo collegamento per la reimpostazione della password è già scaduto', PASSWORD_RESET_SUCCESS: 'Passaporto resettato con successo', PASSWORD_CHANGE_SUCCESS: 'Passaporto modificato con successo', RESET_PASSWORD: 'Ripristina la tua password', CHANGE_PASSWORD: 'Modifica password', CONTINUE_TO_LOGIN: 'Continua alla pagina di login', VERIFY_SUCCESS: 'Account attivato correttamente', VERIFY_ERROR: 'Il collegamento di verifica non è valido o è scaduto', ERROR: 'Errore' }); }]); 'use strict'; angular.module('users').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('es', { ACCESS_DENIED_TEXT: 'Tenés que estar logueado para acceder a esta página', USERNAME_OR_EMAIL_LABEL: 'Usuario o Email', USERNAME_LABEL: 'Usuario', PASSWORD_LABEL: 'Contraseña', CURRENT_PASSWORD_LABEL: 'Contraseña actual', NEW_PASSWORD_LABEL: 'Nueva contraseña', VERIFY_PASSWORD_LABEL: 'Verificar contraseña', UPDATE_PASSWORD_LABEL: 'Actualizar contraseña', FIRST_NAME_LABEL: 'Nombre', LAST_NAME_LABEL: 'Apellido', LANGUAGE_LABEL: 'Idioma', EMAIL_LABEL: 'Email', SIGNUP_ACCOUNT_LINK: '¿No tenés cuenta? Resgistrate acá', SIGN_IN_ACCOUNT_LINK: '¿Ya tenés cuenta? Entra acá', SIGNUP_HEADER_TEXT: 'Registrar', SIGNIN_HEADER_TEXT: 'Entrar', SIGNUP_ERROR_TEXT: 'No se pudo terminar la registración por errores', ENTER_ACCOUNT_EMAIL: 'Ingresá tu correo electrónico.', RESEND_VERIFICATION_EMAIL: 'Reenviar email de verificación', SAVE_CHANGES: 'Grabar cambios', CANCEL_BTN: 'Cancelar', EDIT_PROFILE: 'Editar perfil', UPDATE_PROFILE_BTN: 'Actualizar perfil', PROFILE_SAVE_SUCCESS: 'Perfil actualizado satisfactoriamente', PROFILE_SAVE_ERROR: 'No se pudo grabar el perfil.', CONNECTED_SOCIAL_ACCOUNTS: 'Redes sociales conectadas', CONNECT_OTHER_SOCIAL_ACCOUNTS: 'Conectar otras redes sociales', FORGOT_PASSWORD_LINK: '¿Olvidaste la contraseña?', REVERIFY_ACCOUNT_LINK: 'Reenviar email de verificación', SIGNIN_BTN: 'Entrar', SIGNUP_BTN: 'Registrarse', SAVE_PASSWORD_BTN: 'Grabar contraseña', SUCCESS_HEADER: 'Ingresaste exitosamente', SUCCESS_TEXT: 'Registraste exitosamente una cuenta en TellForm.', VERIFICATION_EMAIL_SENT: 'El email de verificación fue enviado exitosamente', VERIFICATION_EMAIL_SENT_TO: 'Un email de verificación fue enviado a', NOT_ACTIVATED_YET: 'Tu cuenta aún no está activa', BEFORE_YOU_CONTINUE: 'Antes de continuar asegurate de leer el email de verificación que te enviamos. Si no lo recibís en 24hs escribinos a ', CHECK_YOUR_EMAIL: 'Leé el email y hacé click en el link de activación para activar la cuenta. Si tenés alguna pregunta escribinos a ', CONTINUE: 'Continuar', PASSWORD_RESTORE_HEADER: 'Restaurar la contraseña', ENTER_YOUR_EMAIL: 'Ingresá el email de tu cuenta.', SUBMIT_BTN: 'Enviar', ASK_FOR_NEW_PASSWORD: 'Pedir reseteo de contraseña', PASSWORD_RESET_INVALID: 'Este enlace de restablecimiento de contraseña ya ha caducado', PASSWORD_RESET_SUCCESS: 'Contraseña exitosamente reseteada', PASSWORD_CHANGE_SUCCESS: 'Contraseña exitosamente cambiada', RESET_PASSWORD: 'Resetear contraseña', CHANGE_PASSWORD: 'Cambiar contraseña', CONTINUE_TO_LOGIN: 'Ir a la página de ingreso', VERIFY_SUCCESS: 'Cuenta activada exitosamente', VERIFY_ERROR: 'El link de verificación es inválido o inexistente', ERROR: 'Error' }); }]); 'use strict'; angular.module('forms').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('en', { //Configure Form Tab View 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', DISPLAY_START_PAGE: 'Display Start Page?', DISPLAY_END_PAGE: 'Display Custom End Page?', //List Forms View CREATE_A_NEW_FORM: 'Create a new form', CREATE_FORM: 'Create form', CREATED_ON: 'Created on', MY_FORMS: 'My forms', NAME: 'Name', LANGUAGE: 'Language', FORM_PAUSED: 'Form paused', //Edit Field Modal EDIT_FIELD: 'Edit this Field', SAVE_FIELD: 'Save', ON: 'ON', OFF: 'OFF', REQUIRED_FIELD: 'Required', LOGIC_JUMP: 'Logic Jump', SHOW_BUTTONS: 'Additional Buttons', SAVE_START_PAGE: 'Save', //Admin Form View 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 and remove all associated form submissions.', 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', COPY: 'Copy', COPY_AND_PASTE: 'Copy and Paste this to add your TellForm to your website', CHANGE_WIDTH_AND_HEIGHT: 'Change the width and height values to suit you best', POWERED_BY: 'Powered by', TELLFORM_URL: 'Your TellForm is permanently at this URL', //Edit Form View DISABLED: 'Disabled', YES: 'YES', NO: 'NO', ADD_LOGIC_JUMP: 'Add Logic Jump', ADD_FIELD_LG: 'Click to Add New Field', ADD_FIELD_MD: 'Add New Field', ADD_FIELD_SM: 'Add Field', EDIT_START_PAGE: 'Edit Start Page', EDIT_END_PAGE: 'Edit End Page', WELCOME_SCREEN: 'Start Page', END_SCREEN: 'End Page', INTRO_TITLE: 'Title', INTRO_PARAGRAPH: 'Paragraph', INTRO_BTN: 'Start Button', TITLE: 'Title', PARAGRAPH: 'Paragraph', BTN_TEXT: 'Go Back Button', BUTTONS: 'Buttons', BUTTON_TEXT: 'Text', BUTTON_LINK: 'Link', ADD_BUTTON: 'Add Button', PREVIEW_FIELD: 'Preview Question', QUESTION_TITLE: 'Title', QUESTION_DESCRIPTION: 'Description', OPTIONS: 'Options', ADD_OPTION: 'Add Option', NUM_OF_STEPS: 'Number of Steps', CLICK_FIELDS_FOOTER: 'Click on fields to add them here', SHAPE: 'Shape', IF_THIS_FIELD: 'If this field', IS_EQUAL_TO: 'is equal to', IS_NOT_EQUAL_TO: 'is not equal to', IS_GREATER_THAN: 'is greater than', IS_GREATER_OR_EQUAL_THAN: 'is greater or equal than', IS_SMALLER_THAN: 'is smaller than', IS_SMALLER_OR_EQUAL_THAN: 'is smaller or equal than', CONTAINS: 'contains', DOES_NOT_CONTAINS: 'does not contain', ENDS_WITH: 'ends with', DOES_NOT_END_WITH: 'does not end with', STARTS_WITH: 'starts with', DOES_NOT_START_WITH: 'does not start with', THEN_JUMP_TO: 'then jump to', //Edit Submissions View 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', //Design View 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', //Share View EMBED_YOUR_FORM: 'Embed your form', SHARE_YOUR_FORM: 'Share your form', //Admin Tabs CREATE_TAB: 'Create', DESIGN_TAB: 'Design', CONFIGURE_TAB: 'Configure', ANALYZE_TAB: 'Analyze', SHARE_TAB: 'Share', //Field Types SHORT_TEXT: 'Short Text', EMAIL: 'Email', MULTIPLE_CHOICE: 'Multiple Choice', DROPDOWN: 'Dropdown', DATE: 'Date', PARAGRAPH_T: 'Paragraph', YES_NO: 'Yes/No', LEGAL: 'Legal', RATING: 'Rating', NUMBERS: 'Numbers', SIGNATURE: 'Signature', FILE_UPLOAD: 'File upload', OPTION_SCALE: 'Option Scale', PAYMENT: 'Payment', STATEMENT: 'Statement', LINK: 'Link', //Form Preview FORM_SUCCESS: 'Form entry successfully submitted!', REVIEW: 'Review', BACK_TO_FORM: 'Go back to Form', EDIT_FORM: 'Edit 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', NEWLINE: 'press SHIFT+ENTER to create a newline', CONTINUE: 'Continue', LEGAL_ACCEPT: 'I accept', LEGAL_NO_ACCEPT: 'I don’t accept', SUBMIT: 'Submit', UPLOAD_FILE: 'Upload your File' }); }]); 'use strict'; angular.module('forms').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('fr', { // Configurer la vue de l'onglet Formulaire ADVANCED_SETTINGS: 'Paramètres avancés', FORM_NAME: "Nom du formulaire", FORM_STATUS: 'Statut du formulaire', PUBLIC: 'Public', PRIVATE: "Privé", GA_TRACKING_CODE: "Code de suivi Google Analytics", DISPLAY_FOOTER: "Afficher le pied de formulaire?", SAVE_CHANGES: 'Enregistrer les modifications', CANCEL: 'Annuler', DISPLAY_START_PAGE: "Afficher la page de démarrage?", DISPLAY_END_PAGE: "Afficher la page de fin personnalisée?", // Afficher les formulaires CREATE_A_NEW_FORM: "Créer un nouveau formulaire", CREATE_FORM: "Créer un formulaire", CREATED_ON: 'Créé le', MY_FORMS: 'Mes formes', NAME: "Nom", LANGUE: 'Langue', FORM_PAUSED: 'Formulaire en pause', // Modifier le modal de champ EDIT_FIELD: "Modifier ce champ", SAVE_FIELD: 'Enregistrer', ON: 'ON', OFF: "OFF", REQUIRED_FIELD: "Obligatoire", LOGIC_JUMP: 'Saut logique', SHOW_BUTTONS: 'Boutons supplémentaires', SAVE_START_PAGE: "Enregistrer", // Affichage du formulaire d'administration ARE_YOU_SURE: 'Es-tu ABSOLUMENT sûr?', READ_WARNING: "De mauvaises choses inattendues se produiront si vous ne lisez pas ceci!", DELETE_WARNING1: 'Cette action NE PEUT PAS être annulée. Cela supprimera définitivement le "', DELETE_WARNING2: '" forme et supprime toutes les soumissions de formulaire associées. ', DELETE_CONFIRM: "Veuillez taper le nom du formulaire pour confirmer.", I_UNDERSTAND: 'Je comprends les conséquences, efface ce formulaire.', DELETE_FORM_SM: 'Supprimer', DELETE_FORM_MD: "Supprimer le formulaire", DELETE: "Supprimer", FORM: 'Formulaire', VIEW: "Afficher", LIVE: "Live", PREVIEW: 'Aperçu', COPY: "Copier", COPY_AND_PASTE: "Copiez et collez ceci pour ajouter votre TellForm à votre site Web", CHANGE_WIDTH_AND_HEIGHT: "Changez les valeurs de largeur et de hauteur pour mieux vous convenir", POWERED_BY: "Alimenté par", TELLFORM_URL: "Votre TellForm est en permanence sur cette URL", // Modifier la vue de formulaire DISABLED: "Désactivé", OUI: 'OUI', NO: 'NON', ADD_LOGIC_JUMP: 'Ajouter un saut de logique', ADD_FIELD_LG: "Cliquez pour ajouter un nouveau champ", ADD_FIELD_MD: "Ajouter un nouveau champ", ADD_FIELD_SM: "Ajouter un champ", EDIT_START_PAGE: "Modifier la page de démarrage", EDIT_END_PAGE: "Modifier la page de fin", WELCOME_SCREEN: 'Page de démarrage', END_SCREEN: 'Fin de page', INTRO_TITLE: "Titre", INTRO_PARAGRAPH: 'Paragraphe', INTRO_BTN: 'Bouton de démarrage', TITLE: "Titre", PARAGRAPHE: 'Paragraphe', BTN_TEXT: "Bouton Retour", BOUTONS: 'Boutons', BUTTON_TEXT: "Texte", BUTTON_LINK: "Lien", ADD_BUTTON: 'Ajouter un bouton', PREVIEW_FIELD: 'Question d\'aperçu', QUESTION_TITLE: "Titre", QUESTION_DESCRIPTION: 'Description', OPTIONS: 'Options', ADD_OPTION: 'Ajouter une option', NUM_OF_STEPS: "Nombre d'étapes", CLICK_FIELDS_FOOTER: 'Cliquez sur les champs pour les ajouter ici', SHAPE: 'Forme', IF_THIS_FIELD: "Si ce champ", IS_EQUAL_TO: 'est égal à', IS_NOT_EQUAL_TO: 'n\'est pas égal à', IS_GREATER_THAN: 'est supérieur à', IS_GREATER_OR_EQUAL_THAN: 'est supérieur ou égal à', IS_SMALLER_THAN: 'est plus petit que', IS_SMALLER_OR_EQUAL_THAN: 'est plus petit ou égal à', CONTAINS: 'contient', DOES_NOT_CONTAINS: 'ne contient pas', ENDS_WITH: "se termine par", DOES_NOT_END_WITH: "ne finit pas avec", STARTS_WITH: 'commence par', DOES_NOT_START_WITH: "ne commence pas par", THEN_JUMP_TO: 'alors saute à', // Modifier la vue des soumissions TOTAL_VIEWS: 'total des visites uniques', RESPONSES: "réponses", COMPLETION_RATE: "taux d'achèvement", AVERAGE_TIME_TO_COMPLETE: 'moy. le temps d\'achèvement', DESKTOP_AND_LAPTOP: 'Desktops', TABLETS: 'Tablettes', PHONES: 'Téléphones', OTHER: 'Autre', UNIQUE_VISITS: 'Visites uniques', FIELD_TITLE: 'Titre du champ', FIELD_VIEWS: 'Vues de champ', FIELD_DROPOFF: "Achèvement du champ", FIELD_RESPONSES: 'Réponses sur le terrain', DELETE_SELECTED: 'Supprimer la sélection', EXPORT_TO_EXCEL: 'Exporter vers Excel', EXPORT_TO_CSV: 'Export vers CSV', EXPORT_TO_JSON: "Exporter vers JSON", PERCENTAGE_COMPLETE: 'Pourcentage terminé', TIME_ELAPSED: 'Temps écoulé', DEVICE: "Dispositif", LOCATION: "Emplacement", IP_ADDRESS: 'Adresse IP', DATE_SUBMITTED: 'Date de soumission', // Vue de conception BACKGROUND_COLOR: "Couleur d'arrière-plan", DESIGN_HEADER: "Changez l'apparence de votre formulaire", QUESTION_TEXT_COLOR: "Couleur du texte de la question", ANSWER_TEXT_COLOR: "Couleur du texte de la réponse", BTN_BACKGROUND_COLOR: "Couleur d'arrière-plan du bouton", BTN_TEXT_COLOR: "Couleur du texte du bouton", // Vue de partage EMBED_YOUR_FORM: "Intégrez votre formulaire", SHARE_YOUR_FORM: "Partager votre formulaire", // Onglets d'administration CREATE_TAB: "Créer", DESIGN_TAB: 'Design', CONFIGURE_TAB: 'Configurer', ANALYZE_TAB: "Analyser", SHARE_TAB: "Partager", // Types de champs SHORT_TEXT: "Texte court", EMAIL: "E-mail", MULTIPLE_CHOICE: 'Choix multiple', DROPDOWN: 'Menu Déroulant', DATE: 'Date', PARAGRAPH_T: "Paragraphe", OUI_NON: 'Oui / Non', LEGAL: 'Légal', RATING: "Évaluation", NUMBERS: "Chiffres", SIGNATURE: 'Signature', FILE_UPLOAD: 'Téléchargement de fichier', OPTION_SCALE: 'Option Scale', PAYMENT: 'Paiement', STATEMENT: 'Déclaration', LINK: "Lien", // Aperçu du formulaire FORM_SUCCESS: 'Entrée de formulaire soumise avec succès!', REVIEW: 'Réviser', BACK_TO_FORM: "Revenir au formulaire", EDIT_FORM: "Modifier ce TellForm", ADVANCEMENT: '{{done}} sur {{total}} a répondu', CONTINUE_FORM: "Continuer à se former", REQUIRED: 'requis', COMPLETING_NEEDED: '{{answers_not_completed}} réponse (s) doivent être complétées', OPTIONAL: 'optionnel', ERROR_EMAIL_INVALID: "Veuillez entrer une adresse email valide", ERROR_NOT_A_NUMBER: "Veuillez entrer uniquement des numéros valides", ERROR_URL_INVALID: "S'il vous plaît une adresse valide", OK: 'OK', ENTER: 'appuyez sur ENTRER', NEWLINE: 'appuyez sur MAJ + ENTRÉE pour créer une nouvelle ligne', CONTINUE: "Continuer", LEGAL_ACCEPT: 'J\'accepte', LEGAL_NO_ACCEPT: "Je n'accepte pas", SUBMIT: "Soumettre", UPLOAD_FILE: "Télécharger votre fichier" }); }]); 'use strict'; angular.module('forms').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('de', { // Konfigurieren der Formularregisterkarte ADVANCED_SETTINGS: 'Erweiterte Einstellungen', FORM_NAME: 'Formularname', FORM_STATUS: 'Formularstatus', PUBLIC: 'Öffentlich', PRIVATE: 'Privat', GA_TRACKING_CODE: 'Google Analytics Tracking-Code', DISPLAY_FOOTER: 'Formularfußzeile anzeigen?', SAVE_CHANGES: 'Änderungen speichern', CANCEL: 'Abbrechen', DISPLAY_START_PAGE: 'Startseite anzeigen?', DISPLAY_END_PAGE: 'Benutzerdefinierte Endseite anzeigen?', // Listenformularansicht CREATE_A_NEW_FORM: 'Erstelle ein neues Formular', CREATE_FORM: 'Formular erstellen', CREATED_ON: 'Erstellt am', MY_FORMS: 'Meine Formulare', NAME: 'Name', SPRACHE: 'Sprache', FORM_PAUSED: 'Formular pausiert', // Feld Modal bearbeiten EDIT_FIELD: 'Dieses Feld bearbeiten', SAVE_FIELD: 'Speichern', ON: 'ON', AUS: 'AUS', REQUIRED_FIELD: 'Erforderlich', LOGIC_JUMP: 'Logischer Sprung', SHOW_BUTTONS: 'Zusätzliche Schaltflächen', SAVE_START_PAGE: 'Speichern', // Admin-Formularansicht ARE_YOU_SURE: "Bist du ABSOLUT sicher?", READ_WARNING: 'Unerwartete schlimme Dinge werden passieren, wenn Sie das nicht lesen!', DELETE_WARNING1: 'Diese Aktion kann NICHT rückgängig gemacht werden. Dies wird dauerhaft die "', DELETE_WARNING2: '"Formular und entferne alle verknüpften Formulareinreichungen.', DELETE_CONFIRM: 'Bitte geben Sie den Namen des zu bestätigenden Formulars ein.', I_UNDERSTAND: "Ich verstehe die Konsequenzen, lösche dieses Formular.", DELETE_FORM_SM: 'Löschen', DELETE_FORM_MD: 'Formular löschen', DELETE: 'Löschen', FORM: 'Formular', VIEW: 'Ansicht', LIVE: 'Leben', PREVIEW: 'Vorschau', COPY: 'Kopieren', COPY_AND_PASTE: 'Kopieren und einfügen, um Ihre TellForm auf Ihrer Website hinzuzufügen', CHANGE_WIDTH_AND_HEIGHT: 'Ändern Sie die Werte für Breite und Höhe, um Ihnen am besten zu entsprechen', POWERED_BY: 'Unterstützt von', TELLFORM_URL: "Ihr TellForm ist dauerhaft unter dieser URL", // Formularansicht bearbeiten DISABLED: 'Deaktiviert', JA: 'JA', NO: 'NEIN', ADD_LOGIC_JUMP: 'Logic Jump hinzufügen', ADD_FIELD_LG: 'Klicken Sie auf Neues Feld hinzufügen', ADD_FIELD_MD: 'Neues Feld hinzufügen', ADD_FIELD_SM: 'Feld hinzufügen', EDIT_START_PAGE: 'Startseite bearbeiten', EDIT_END_PAGE: 'Endseite bearbeiten', WELCOME_SCREEN: 'Startseite', END_SCREEN: 'Ende Seite', INTRO_TITLE: 'Titel', INTRO_PARAGRAPH: "Absatz", INTRO_BTN: 'Start Knopf', TITLE: "Titel", PARAGRAPH: "Absatz", BTN_TEXT: 'Zurück Button', TASTEN: 'Knöpfe', BUTTON_TEXT: 'Text', BUTTON_LINK: 'Link', ADD_BUTTON: 'Schaltfläche hinzufügen', PREVIEW_FIELD: 'Vorschaufrage', QUESTION_TITLE: 'Titel', QUESTION_DESCRIPTION: 'Beschreibung', OPTIONS: 'Optionen', ADD_OPTION: 'Option hinzufügen', NUM_OF_STEPS: 'Anzahl der Schritte', CLICK_FIELDS_FOOTER: 'Klicken Sie auf Felder, um sie hier hinzuzufügen', FORM: 'Formular', IF_THIS_FIELD: 'Wenn dieses Feld', IS_EQUAL_TO: 'ist gleich', IS_NOT_EQUAL_TO: 'ist nicht gleich', IS_GREATER_THAN: 'ist größer als', IS_GREATER_OR_EQUAL_THAN: 'ist größer oder gleich', IS_SMALLER_THAN: 'ist kleiner als', IS_SMALLER_OR_EQUAL_THAN: 'ist kleiner oder gleich', CONTAINS: 'enthält', DOES_NOT_CONTAINS: 'enthält nicht', ENDS_WITH: 'endet mit', DOES_NOT_END_WITH: 'endet nicht mit', STARTS_WITH: 'beginnt mit', DOES_NOT_START_WITH: 'beginnt nicht mit', THEN_JUMP_TO: 'Springe dann zu', // Bearbeiten der Einreichungsansicht TOTAL_VIEWS: 'Gesamtzahl eindeutiger Besuche', RESPONSES: 'Antworten', COMPLETION_RATE: 'Abschlussrate', AVERAGE_TIME_TO_COMPLETE: 'avg. Fertigstellungszeit', DESKTOP_AND_LAPTOP: 'Desktops', TABLETS: "Tabletten", PHONES: 'Telefone', OTHER: 'Andere', UNIQUE_VISITS: 'Eindeutige Besuche', FIELD_TITLE: 'Feldtitel', FIELD_VIEWS: 'Feld Ansichten', FIELD_DROPOFF: 'Feldabschluss', FIELD_RESPONSES: 'Feldantworten', DELETE_SELECTED: 'Ausgewählte löschen', EXPORT_TO_EXCEL: 'Export nach Excel', EXPORT_TO_CSV: 'In CSV exportieren', EXPORT_TO_JSON: 'Export nach JSON', PERCENTAGE_COMPLETE: 'Prozent abgeschlossen', TIME_ELAPSED: 'Zeit verstrichen', DEVICE: 'Gerät', LOCATION: 'Ort', IP_ADDRESS: 'IP-Adresse', DATE_SUBMITTED: 'Eingereichtes Datum', // Entwurfsansicht BACKGROUND_COLOR: 'Hintergrundfarbe', DESIGN_HEADER: 'Ändern Sie, wie Ihr Formular aussieht', QUESTION_TEXT_COLOR: 'Fragetextfarbe', ANSWER_TEXT_COLOR: 'Textfarbe beantworten', BTN_BACKGROUND_COLOR: 'Schaltfläche Hintergrundfarbe', BTN_TEXT_COLOR: 'Schaltfläche Textfarbe', // Freigabeansicht EMBED_YOUR_FORM: 'Einbetten Ihres Formulars', SHARE_YOUR_FORM: 'Teilen Sie Ihr Formular', // Admin-Registerkarten CREATE_TAB: 'Erstellen', DESIGN_TAB: 'Entwurf', CONFIGURE_TAB: 'Konfigurieren', ANALYZE_TAB: 'Analysieren', SHARE_TAB: 'Freigeben', // Feldtypen SHORT_TEXT: 'Kurztext', EMAIL: 'Email', MULTIPLE_CHOICE: 'Mehrfachauswahl', DROPDOWN: 'Dropdown-Liste', DATE: 'Datum', PARAGRAPH_T: "Absatz", YES_NO: 'Ja / Nein', LEGAL: "Rechtliche", RATING: 'Bewertung', NUMBERS: 'Zahlen', SIGNATURE: "Unterschrift", FILE_UPLOAD: 'Datei-Upload', OPTION_SCALE: 'Optionsskala', ZAHLUNG: "Zahlung", STATEMENT: 'Anweisung', LINK: 'Link', // Formularvorschau FORM_SUCCESS: 'Formulareintrag erfolgreich gesendet!', REVIEW: 'Überprüfung', BACK_TO_FORM: 'Gehe zurück zu Formular', EDIT_FORM: 'Bearbeiten Sie diese TellForm', ADVANCEMENT: '{{done}} von {{total}} wurde beantwortet', CONTINUE_FORM: 'Weiter zum Formular', REQUIRED: 'erforderlich', COMPLETING_NEEDED: '{{answers_not_completed}} Antwort (en) müssen ausgefüllt werden', OPTIONAL: 'optional', ERROR_EMAIL_INVALID: 'Geben Sie eine gültige E-Mail-Adresse ein', ERROR_NOT_A_NUMBER: 'Bitte nur gültige Nummern eingeben', ERROR_URL_INVALID: 'Bitte eine gültige URL', OK: 'OK', ENTER: 'ENTER drücken', NEWLINE: 'Drücken Sie UMSCHALT + EINGABETASTE, um eine neue Zeile zu erstellen', CONTINUE: 'Weiter', LEGAL_ACCEPT: "Ich akzeptiere", LEGAL_NO_ACCEPT: "Ich akzeptiere nicht", SUBMIT: 'Senden', UPLOAD_FILE: 'Hochladen Ihrer Datei' }); }]); 'use strict'; angular.module('forms').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('it', { // Configura la visualizzazione scheda modulo ADVANCED_SETTINGS: 'Impostazioni avanzate', FORM_NAME: 'Nome modulo', FORM_STATUS: 'Stato modulo', PUBLIC: 'pubblico', PRIVATE: 'Privato', GA_TRACKING_CODE: 'Codice di monitoraggio di Google Analytics', DISPLAY_FOOTER: 'Visualizza piè di pagina?', SAVE_CHANGES: 'Salva modifiche', CANCEL: 'Annulla', DISPLAY_START_PAGE: 'Visualizza pagina iniziale?', DISPLAY_END_PAGE: 'Mostra pagina finale personalizzata?', // Visualizzazione dei moduli di elenco CREATE_A_NEW_FORM: 'Crea un nuovo modulo', CREATE_FORM: 'Crea modulo', CREATED_ON: 'Creato su', MY_FORMS: 'Le mie forme', NAME: 'Nome', LINGUA: 'Lingua', FORM_PAUSED: 'Forme in pausa', // Modifica campo modale EDIT_FIELD: 'Modifica questo campo', SAVE_FIELD: 'Salva', ON: 'ON', OFF: 'OFF', REQUIRED_FIELD: 'Obbligatorio', LOGIC_JUMP: 'Jump Logic', SHOW_BUTTONS: 'Pulsanti aggiuntivi', SAVE_START_PAGE: 'Salva', // Visualizzazione modulo di amministrazione ARE_YOU_SURE: 'Sei ASSOLUTAMENTE sicuro?', READ_WARNING: 'Le cose cattive impreviste avverranno se non lo leggi!', DELETE_WARNING1: 'Questa azione NON può essere annullata. Ciò eliminerà in modo permanente il "', DELETE_WARNING2: '" forma e rimuovi tutti i moduli di modulo associati. ', DELETE_CONFIRM: 'Inserisci il nome del modulo per confermare', I_UNDERSTAND: "Capisco le conseguenze, elimina questa forma", DELETE_FORM_SM: 'Elimina', DELETE_FORM_MD: 'Elimina modulo', DELETE: 'Elimina', FORM: 'Forma', VIEW: 'Visualizza', LIVE: 'Live', PREVIEW: 'Anteprima', COPY: 'Copia', COPY_AND_PASTE: 'Copia e incolla questo per aggiungere il tuo TellForm al tuo sito web', CHANGE_WIDTH_AND_HEIGHT: 'Modifica i valori di larghezza e di altezza per adattarti al meglio', POWERED_BY: 'Offerto da', TELLFORM_URL: 'Il tuo TellForm è permanente in questo URL', // Modifica vista modulo DISABLED: 'disabilitato', YES: 'SI', NO: 'NO', ADD_LOGIC_JUMP: 'Aggiungi logico salto', ADD_FIELD_LG: 'Clicca per aggiungere nuovo campo', ADD_FIELD_MD: 'Aggiungi nuovo campo', ADD_FIELD_SM: 'Aggiungi campo', EDIT_START_PAGE: 'Modifica pagina iniziale', EDIT_END_PAGE: 'Modifica pagina finale', WELCOME_SCREEN: 'Pagina iniziale', END_SCREEN: 'Fine pagina', INTRO_TITLE: 'Titolo', INTRO_PARAGRAPH: 'Paragrafo', INTRO_BTN: 'Pulsante Start', TITLE: 'Titolo', PARAGRAFO: 'Paragrafo', BTN_TEXT: 'Tornare indietro', TASTI: 'Pulsanti', BUTTON_TEXT: 'Testo', BUTTON_LINK: 'Link', ADD_BUTTON: 'Aggiungi pulsante', PREVIEW_FIELD: 'Anteprima domanda', QUESTION_TITLE: 'Titolo', QUESTION_DESCRIPTION: 'Descrizione', OPTIONS: 'Opzioni', ADD_OPTION: 'Aggiungi opzione', NUM_OF_STEPS: 'Numero di passi', CLICK_FIELDS_FOOTER: 'Clicca sui campi per aggiungerli qui', FORMA: 'Forma', IF_THIS_FIELD: 'Se questo campo', IS_EQUAL_TO: 'è uguale a', IS_NOT_EQUAL_TO: 'non è uguale a', IS_GREATER_THAN: 'è maggiore di', IS_GREATER_OR_EQUAL_THAN: 'è maggiore o uguale a', IS_SMALLER_THAN: 'è inferiore a', IS_SMALLER_OR_EQUAL_THAN: 'è più piccolo o uguale a quello', CONTAINS: 'contiene', DOES_NOT_CONTAINS: 'non contiene', ENDS_WITH: 'finisce con', DOES_NOT_END_WITH: 'non finisce con', STARTS_WITH: 'inizia con', DOES_NOT_START_WITH: 'non inizia con', THEN_JUMP_TO: 'poi salta a', // Modifica visualizzazione presentazioni TOTAL_VIEWS: 'visite totali totali', RESPONSES: 'risposte', COMPLETION_RATE: 'tasso di completamento', AVERAGE_TIME_TO_COMPLETE: 'avg. tempo di completamento', DESKTOP_AND_LAPTOP: 'Desktop', TABLETS: 'compresse', PHONES: 'Telefoni', OTHER: 'Altro', UNIQUE_VISITS: 'Visite Uniche', FIELD_TITLE: 'Titolo del campo', FIELD_VIEWS: 'Viste sul campo', FIELD_DROPOFF: 'Completamento del campo', FIELD_RESPONSES: 'Risposte sul campo', DELETE_SELECTED: 'Elimina selezionata', EXPORT_TO_EXCEL: 'Esporta in Excel', EXPORT_TO_CSV: 'Esporta in CSV', EXPORT_TO_JSON: 'Esporta in JSON', PERCENTAGE_COMPLETE: 'Percentuale completa', TIME_ELAPSED: 'Tempo trascorso', DEVICE: 'Dispositivo', LOCATION: 'Posizione', IP_ADDRESS: 'Indirizzo IP', DATE_SUBMITTED: 'Data trasmessa', // Vista di progettazione BACKGROUND_COLOR: 'Colore di sfondo', DESIGN_HEADER: 'Modifica il tuo aspetto forma', QUESTION_TEXT_COLOR: 'Colore del testo di domanda', ANSWER_TEXT_COLOR: 'Rispondere al colore del testo', BTN_BACKGROUND_COLOR: 'Colore di sfondo del pulsante', BTN_TEXT_COLOR: 'Colore del testo pulsante', // Vista condivisione EMBED_YOUR_FORM: 'Inserisci il tuo modulo', SHARE_YOUR_FORM: 'Condividi il tuo modulo', // Schede amministratore CREATE_TAB: 'Crea', DESIGN_TAB: 'Design', CONFIGURE_TAB: 'Configura', ANALYZE_TAB: 'Analizza', SHARE_TAB: 'Condividi', // Tipi di campo SHORT_TEXT: 'Testo corto', EMAIL: 'E-mail', MULTIPLE_CHOICE: 'Scelta multipla', DROPDOWN: 'Dropdown', DATE: 'Data', PARAGRAPH_T: 'Paragrafo', YES_NO: 'Sì / no', LEGAL: 'Legale', RATING: 'Valutazione', NUMBERS: 'Numeri', SIGNATURE: 'Firma', FILE_UPLOAD: 'Caricamento file', OPTION_SCALE: 'Scala opzione', PAGAMENTO: 'Pagamento', STATEMENT: 'Dichiarazione', LINK: 'Link', // Anteprima del modulo FORM_SUCCESS: 'Inserimento modulo con successo presentato!', REVIEW: 'Recensione', BACK_TO_FORM: 'Torna alla scheda', EDIT_FORM: 'Modifica questo TellForm', ADVANCEMENT: '{{done}} su {{total}} ha risposto', CONTINUE_FORM: "Continua a formare", REQUIRED: 'richiesta', COMPLETING_NEEDED: '{{answers_not_completed}} answer (s) need completing', OPTIONAL: 'facoltativo', ERROR_EMAIL_INVALID: 'Inserisci un indirizzo e-mail valido', ERROR_NOT_A_NUMBER: 'Inserisci solo numeri validi', ERROR_URL_INVALID: 'Per favore un url valido', OK: 'OK', ENTER: 'premere INVIO', NEWLINE: 'premere SHIFT + INVIO per creare una nuova riga', CONTINUE: 'Continua', LEGAL_ACCEPT: 'accetto', LEGAL_NO_ACCEPT: 'Non accetto', SUBMIT: 'Invia', UPLOAD_FILE: 'Carica il tuo file' }); }]); 'use strict'; angular.module('forms').config(['$translateProvider', function ($translateProvider) { $translateProvider.translations('es', { //Configure Form Tab View ADVANCED_SETTINGS: 'Configuraciones avanzadas', FORM_NAME: 'Nombre del formulario', FORM_STATUS: 'Estado del formulario', PUBLIC: 'Público', PRIVATE: 'Privado', GA_TRACKING_CODE: 'Código de Google Analytics', DISPLAY_FOOTER: '¿Mostrar pie de página?', SAVE_CHANGES: 'Grabar', CANCEL: 'Cancelar', DISPLAY_START_PAGE: '¿Mostrar página de inicio?', DISPLAY_END_PAGE: '¿Mostrar paǵina de fin?', //List Forms View CREATE_A_NEW_FORM: 'Crear formulario', CREATE_FORM: 'Crear formulario', CREATED_ON: 'Creado en', MY_FORMS: 'Mis formularios', NAME: 'Nombre', LANGUAGE: 'Idioma', FORM_PAUSED: 'Formulario pausado', //Edit Field Modal EDIT_FIELD: 'Editar este campo', SAVE_FIELD: 'Grabar', ON: 'EN', OFF: 'APAGADO', REQUIRED_FIELD: 'Requerido', LOGIC_JUMP: 'Salto lógico', SHOW_BUTTONS: 'Botones adicionales', SAVE_START_PAGE: 'Grabar', //Admin Form View ARE_YOU_SURE: '¿Estás absolutamente seguro?', READ_WARNING: '¡Algo malo ocurrirá si no lees esto!', DELETE_WARNING1: 'Esta acción no tiene vuelta atrás. Esto borrará permanentemente el "', DELETE_WARNING2: '" formulario y todos los datos asociados.', DELETE_CONFIRM: 'Por favor escribí el nombre del formulario para confirmar.', I_UNDERSTAND: 'Entiendo las consecuencias y quiero borrarlo.', DELETE_FORM_SM: 'Borrar', DELETE_FORM_MD: 'Borrar formulario', DELETE: 'Borrar', FORM: 'Formulario', VIEW: 'Vista', LIVE: 'Online', PREVIEW: 'Vista previa', COPY: 'Copiar', COPY_AND_PASTE: 'Copiar y pegar esto para agregar su TellForm a su sitio web', CHANGE_WIDTH_AND_HEIGHT: 'Cambie los valores de ancho y altura para adaptar el formulario a sus necesidades', POWERED_BY: 'Con la tecnlogía de', TELLFORM_URL: 'Tu TellForm está en esta URL permanente', //Edit Form View DISABLED: 'Deshabilitado', YES: 'SI', NO: 'NO', ADD_LOGIC_JUMP: 'Agregar salto lógico', ADD_FIELD_LG: 'Click para agregar campo', ADD_FIELD_MD: 'Agregar nuevo campo', ADD_FIELD_SM: 'Agregar campo', EDIT_START_PAGE: 'Editar paǵina de inicio', EDIT_END_PAGE: 'Editar página de finalización', WELCOME_SCREEN: 'Comienzo', END_SCREEN: 'Fin', INTRO_TITLE: 'Título', INTRO_PARAGRAPH: 'Parágrafo', INTRO_BTN: 'Botón de comienzo', TITLE: 'Título', PARAGRAPH: 'Paragrafo', BTN_TEXT: 'Botón para volver atrás', BUTTONS: 'Botones', BUTTON_TEXT: 'Texto', BUTTON_LINK: 'Link', ADD_BUTTON: 'Agregar Botón', PREVIEW_FIELD: 'Vista previa Pregunta', QUESTION_TITLE: 'Título', QUESTION_DESCRIPTION: 'Descripción', OPTIONS: 'Opciones', ADD_OPTION: 'Agregar Opciones', NUM_OF_STEPS: 'Cantidad de pasos', CLICK_FIELDS_FOOTER: 'Click en los campos para agregar', SHAPE: 'Forma', IF_THIS_FIELD: 'Si este campo', IS_EQUAL_TO: 'es igual a', IS_NOT_EQUAL_TO: 'no es igual a', IS_GREATER_THAN: 'es mayor que', IS_GREATER_OR_EQUAL_THAN: 'es mayor o igual que', IS_SMALLER_THAN: 'es menor que', IS_SMALLER_OR_EQUAL_THAN: 'is menor o igual que', CONTAINS: 'contiene', DOES_NOT_CONTAINS: 'no contiene', ENDS_WITH: 'termina con', DOES_NOT_END_WITH: 'no termina con', STARTS_WITH: 'comienza con', DOES_NOT_START_WITH: 'no comienza con', THEN_JUMP_TO: 'luego salta a', //Edit Submissions View TOTAL_VIEWS: 'Total de visitas únicas', RESPONSES: 'respuestas', COMPLETION_RATE: 'Taza de terminación', AVERAGE_TIME_TO_COMPLETE: 'Promedio de tiempo de rellenado', DESKTOP_AND_LAPTOP: 'Computadora', TABLETS: 'Tablets', PHONES: 'Móviles', OTHER: 'Otros', UNIQUE_VISITS: 'Visitas únicas', FIELD_TITLE: 'Título de campo', FIELD_VIEWS: 'Vistas de campo', FIELD_DROPOFF: 'Finalización de campo', FIELD_RESPONSES: 'Respuestas de campo', DELETE_SELECTED: 'Borrar selección', EXPORT_TO_EXCEL: 'Exportar a Excel', EXPORT_TO_CSV: 'Exportar a CSV', EXPORT_TO_JSON: 'Exportar a JSON', PERCENTAGE_COMPLETE: 'Porcentaje de completitud', TIME_ELAPSED: 'Tiempo usado', DEVICE: 'Dispositivo', LOCATION: 'Lugar', IP_ADDRESS: 'Dirección IP', DATE_SUBMITTED: 'Fecha de envío', //Design View BACKGROUND_COLOR: 'Color de fondo', DESIGN_HEADER: 'Cambiar diseño de formulario', QUESTION_TEXT_COLOR: 'Color de la pregunta', ANSWER_TEXT_COLOR: 'Color de la respuesta', BTN_BACKGROUND_COLOR: 'Color de fondo del botón', BTN_TEXT_COLOR: 'Color del texto del botón', //Share View EMBED_YOUR_FORM: 'Pone tu formulario', SHARE_YOUR_FORM: 'Compartí tu formulario', //Admin Tabs CREATE_TAB: 'Crear', DESIGN_TAB: 'Diseño', CONFIGURE_TAB: 'Configuración', ANALYZE_TAB: 'Análisis', SHARE_TAB: 'Compartir', //Field Types SHORT_TEXT: 'Texto corto', EMAIL: 'Email', MULTIPLE_CHOICE: 'Opciones múltiples', DROPDOWN: 'Desplegable', DATE: 'Fecha', PARAGRAPH_T: 'Párrafo', YES_NO: 'Si/No', LEGAL: 'Legal', RATING: 'Puntaje', NUMBERS: 'Números', SIGNATURE: 'Firma', FILE_UPLOAD: 'Subir archivo', OPTION_SCALE: 'Escala', PAYMENT: 'Pago', STATEMENT: 'Declaración', LINK: 'Enlace', FORM_SUCCESS: '¡El formulario ha sido enviado con éxito!', REVIEW: 'Revisar', BACK_TO_FORM: 'Regresar al formulario', 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', NEWLINE: 'presione SHIFT+INTRO para crear una nueva línea', CONTINUE: 'Continuar', LEGAL_ACCEPT: 'Yo acepto', LEGAL_NO_ACCEPT: 'Yo no acepto', SUBMIT: 'Registrar', UPLOAD_FILE: 'Cargar el archivo', Y: 'S', N: 'N' }); }]); 'use strict'; // Use Application configuration module to register a new module ApplicationConfiguration.registerModule('view-form', [ 'ngFileUpload', 'ui.date', 'angular-input-stars' ]); (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) { var lang = window.navigator.userLanguage || window.navigator.language; lang = lang.slice(0,2); var userAgentString = navigator.userAgent; var md = new MobileDetect(userAgentString); var deviceType = 'other'; if (md.tablet()){ deviceType = 'tablet'; } else if (md.mobile()) { deviceType = 'mobile'; } else if (!md.is('bot')) { deviceType = 'desktop'; } // Create a new message object var visitorData = { referrer: document.referrer, isSubmitted: form.submitted, formId: form._id, lastActiveField: form.form_fields[lastActiveIndex]._id, timeElapsed: timeElapsed, language: lang, deviceType: deviceType, ipAddr: null, geoLocation: null }; Socket.emit('form-visitor-data', visitorData); } function init(){ // Make sure the Socket is connected if (!Socket.socket) { Socket.connect(); } Socket.on('disconnect', function(){ 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; 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: '=', nextField: '&' }, 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'; if($attrs.onValidKey){ $scope.$root.$eval($attrs.onValidKey); } }); }else if(keyCode === falseyKeyCode){ event.preventDefault(); $scope.$apply(function() { $scope.field.fieldValue = 'false'; if($attrs.onValidKey){ $scope.$root.$eval($attrs.onValidKey); } }); } }); } }; }]); '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 !== 'rating' && field.fieldType !== 'statement'){ return !!(field.fieldValue); } else if (field.fieldType === 'rating'){ return true; } }).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').constant('VIEW_FORM_URL', '/forms/:formId/render'); 'use strict'; angular.module('view-form').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', Y: 'Y', N: 'N', OPTION_PLACEHOLDER: 'Type or select an option', ADD_NEW_LINE_INSTR: 'Press SHIFT+ENTER to add a newline', ERROR: 'Error', FORM_404_HEADER: '404 - Form Does Not Exist', FORM_404_BODY: 'The form you are trying to access does not exist. Sorry about that!', FORM_UNAUTHORIZED_HEADER: 'Not Authorized to Access Form', FORM_UNAUTHORIZED_BODY1: 'The form you are trying to access is currently private and not accesible publically.', FORM_UNAUTHORIZED_BODY2: 'If you are the owner of the form, you can set it to "Public" in the "Configuration" panel in the form admin.', }); $translateProvider.preferredLanguage('en') .fallbackLanguage('en') .useSanitizeValueStrategy('escape'); }]); 'use strict'; angular.module('view-form').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', OPTION_PLACEHOLDER: 'Tapez ou sélectionnez une option', ADD_NEW_LINE_INSTR: 'Appuyez sur MAJ + ENTRÉE pour ajouter une nouvelle ligne', ERROR: 'Erreur', FORM_404_HEADER: '404 - Le formulaire n\'existe pas', FORM_404_BODY: 'Le formulaire auquel vous essayez d\'accéder n\'existe pas. Désolé pour ça!', FORM_UNAUTHORIZED_HEADER: 'Non autorisé à accéder au formulaire',    FORM_UNAUTHORIZED_BODY1: 'Le formulaire auquel vous essayez d\'accéder est actuellement privé et inaccessible publiquement.',    FORM_UNAUTHORIZED_BODY2: 'Si vous êtes le propriétaire du formulaire, vous pouvez le définir sur "Public" dans le panneau "Configuration" du formulaire admin.', }); }]); 'use strict'; angular.module('view-form').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: 'Dieses TellForm erstellen', 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', OPTION_PLACEHOLDER: 'Geben oder wählen Sie eine Option aus', ADD_NEW_LINE_INSTR: 'Drücken Sie UMSCHALT + EINGABETASTE, um eine neue Zeile hinzuzufügen', ERROR: 'Fehler', FORM_404_HEADER: '404 - Formular existiert nicht', FORM_404_BODY: 'Das Formular, auf das Sie zugreifen möchten, existiert nicht. Das tut mir leid!', FORM_UNAUTHORIZED_HEADER: 'Nicht zum Zugriffsformular berechtigt\' ',    FORM_UNAUTHORIZED_BODY1: 'Das Formular, auf das Sie zugreifen möchten, ist derzeit privat und nicht öffentlich zugänglich.',    FORM_UNAUTHORIZED_BODY2: 'Wenn Sie der Eigentümer des Formulars sind, können Sie es im Fenster "Konfiguration" im Formular admin auf "Öffentlich" setzen.', }); }]); 'use strict'; angular.module('view-form').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: 'Crea questo 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: 'I accept', LEGAL_NO_ACCEPT: 'I don’t accept', DELETE: 'Cancella', CANCEL: 'Reset', SUBMIT: 'Registra', UPLOAD_FILE: 'Invia un file', Y: 'S', N: 'N', OPTION_PLACEHOLDER: 'Digitare o selezionare un\'opzione', ADD_NEW_LINE_INSTR: 'Premere SHIFT + INVIO per aggiungere una nuova riga', ERROR: 'Errore', FORM_404_HEADER: '404 - Il modulo non esiste', FORM_404_BODY: 'La forma che stai cercando di accedere non esiste. Ci dispiace!', FORM_UNAUTHORIZED_HEADER: 'Non autorizzato per accedere al modulo',    FORM_UNAUTHORIZED_BODY1: 'Il modulo che si sta tentando di accedere è attualmente privato e non accessibile in pubblico.',    FORM_UNAUTHORIZED_BODY2: 'Se sei il proprietario del modulo, puoi impostarlo su "Pubblico" nel pannello "Configurazione" nell\'amministratore di moduli.', }); }]); 'use strict'; angular.module('view-form').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: 'Editar este TellForm', CREATE_FORM: 'Crear 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: 'Yo acepto', LEGAL_NO_ACCEPT: 'Yo no acepto', DELETE: 'Eliminar', CANCEL: 'Cancelar', SUBMIT: 'Registrar', UPLOAD_FILE: 'Cargar el archivo', Y: 'S', N: 'N', OPTION_PLACEHOLDER: 'Escriba o seleccione una opción', ADD_NEW_LINE_INSTR: 'Presione MAYÚS + ENTRAR para agregar una nueva línea', ERROR: 'Error', FORM_404_HEADER: '404 - La forma no existe', FORM_404_BODY: 'El formulario al que intenta acceder no existe. ¡Lo siento por eso!', FORM_UNAUTHORIZED_HEADER: 'Non autorizzato per accedere al modulo',    FORM_UNAUTHORIZED_BODY1: 'Il modulo che si sta tentando di accedere è attualmente privato e non accessibile in pubblico.',    FORM_UNAUTHORIZED_BODY2: 'Se sei il proprietario del modulo, puoi impostarlo su "Pubblico" nel pannello "Configurazione" nell\'amministratore di moduli.', }); }]); 'use strict'; // SubmitForm controller angular.module('view-form').controller('SubmitFormController', [ '$scope', '$rootScope', '$state', '$translate', 'myForm', function($scope, $rootScope, $state, $translate, myForm) { $scope.myform = myForm; $(".loader").fadeOut("slow"); document.body.style.background = myForm.design.colors.backgroundColor; $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 getTemplateHtml = function(fieldType) { var type = fieldType; var supported_fields = [ 'textfield', 'textarea', 'date', 'dropdown', 'hidden', 'password', 'radio', 'legal', 'statement', 'rating', 'yes_no', 'number', 'natural' ]; var templateUrl = 'form_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'){ scope.field.fieldValue = scope.field.fieldOptions[0].option_value; }else if(type === 'legal'){ scope.field.fieldValue = 'true'; $rootScope.nextField(); } }; scope.nextField = $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.input_type = 'text'; break; case 'email': scope.input_type = 'email'; scope.placeholder = 'joesmith@example.com'; break; case 'number': scope.input_type = 'text'; scope.validateRegex = /^-?\d+$/; break; default: scope.input_type = 'url'; scope.placeholder = 'http://example.com'; break; } fieldType = 'textfield'; } var template = getTemplateHtml(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('keyup 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) { console.log('onTabAndShiftKey'); 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 () { $rootScope.$broadcast(broadcastMessage+' Finished'); }); } } }; }]); 'use strict'; //FIXME: Should find an appropriate place for this //Setting up jsep jsep.addBinaryOp('contains', 10); jsep.addBinaryOp('!contains', 10); jsep.addBinaryOp('begins', 10); jsep.addBinaryOp('!begins', 10); jsep.addBinaryOp('ends', 10); jsep.addBinaryOp('!ends', 10); angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCounter', '$filter', '$rootScope', 'SendVisitorData', '$translate', '$timeout', function ($http, TimeCounter, $filter, $rootScope, SendVisitorData, $translate, $timeout) { return { templateUrl: 'form_modules/forms/base/views/directiveViews/form/submit-form.client.view.html', restrict: 'E', scope: { myform:'=', ispreview: '=' }, controller: ["$document", "$window", "$scope", function($document, $window, $scope){ var NOSCROLL = false; var FORM_ACTION_ID = 'submit_field'; $scope.forms = {}; //Don't start timer if we are looking at a design preview if($scope.ispreview){ TimeCounter.restartClock(); } var form_fields_count = $scope.myform.visible_form_fields.filter(function(field){ return field.fieldType !== 'statement'; }).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); //Reset Timer TimeCounter.restartClock(); }; /* ** Field Controls */ var evaluateLogicJump = function(field){ var logicJump = field.logicJump; if(logicJump.enabled){ if (logicJump.expressionString && logicJump.valueB && field.fieldValue) { var parse_tree = jsep(logicJump.expressionString); var left, right; if(parse_tree.left.name === 'field'){ left = field.fieldValue; right = logicJump.valueB; } else { left = logicJump.valueB; right = field.fieldValue; } if(field.fieldType === 'number' || field.fieldType === 'scale' || field.fieldType === 'rating'){ switch(parse_tree.operator) { case '==': return (parseInt(left) === parseInt(right)); case '!==': return (parseInt(left) !== parseInt(right)); case '>': return (parseInt(left) > parseInt(right)); case '>=': return (parseInt(left) > parseInt(right)); case '<': return (parseInt(left) < parseInt(right)); case '<=': return (parseInt(left) <= parseInt(right)); default: return false; } } else { switch(parse_tree.operator) { case '==': return (left === right); case '!==': return (left !== right); case 'contains': return (left.indexOf(right) > -1); case '!contains': /* jshint -W018 */ return !(left.indexOf(right) > -1); case 'begins': return left.startsWith(right); case '!begins': return !left.startsWith(right); case 'ends': return left.endsWith(right); case '!ends': return left.endsWith(right); default: return false; } } } } }; 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 === FORM_ACTION_ID) { return $scope.myform.form_fields.length - 1; } return $scope.selected.index; }; $scope.isActiveField = function(field){ if($scope.selected._id === field._id) { return true } return false; }; $scope.setActiveField = $rootScope.setActiveField = function(field_id, field_index, animateScroll) { if($scope.selected === null || (!field_id && field_index === null) ) { return; } if(!field_id){ field_id = $scope.myform.visible_form_fields[field_index]._id; } else if(field_index === null){ field_index = $scope.myform.visible_form_fields.length for(var i=0; i < $scope.myform.visible_form_fields.length; i++){ var currField = $scope.myform.visible_form_fields[i]; if(currField['_id'] == field_id){ field_index = i; break; } } } if($scope.selected._id === field_id){ return; } $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){ NOSCROLL=true; setTimeout(function() { $document.scrollToElement(angular.element('.activeField'), -10, 200).then(function() { 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(); } }); }); }); } }; $scope.$watch('selected.index', function(oldValue, newValue){ if(oldValue !== newValue && newValue < $scope.myform.form_fields.length){ //Only send analytics data if form has not been submitted if(!$scope.myform.submitted){ console.log('SendVisitorData.send()'); SendVisitorData.send($scope.myform, newValue, TimeCounter.getTimeElapsed()); } } }); //Fire event when window is scrolled $window.onscroll = function(){ if(!NOSCROLL){ var scrollTop = $(window).scrollTop(); var elemBox = document.getElementsByClassName('activeField')[0].getBoundingClientRect(); var fieldTop = elemBox.top; var fieldBottom = elemBox.bottom; var field_id, field_index; var elemHeight = $('.activeField').height(); var submitSectionHeight = $('.form-actions').height(); var maxScrollTop = $(document).height() - $(window).height(); var fieldWrapperHeight = $('form_fields').height(); var selector = 'form > .field-directive:nth-of-type(' + String($scope.myform.visible_form_fields.length - 1)+ ')' var fieldDirectiveHeight = $(selector).height() var scrollPosition = maxScrollTop - submitSectionHeight - fieldDirectiveHeight*1.2; var fractionToJump = 0.9; //Focus on field above submit form button if($scope.selected.index === $scope.myform.visible_form_fields.length){ if(scrollTop < scrollPosition){ field_index = $scope.selected.index-1; $scope.setActiveField(null, field_index, false); } } //Focus on submit form button else if($scope.selected.index === $scope.myform.visible_form_fields.length-1 && scrollTop > scrollPosition){ field_index = $scope.selected.index+1; $scope.setActiveField(FORM_ACTION_ID, field_index, false); } //If we scrolled bellow the current field, move to next field else if(fieldBottom < elemHeight * fractionToJump && $scope.selected.index < $scope.myform.visible_form_fields.length-1 ){ field_index = $scope.selected.index+1; $scope.setActiveField(null, field_index, false); } //If we scrolled above the current field, move to prev field else if ( $scope.selected.index !== 0 && fieldTop > elemHeight * fractionToJump) { field_index = $scope.selected.index-1; $scope.setActiveField(null, field_index, false); } } $scope.$apply(); }; $rootScope.nextField = $scope.nextField = function(){ if($scope.selected && $scope.selected.index > -1){ if($scope.selected._id !== FORM_ACTION_ID){ var currField = $scope.myform.visible_form_fields[$scope.selected.index]; //Jump to logicJump's destination if it is true if(currField.logicJump && currField.logicJump.jumpTo && evaluateLogicJump(currField)){ $scope.setActiveField(currField.logicJump.jumpTo, null, true); } else if($scope.selected.index < $scope.myform.visible_form_fields.length-1){ $scope.setActiveField(null, $scope.selected.index+1, true); } else { $scope.setActiveField(FORM_ACTION_ID, null, true); } } else { //If we are at the submit actions page, go to the first field $rootScope.setActiveField(null, 0, true); } } else { //If selected is not defined go to the first field $rootScope.setActiveField(null, 0, true); } }; $rootScope.prevField = $scope.prevField = function(){ console.log('prevField'); console.log($scope.selected); var selected_index = $scope.selected.index - 1; if($scope.selected.index > 0){ $scope.setActiveField(null, selected_index, true); } }; $rootScope.goToInvalid = $scope.goToInvalid = function() { var field_id = $('.row.field-directive .ng-invalid.focusOn, .row.field-directive .ng-untouched.focusOn:not(.ng-valid)').first().parents('.row.field-directive').first().attr('data-id'); $scope.setActiveField(field_id, null, 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; } }; var getDeviceData = function(){ var md = new MobileDetect(window.navigator.userAgent); var deviceType = 'other'; if (md.tablet()){ deviceType = 'tablet'; } else if (md.mobile()) { deviceType = 'mobile'; } else if (!md.is('bot')) { deviceType = 'desktop'; } return { type: deviceType, name: window.navigator.platform }; }; var getIpAndGeo = function(){ //Get Ip Address and GeoLocation Data $.ajaxSetup( { 'async': false } ); var geoData = $.getJSON('https://freegeoip.net/json/').responseJSON; $.ajaxSetup( { 'async': true } ); if(!geoData || !geoData.ip){ geoData = { ip: 'Adblocker' }; } return { ipAddr: geoData.ip, geoLocation: { City: geoData.city, Country: geoData.country_name } }; }; $rootScope.submitForm = $scope.submitForm = function() { if($scope.forms.myForm.$invalid){ $scope.goToInvalid(); return; } var _timeElapsed = TimeCounter.stopClock(); $scope.loading = true; var form = _.cloneDeep($scope.myform); var deviceData = getDeviceData(); form.device = deviceData; var geoData = getIpAndGeo(); form.ipAddr = geoData.ipAddr; form.geoLocation = geoData.geoLocation; form.timeElapsed = _timeElapsed; form.percentageComplete = $filter('formValidity')($scope.myform) / $scope.myform.visible_form_fields.length * 100; delete form.endPage delete form.isLive delete form.provider delete form.startPage delete form.visible_form_fields; delete form.analytics; delete form.design; delete form.submissions; delete form.submitted; 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; } //Get rid of unnessecary attributes for each form field delete form.form_fields[i].submissionId; delete form.form_fields[i].disabled; delete form.form_fields[i].ratingOptions; delete form.form_fields[i].fieldOptions; delete form.form_fields[i].logicJump; delete form.form_fields[i].description; delete form.form_fields[i].validFieldTypes; delete form.form_fields[i].fieldType; } setTimeout(function () { $scope.submitPromise = $http.post('/forms/' + $scope.myform._id, form) .success(function (data, status) { $scope.myform.submitted = true; $scope.loading = false; SendVisitorData.send(form, 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', 'VIEW_FORM_URL', function($resource, VIEW_FORM_URL) { return $resource(VIEW_FORM_URL, { formId: '@_id' }, { '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 function Socket($timeout, $window) { var service = { socket: null }; // Connect to TellForm Socket.io server function connect() { var url = ''; if($window.socketUrl && $window.socketPort){ url = window.location.protocol + '//' + $window.socketUrl + ':' + $window.socketPort; } else if ($window.socketUrl){ url = window.location.protocol + '//' + $window.socketUrl; } else if ($window.socketPort){ url = window.location.protocol + '//' + window.location.hostname + ':' + $window.socketPort; } else { url = window.location.protocol + '//' + window.location.hostname; } 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); } } connect(); service = { connect: connect, emit: emit, on: on, removeListener: removeListener, socket: null }; return service; } angular .module('view-form') .factory('Socket', Socket); Socket.$inject = ['$timeout', '$window']; }()); 'use strict'; 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(){ 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; } return new Error('Clock has not been started'); }; this.clockStarted = function(){ return !!this._startTime; }; } ]);