diff --git a/gruntfile.js b/gruntfile.js index 1eead5e8..af7a331f 100755 --- a/gruntfile.js +++ b/gruntfile.js @@ -227,7 +227,7 @@ module.exports = function(grunt) { }, html2js: { options: { - base: 'public', + base: 'NodeForm', watch: true, module: 'NodeForm.templates', singleModule: true, @@ -294,7 +294,7 @@ module.exports = function(grunt) { grunt.registerTask('lint:tests', ['jshint:allTests']); // Build task(s). - grunt.registerTask('build', ['lint', 'loadConfig', 'cssmin', 'html2js:main', 'ngAnnotate', 'uglify']); + grunt.registerTask('build', ['lint', 'loadConfig', 'cssmin', 'ngAnnotate', 'uglify', 'html2js:main']); // Test task(s). grunt.registerTask('test', ['lint:tests', 'test:server', 'test:client']); diff --git a/public/dist/application.js b/public/dist/application.js new file mode 100644 index 00000000..c2f07c76 --- /dev/null +++ b/public/dist/application.js @@ -0,0 +1,2713 @@ +angular.module('NodeForm.templates', []).run(['$templateCache', function($templateCache) { + "use strict"; + $templateCache.put("../public/modules/core/views/header.client.view.html", + "
"); + $templateCache.put("../public/modules/core/views/home.client.view.html", + "

TellForm

Craft beautiful forms in seconds.

Craft beautiful forms.

TellForm is an opensource alternative to TypeForm that can create stunning forms from PDFs or from scratch

TellForm is an opensource alternative to TypeForm that can create stunning forms from PDFs or from scratch

Create your next ______.

Tell a story with a form.

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

"); + $templateCache.put("../public/modules/forms/views/list-forms.client.view.html", + "

Create a new form
Name
Language

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

Change how your Form Looks

Change how your Form Looks

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

{{pageData.introTitle}}

{{pageData.introParagraph}}

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

{{field.title}} *(required)

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

{{field.title}} *(required)

{{$select.selected.option_value}}

"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/file.html", + "
{{field.title}} (* required)
{{field.file.originalname}}
Upload your File
"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/hidden.html", + ""); + $templateCache.put("../public/modules/forms/views/directiveViews/field/legal.html", + "

{{field.title}} *(required)


{{field.description}}


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

{{field.title}} *(required)


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

{{field.title}} *(required)

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

{{field.title}} *(required)


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

{{field.title}} *(required)

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

{{field.title}}

{{field.description}}


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

{{field.title}} *(required)

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

{{field.title}} *(required)

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

{{field.title}} *(required)

{{field.description}}


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

PDF Generation/EMR

PDF Generation/EMR

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


Advanced Settings

Advanced Settings

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

Click to Add New Field

Add New Field

Add Field

Start Page

Preview Start Page

    {{myform.startPage.introTitle}}

    {{myform.startPage.introParagraph}}

Edit Start Page


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

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

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

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

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

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

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

You need to be logged in to access this page

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

Sign into your account

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

Signup Successful

You've successfully registered an account at TellForm.

But your account is not activated yet



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

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

Signup with your email

Couldn't submit form due to errors:

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

Restore your password

Enter your account email.

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

Password reset is invalid

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

Password successfully reset

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

Reset your password

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

Change your password


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

Edit your profile

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

Language
Email (also your username)
"); + $templateCache.put("../public/modules/users/views/settings/social-accounts.client.view.html", + "

Connected social accounts:

Connect other social accounts:

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

Resend your account verification email

Enter your account email.

{{error}}

Verification Email has been Sent

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

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

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

Account successfuly activated

Continue to login page

Verification link is invalid or has expired

Resend your verification email Signin to your account
"); +}]); + +'use strict'; + +// Init the application configuration module for AngularJS application +var ApplicationConfiguration = (function() { + // Init module configuration options + var applicationModuleName = 'NodeForm'; + var applicationModuleVendorDependencies = ['duScroll', 'ui.select', 'cgBusy', 'ngSanitize', 'vButton', 'ngResource', 'NodeForm.templates', 'ui.router', 'ui.bootstrap', 'ui.utils', 'ngRaven']; + + // 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', +}); + +angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', '$state', '$stateParams', + function($rootScope, Auth, $state, $stateParams) { + + $rootScope.$state = $state; + $rootScope.$stateParams = $stateParams; + + // add previous state property + $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState) { + $state.previous = fromState; + console.log('toState: '+toState.name); + + //Redirect to listForms if user is authenticated + if(toState.name === 'home' || toState.name === 'signin' || toState.name === 'resendVerifyEmail' || toState.name === 'verify' || toState.name === 'signup' || toState.name === 'signup-success'){ + if(Auth.isAuthenticated()){ + event.preventDefault(); // stop current execution + console.log('go to forms'); + $state.go('listForms'); // go to listForms page + } + } + //Redirect to 'home' route if user is not authenticated + else if(toState.name !== 'access_denied' && !Auth.isAuthenticated() && toState.name !== 'submitForm'){ + console.log('go to home'); + event.preventDefault(); // stop current execution + $state.go('home'); // go to listForms page + } + + }); + + } +]); + +//Page access/authorization logic +angular.module(ApplicationConfiguration.applicationModuleName).run(['$rootScope', 'Auth', 'User', 'Authorizer', '$state', '$stateParams', + function($rootScope, Auth, User, Authorizer, $state, $stateParams) { + $rootScope.$on('$stateChangeStart', function(event, next) { + var authenticator, permissions, user; + permissions = next && next.data && next.data.permissions ? next.data.permissions : null; + + Auth.ensureHasCurrentUser(User); + user = Auth.currentUser; + + if(user){ + authenticator = new Authorizer(user); + //console.log('access denied: '+!authenticator.canAccess(permissions)); + //console.log(permissions); + if( (permissions != null) ){ + if( !authenticator.canAccess(permissions) ){ + event.preventDefault(); + console.log('access denied'); + $state.go('access_denied'); + } + } + } + }); +}]); + +//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]); +}); + +'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', 'colorpicker.module', 'ui.date', 'ui.sortable', 'angular-input-stars', 'users']); +'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'); + } +]); + +'use strict'; + +angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User', + function ($rootScope, $scope, Menus, $state, Auth, User) { + $scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User); + $scope.authentication = $rootScope.authentication = Auth; + + $rootScope.languages = $scope.languages = ['english', 'french', 'spanish']; + + $scope.isCollapsed = 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('home'); + }, + function(reason) { + console.log('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'; + + +angular.module('core').controller('HomeController', ['$rootScope', '$scope', 'User', '$state', + function($rootScope, $scope, User, $state) { + $scope = $rootScope; + } +]); + +'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; + } else { + for (var userRoleIndex in user.roles) { + for (var roleIndex in this.roles) { + console.log(this.roles[roleIndex]); + console.log( this.roles[roleIndex] === user.roles[userRoleIndex]); + if (this.roles[roleIndex] === user.roles[userRoleIndex]) { + return true; + } + } + } + } + } else { + return this.isPublic; + } + + return false; + }; + + // 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'); + } + + return false; + }; + + // 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'; + +// 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('highlight', function() { + function escapeRegexp(queryToEscape) { + return ('' + queryToEscape).replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'); + } + + return function(matchItem, query) { + return query && matchItem ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; + }; +})*/ +.filter('formValidity', + function(){ + return function(formObj){ + if(formObj && formObj.form_fields && formObj.visible_form_fields){ + + //get keys + var formKeys = Object.keys(formObj); + + //we only care about things that don't start with $ + var fieldKeys = formKeys.filter(function(key){ + return key[0] !== '$'; + }); + + var fields = formObj.form_fields; + + var valid_count = fields.filter(function(field){ + if(typeof field === 'object' && field.fieldType !== 'statement' && field.fieldType !== 'rating'){ + return !!(field.fieldValue); + } + + }).length; + return valid_count - (formObj.form_fields.length - formObj.visible_form_fields.length); + } + return 0; + }; +}).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/views/list-forms.client.view.html' + }). + state('submitForm', { + url: '/forms/:formId', + templateUrl: 'modules/forms/views/submit-form.client.view.html', + data: { + hideNav: true, + }, + resolve: { + Forms: 'Forms', + myForm: ["Forms", "$stateParams", function (Forms, $stateParams) { + return Forms.get({formId: $stateParams.formId}).$promise; + }], + }, + controller: 'SubmitFormController', + controllerAs: 'ctrl' + }).state('viewForm', { + url: '/forms/:formId/admin', + templateUrl: 'modules/forms/views/admin-form.client.view.html', + data: { + permissions: [ 'editForm' ] + }, + resolve: { + Forms: 'Forms', + myForm: ["Forms", "$stateParams", function (Forms, $stateParams) { + return Forms.get({formId: $stateParams.formId}).$promise; + }], + }, + controller: 'AdminFormController' + }).state('viewForm.configure', { + url: '/configure', + templateUrl: 'modules/forms/views/adminTabs/configure.html' + }).state('viewForm.design', { + url: '/design', + templateUrl: 'modules/forms/views/adminTabs/design.html' + }).state('viewForm.analyze', { + url: '/analyze', + templateUrl: 'modules/forms/views/adminTabs/analyze.html', + }).state('viewForm.create', { + url: '/create', + templateUrl: 'modules/forms/views/adminTabs/create.html' + }); + } +]); + +'use strict'; + +// Forms controller +angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm', '$http', '$uibModal', 'myForm', + function($rootScope, $scope, $stateParams, $state, Forms, CurrentForm, $http, $uibModal, myForm) { + + $scope = $rootScope; + $scope.animationsEnabled = true; + $scope.myform = myForm; + $rootScope.saveInProgress = false; + + CurrentForm.setForm($scope.myform); + + $scope.tabData = [ + { + heading: 'Create', + route: 'viewForm.create' + }, + { + heading: 'Design', + route: 'viewForm.design', + }, + { + heading: 'Configure', + route: 'viewForm.configure', + }, + { + heading: 'Analyze', + route: 'viewForm.analyze', + } + ]; + + $scope.setForm = function(form){ + $scope.myform = form; + }; + $rootScope.resetForm = function(){ + $scope.myform = Forms.get({ + formId: $stateParams.formId + }); + }; + + /* + ** DeleteModal Functions + */ + $scope.openDeleteModal = function(){ + $scope.deleteModal = $uibModal.open({ + animation: $scope.animationsEnabled, + templateUrl: 'myModalContent.html', + controller: 'AdminFormController', + resolve: { + myForm: function(){ + return $scope.myform; + } + } + }); + $scope.deleteModal.result.then(function (selectedItem) { + $scope.selected = selectedItem; + }, function () { + console.log('Modal dismissed at: ' + new Date()); + }); + }; + + + $scope.cancelDeleteModal = function(){ + 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) + .success(function(data, status, headers){ + console.log('form deleted successfully'); + + $state.go('listForms', {}, {reload: true}); + + }).error(function(error){ + console.log('ERROR: Form could not be deleted.'); + console.error(error); + }); + } + }; + + // Update existing Form + $scope.update = $rootScope.update = function(updateImmediately, cb){ + + var continueUpdate = true; + if(!updateImmediately){ + continueUpdate = !$rootScope.saveInProgress; + } + + //Update form **if we are not currently updating** or if **shouldUpdateNow flag is set** + if(continueUpdate){ + var err = null; + + if(!updateImmediately){ $rootScope.saveInProgress = true; } + + $scope.updatePromise = $http.put('/forms/'+$scope.myform._id, {form: $scope.myform}) + .then(function(response){ + $rootScope.myform = $scope.myform = response.data; + // console.log(response.data); + }).catch(function(response){ + console.log('Error occured during form UPDATE.\n'); + // console.log(response.data); + err = response.data; + }).finally(function() { + // console.log('finished updating'); + if(!updateImmediately){$rootScope.saveInProgress = false; } + + if( (typeof cb) === 'function'){ + cb(err); + } + }); + } + }; + + + } +]); +'use strict'; + +// Forms controller +angular.module('forms').controller('ListFormsController', ['$rootScope', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm', '$http', + function($rootScope, $scope, $stateParams, $state, Forms, CurrentForm, $http) { + + $scope = $rootScope; + $scope.forms = {}; + $scope.showCreateModal = false; + + // Return all user's Forms + $scope.findAll = function() { + Forms.query(function(_forms){ + $scope.myforms = _forms; + }); + }; + + //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(){ + // console.log($scope.forms.createForm); + + 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){ + console.log('new form created'); + // 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){ + console.log('form deleted successfully'); + $scope.myforms.splice(form_index, 1); + }).error(function(error){ + console.log('ERROR: Form could not be deleted.'); + console.error(error); + }); + }; + } +]); +'use strict'; + +// SubmitForm controller +angular.module('forms').controller('SubmitFormController', ['$scope', '$rootScope', '$state', 'myForm', 'Auth', + function($scope, $rootScope, $state, myForm, Auth) { + $scope.authentication = Auth; + $scope.myform = myForm; + + if(!$scope.myform.isLive){ + // Show navbar if form is not public AND user IS loggedin + if($scope.authentication.isAuthenticated()){ + $scope.hideNav = $rootScope.hideNav = false; + } + // Redirect if form is not public user IS NOT loggedin + else { + $scope.hideNav = $rootScope.hideNav = true; + $state.go('access_denied'); + } + }else{ + $scope.hideNav = $rootScope.hideNav = true; + } + + } +]); +'use strict'; + + +function removeDateFieldsFunc(o) { + var clone = _.clone(o); + function eachObject(v,k){ + + if(k === 'lastModified' || k === 'created'){ + delete clone[i][k]; + } + } + + for(var i=0; i FormFields + $scope.oscarFieldsLeft = function(field_id){ + + if($scope.myform && $scope.myform.plugins.oscarhost.settings.validFields.length > 0){ + if(!$scope.myform.plugins.oscarhost.settings.fieldMap) $scope.myform.plugins.oscarhost.settings.fieldMap = {}; + + var oscarhostFields = $scope.myform.plugins.oscarhost.settings.validFields; + var currentFields = _($scope.myform.plugins.oscarhost.settings.fieldMap).invert().keys().value(); + + if( $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id) ){ + currentFields = _(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id]); + } + + //Get all oscarhostFields that haven't been mapped to a formfield + return _(oscarhostFields).difference(currentFields).value(); + } + return []; + }; + + /* + ** 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(modifyForm, fieldType){ + + // incr field_id counter + $scope.addField.lastAddedID++; + var fieldTitle; + + 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; + } + } + var newField = { + title: fieldTitle, + fieldType: fieldType, + fieldValue: '', + required: true, + disabled: false, + deletePreserved: false + }; + // console.log('\n\n---------\nAdded field CLIENT'); + // console.log(newField); + // newField._id = _.uniqueId(); + + // put newField into fields array + if(modifyForm){ + $scope.myform.form_fields.push(newField); + } + return newField; + }; + + // Delete particular field on button click + $scope.deleteField = function (field_index){ + + //Delete field from field map + var currFieldId = $scope.myform.form_fields[field_index]._id; + if($scope.myform.hasOwnProperty('plugins.oscarhost.baseUrl')) delete $scope.myform.plugins.oscarhost.settings.fieldMap[currFieldId]; + + //Delete field + $scope.myform.form_fields.splice(field_index, 1); + }; + $scope.duplicateField = function (field_index){ + var currField = _.cloneDeep($scope.myform.form_fields[field_index]); + currField._id = 'cloned'+_.uniqueId(); + currField.title += ' copy'; + + //Insert field at selected index + $scope.myform.form_fields.splice(field_index+1, 0, currField); + }; + + + /* + ** startPage Button Methods + */ + + // 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; + console.log(currID); + + if(currID === button._id){ + $scope.myform.startPage.buttons.splice(i, 1); + break; + } + } + }; + + + /* + ** Field Option Methods + */ + + // add new option to the field + $scope.addOption = function(field_index){ + var currField = $scope.myform.form_fields[field_index]; + console.log(field_index); + console.log(currField); + + if(currField.fieldType === 'checkbox' || currField.fieldType === 'dropdown' || currField.fieldType === 'radio'){ + if(!currField.fieldOptions) $scope.myform.form_fields[field_index].fieldOptions = []; + + var lastOptionID = 0; + + if(currField.fieldOptions[currField.fieldOptions.length-1]){ + lastOptionID = currField.fieldOptions[currField.fieldOptions.length-1].option_id; + } + + // new option's id + var option_id = lastOptionID + 1; + + var newOption = { + 'option_id' : Math.floor(100000*Math.random()), + 'option_title' : 'Option '+lastOptionID, + 'option_value' : 'Option ' +lastOptionID, + }; + + // put new option into fieldOptions array + $scope.myform.form_fields[field_index].fieldOptions.push(newOption); + } + }; + + // delete particular option + $scope.deleteOption = function (field_index, option){ + var currField = $scope.myform.form_fields[field_index]; + + if(currField.fieldType === 'checkbox' || currField.fieldType === 'dropdown' || currField.fieldType === 'radio'){ + for(var i = 0; i < currField.fieldOptions.length; i++){ + if(currField.fieldOptions[i].option_id === option.option_id){ + + $scope.myform.form_fields[field_index].fieldOptions.splice(i, 1); + break; + + } + } + } + }; + + // 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; + } + }; + + }], + + }; + } +]); + +'use strict'; + +angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', '$http', + function ($rootScope, $http) { + return { + templateUrl: 'modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html', + restrict: 'E', + scope: { + myform:'=', + user:'=' + }, + controller: ["$scope", function($scope){ + $scope.table = { + masterChecker: false, + rows: [] + }; + + /* + ** Table Functions + */ + $scope.isAtLeastOneChecked = function(){ + for(var i=0; i<$scope.table.rows.length; i++){ + if($scope.table.rows[i].selected) return true; + } + return false; + }; + $scope.toggleAllCheckers = function(){ + for(var i=0; i<$scope.table.rows.length; i++){ + $scope.table.rows[i].selected = $scope.table.masterChecker; + } + }; + $scope.toggleObjSelection = function($event, description) { + $event.stopPropagation(); + }; + $scope.rowClicked = function(row_index) { + $scope.table.rows[row_index].selected = !$scope.table.rows[row_index].selected; + }; + + /* + * Form Submission Methods + */ + + //Fetch and display submissions of Form + $scope.initFormSubmissions = function(){ + $http.get('/forms/'+$scope.myform._id+'/submissions') + .success(function(data, status, headers){ + + var _tmpSubFormFields, + defaultFormFields = _.cloneDeep($scope.myform.form_fields); + + // console.log('before textField2: '+data[0].form_fields[1].fieldValue); + + //Iterate through form's submissions + for(var i=0; i', + restrict: 'E', + scope: { + typeName: '@' + }, + controller: ["$scope", function($scope){ + var iconTypeMap = { + 'textfield': 'fa fa-pencil-square-o', + 'dropdown': 'fa fa-th-list', + 'date': 'fa fa-calendar', + 'checkbox': 'fa fa-check-square-o', + 'radio': 'fa fa-dot-circle-o', + 'email': 'fa fa-envelope-o', + 'textarea': 'fa fa-pencil-square', + 'legal': 'fa fa-legal', + 'file': 'fa fa-cloud-upload', + 'rating': 'fa fa-star-half-o', + 'link': 'fa fa-link', + 'scale': 'fa fa-sliders', + 'stripe': 'fa fa-credit-card', + 'statement': 'fa fa-quote-left', + 'yes_no': 'fa fa-toggle-on', + 'number': 'fa fa-slack' + }; + $scope.typeIcon = iconTypeMap[$scope.typeName]; + }], + }; +}); +'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('forms').directive('fieldDirective', ['$http', '$compile', '$rootScope', '$templateCache', + function($http, $compile, $rootScope, $templateCache) { + + var getTemplateUrl = function(fieldType) { + var type = fieldType; + var templateUrl = 'modules/forms/views/directiveViews/field/'; + var supported_fields = [ + 'textfield', + 'textarea', + 'date', + 'dropdown', + 'hidden', + 'password', + 'radio', + 'legal', + 'statement', + 'rating', + 'yes_no', + 'number', + 'natural' + ]; + if (__indexOf.call(supported_fields, type) >= 0) { + templateUrl = templateUrl+type+'.html'; + } + + return $templateCache.get('../public/'+templateUrl); + }; + + return { + template: '
{{field.title}}
', + restrict: 'E', + scope: { + field: '=', + required: '&', + design: '=', + index: '=', + }, + link: function(scope, element) { + scope.setActiveField = $rootScope.setActiveField; + + //Set format only if field is a date + if(scope.field.fieldType === 'date'){ + scope.dateOptions = { + changeYear: true, + changeMonth: true, + altFormat: 'mm/dd/yyyy', + yearRange: '1900:-0', + defaultDate: 0, + }; + } + + var fieldType = scope.field.fieldType; + + if(scope.field.fieldType === 'number' || scope.field.fieldType === 'textfield' || scope.field.fieldType === 'email' || scope.field.fieldType === 'link'){ + switch(scope.field.fieldType){ + case 'textfield': + scope.field.input_type = 'text'; + break; + case 'email': + scope.field.input_type = 'email'; + scope.field.placeholder = 'joesmith@example.com'; + break; + case 'number': + scope.field.input_type = 'number'; + break; + default: + scope.field.input_type = 'url'; + scope.field.placeholder = 'http://example.com'; + break; + } + fieldType = 'textfield'; + } + var template = getTemplateUrl(fieldType); + element.html(template).show(); + $compile(element.contents())(scope); + }, + }; +}]); + +'use strict'; + +angular.module('forms').directive('onEnterKey', ['$rootScope', function($rootScope){ + return { + restrict: 'A', + link: function($scope, $element, $attrs) { + $element.bind('keydown keypress', function(event) { + var keyCode = event.which || event.keyCode; + console.log($attrs.onEnterKey); + if(keyCode === 13) { + $rootScope.$apply(function() { + $rootScope.$eval($attrs.onEnterKey); + }); + + event.preventDefault(); + } + }); + } + }; +}]); + +'use strict'; + +angular.module('forms').directive('onFinishRender', ["$rootScope", "$timeout", function ($rootScope, $timeout) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + + //Don't do anything if we don't have a ng-repeat on the current element + if(!element.attr('ng-repeat') && !element.attr('data-ng-repeat')){ + return; + } + + var broadcastMessage = attrs.onFinishRender || 'ngRepeat'; + + if(scope.$first && !scope.$last) { + scope.$evalAsync(function () { + $rootScope.$broadcast(broadcastMessage+' Started'); + }); + }else if(scope.$last) { + scope.$evalAsync(function () { + // console.log(broadcastMessage+'Finished'); + $rootScope.$broadcast(broadcastMessage+' Finished'); + }); + } + } + }; +}]); + +'use strict'; + +angular.module('forms').directive('submitFormDirective', ['$http', 'TimeCounter', '$filter', '$rootScope', 'Auth', + function ($http, TimeCounter, $filter, $rootScope, Auth) { + return { + templateUrl: 'modules/forms/views/directiveViews/form/submit-form.client.view.html', + restrict: 'E', + scope: { + myform:'=' + }, + controller: ["$document", "$window", "$scope", function($document, $window, $scope){ + $scope.authentication = $rootScope.authentication; + $scope.noscroll = false; + $scope.forms = {}; + $scope.form_fields_count = $scope.myform.visible_form_fields.filter(function(field){ + if(field.fieldType === 'statement' || field.fieldType === 'rating'){ + return false; + } + return true; + }).length; + + $scope.reloadForm = function(){ + //Reset Form + $scope.myform.submitted = false; + $scope.myform.form_fields = _.chain($scope.myform.visible_form_fields).map(function(field){ + field.fieldValue = ''; + return field; + }).value(); + + $scope.loading = false; + $scope.error = ''; + + $scope.selected = { + _id: '', + index: 0 + }; + $scope.setActiveField($scope.myform.visible_form_fields[0]._id, 0, false); + + console.log($scope.selected); + //Reset Timer + TimeCounter.restartClock(); + }; + + $window.onscroll = function(){ + $scope.scrollPos = document.body.scrollTop || document.documentElement.scrollTop || 0; + var elemBox = document.getElementsByClassName('activeField')[0].getBoundingClientRect(); + $scope.fieldTop = elemBox.top; + $scope.fieldBottom = elemBox.bottom; + + //console.log($scope.forms.myForm); + + if(!$scope.noscroll){ + //Focus on submit button + if( $scope.selected.index === $scope.myform.form_fields.length-1 && $scope.fieldBottom < 200){ + var field_index = $scope.selected.index+1; + var field_id = 'submit_field'; + $scope.setActiveField(field_id, field_index, false); + } + //Focus on field above submit button + else if($scope.selected.index === $scope.myform.form_fields.length){ + if($scope.fieldTop > 200){ + var field_index = $scope.selected.index-1; + var field_id = $scope.myform.form_fields[field_index]._id; + $scope.setActiveField(field_id, field_index, false); + } + }else if( $scope.fieldBottom < 0){ + var field_index = $scope.selected.index+1; + var field_id = $scope.myform.form_fields[field_index]._id; + $scope.setActiveField(field_id, field_index, false); + }else if ( $scope.selected.index !== 0 && $scope.fieldTop > 0) { + var field_index = $scope.selected.index-1; + var field_id = $scope.myform.form_fields[field_index]._id; + $scope.setActiveField(field_id, field_index, false); + } + //console.log('$scope.selected.index: '+$scope.selected.index); + //console.log('scroll pos: '+$scope.scrollPos+' fieldTop: '+$scope.fieldTop+' fieldBottom: '+$scope.fieldBottom); + $scope.$apply(); + } + }; + + /* + ** Field Controls + */ + $scope.setActiveField = $rootScope.setActiveField = function(field_id, field_index, animateScroll) { + if($scope.selected === null || $scope.selected._id === field_id){ + console.log('not scrolling'); + console.log($scope.selected); + return; + } + console.log('field_id: '+field_id); + console.log('field_index: '+field_index); + console.log($scope.selected); + + $scope.selected._id = field_id; + $scope.selected.index = field_index; + + if(animateScroll){ + $scope.noscroll=true; + setTimeout(function() { + $document.scrollToElement(angular.element('.activeField'), -10, 200).then(function(){ + $scope.noscroll = false; + document.querySelectorAll('.activeField .focusOn')[0].focus(); + }); + }, 20); + } + }; + + $rootScope.nextField = $scope.nextField = function(){ + console.log('nextfield'); + //console.log($scope.selected.index); + //console.log($scope.myform.form_fields.length-1); + if($scope.selected.index < $scope.myform.form_fields.length-1){ + var selected_index = $scope.selected.index+1; + var selected_id = $scope.myform.form_fields[selected_index]._id; + $rootScope.setActiveField(selected_id, selected_index, true); + } else if($scope.selected.index === $scope.myform.form_fields.length-1) { + var selected_index = $scope.selected.index+1; + var selected_id = 'submit_field'; + $rootScope.setActiveField(selected_id, selected_index, true); + } + }; + + $rootScope.prevField = $scope.prevField = function(){ + if($scope.selected.index > 0){ + var selected_index = $scope.selected.index - 1; + var selected_id = $scope.myform.form_fields[selected_index]._id; + $scope.setActiveField(selected_id, selected_index, true); + } + }; + + /* + ** Form Display Functions + */ + $scope.exitStartPage = function(){ + $scope.myform.startPage.showStart = false; + if($scope.myform.form_fields.length > 0){ + $scope.selected._id = $scope.myform.form_fields[0]._id; + } + }; + + $scope.submitForm = function(){ + var _timeElapsed = TimeCounter.stopClock(); + $scope.loading = true; + var form = _.cloneDeep($scope.myform); + form.timeElapsed = _timeElapsed; + + form.percentageComplete = $filter('formValidity')($scope.myform)/$scope.myform.visible_form_fields.length*100; + delete form.visible_form_fields; + + $scope.submitPromise = $http.post('/forms/'+$scope.myform._id, form) + .success(function(data, status, headers){ + console.log('form submitted successfully'); + setTimeout(function() { + $scope.myform.submitted = true; + $scope.loading = false; + }, 20); + }) + .error(function(error){ + setTimeout(function(){ + $scope.loading = false; + console.log(error); + $scope.error = error.message; + }, 20); + }); + }; + + //Load our form when the page is ready + //angular.element(document).ready(function() { + $scope.reloadForm(); + //}); + + }] + }; + } +]); + +'use strict'; + +//Forms service used for communicating with the forms REST endpoints +angular.module('forms').service('CurrentForm', + function(){ + + //Private variables + var _form = {}; + + //Public Methods + this.getForm = function() { + return _form; + }; + this.setForm = function(form) { + _form = form; + }; + } +); +'use strict'; + +//TODO: DAVID: URGENT: Make this a $resource that fetches valid field types from server +angular.module('forms').service('FormFields', [ + function() { + this.types = [ + { + name : 'textfield', + value : 'Short Text' + }, + { + name : 'email', + value : 'Email' + }, + { + name : 'radio', + value : 'Multiple Choice' + }, + { + name : 'dropdown', + value : 'Dropdown' + }, + { + name : 'date', + value : 'Date' + }, + { + name : 'textarea', + value : 'Paragraph Text' + }, + { + name : 'yes_no', + value : 'Yes/No' + }, + { + name : 'legal', + value : 'Legal' + }, + // { + // name : 'sig', + // value : 'Signature' + // }, + // { + // name : 'file', + // value : 'File Upload' + // }, + { + name : 'rating', + value : 'Rating' + }, + { + name : 'link', + value : 'Link' + }, + { + name : 'number', + value : 'Numbers' + }, + // { + // name : 'scale', + // value : 'Opinion Scale' + // }, + // { + // name : 'stripe', + // value : 'Payment' + // }, + { + name : 'statement', + value : 'Statement' + } + ]; + } + +]); + +'use strict'; + +//Forms service used for communicating with the forms REST endpoints +angular.module('forms').factory('Forms', ['$resource', + function($resource) { + return $resource('/forms/:formId', { + formId: '@_id' + }, { + 'query' : { + method: 'GET', + isArray: true, + //DAVID: TODO: Do we really need to get visible_form_fields for a Query? + // transformResponse: function(data, header) { + // var forms = angular.fromJson(data); + // angular.forEach(forms, function(form, idx) { + // form.visible_form_fields = _.filter(form.form_fields, function(field){ + // return (field.deletePreserved === false); + // }); + // }); + // return forms; + // } + }, + 'get' : { + method: 'GET', + transformResponse: function(data, header) { + var form = angular.fromJson(data); + console.log(form); + + form.visible_form_fields = _.filter(form.form_fields, function(field){ + return (field.deletePreserved === false); + }); + return form; + } + }, + 'update': { + method: 'PUT' + }, + 'save': { + method: 'POST' + } + }); + } +]); +'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('forms').service('TimeCounter', [ + function(){ + var _startTime, _endTime, that=this; + + this.timeSpent = 0; + + this.restartClock = function(){ + _startTime = Date.now(); + _endTime = _startTime; + // console.log('Clock Started'); + }; + + this.stopClock = function(){ + if(_startTime){ + _endTime = Date.now(); + that.timeSpent = Math.abs(_endTime.valueOf() - _startTime.valueOf())/1000; + // console.log('Clock Ended'); + return that.timeSpent; + }else{ + return new Error('Clock has not been started'); + } + }; + + this.clockStarted = function(){ + return !!this._startTime; + }; + + } +]); +'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'){ + console.log('intercepted rejection of ', response.config.url, response.status); + 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(); + + // console.log(Auth.ensureHasCurrentUser(User)); + + 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('sigin', {reload: true}); + }); + } + + return deferred.promise; + }; + checkLoggedin.$inject = ["$q", "$timeout", "$state", "User", "Auth"]; + + // 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', { + url: '/signup', + templateUrl: 'modules/users/views/authentication/signup.client.view.html' + }). + state('signup-success', { + url: '/signup-success', + templateUrl: 'modules/users/views/authentication/signup-success.client.view.html' + }). + state('signin', { + url: '/signin', + templateUrl: 'modules/users/views/authentication/signin.client.view.html' + }). + state('access_denied', { + url: '/access_denied', + templateUrl: 'modules/users/views/authentication/access-denied.client.view.html' + }). + + state('resendVerifyEmail', { + url: '/verify', + templateUrl: 'modules/users/views/verify/resend-verify-email.client.view.html' + }). + state('verify', { + url: '/verify/:token', + templateUrl: 'modules/users/views/verify/verify-account.client.view.html' + }). + + state('forgot', { + url: '/password/forgot', + templateUrl: 'modules/users/views/password/forgot-password.client.view.html' + }). + state('reset-invalid', { + url: '/password/reset/invalid', + templateUrl: 'modules/users/views/password/reset-password-invalid.client.view.html' + }). + state('reset-success', { + url: '/password/reset/success', + templateUrl: 'modules/users/views/password/reset-password-success.client.view.html' + }). + state('reset', { + url: '/password/reset/:token', + templateUrl: 'modules/users/views/password/reset-password.client.view.html' + }); + } +]); +'use strict'; + +angular.module('users').controller('AuthenticationController', ['$scope', '$location', '$state', '$rootScope', 'User', 'Auth', + function($scope, $location, $state, $rootScope, User, Auth) { + + $scope = $rootScope; + $scope.credentials = {}; + $scope.error = ''; + + $scope.signin = function() { + $scope.credentials.email = $scope.credentials.username; + User.login($scope.credentials).then( + function(response) { + Auth.login(response); + $scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User); + + 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.log('loginError: '+error); + } + ); + }; + + $scope.signup = function() { + console.log($scope.credentials); + User.signup($scope.credentials).then( + function(response) { + console.log('signup-success'); + $state.go('signup-success'); + }, + function(error) { + console.log('Error: '); + console.log(error); + if(error) { + $scope.error = error; + console.log(error); + }else { + console.log('No response received'); + } + } + ); + }; + + } +]); + +'use strict'; + +angular.module('users').controller('PasswordController', ['$scope', '$stateParams', '$state', 'User', + function($scope, $stateParams, $state, User) { + $scope.error = ''; + + // Submit forgotten password account id + $scope.askForPasswordReset = function() { + User.askForPasswordReset($scope.credentials).then( + function(response){ + $scope.success = response.message; + $scope.credentials = null; + }, + function(error){ + $scope.error = error; + $scope.credentials = null; + } + ); + }; + + // Change user password + $scope.resetUserPassword = function() { + $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.passwordDetails = null; + + // And redirect to the index page + $state.go('reset-success'); + }, + function(error){ + $scope.error = error.message || error; + $scope.passwordDetails = null; + } + ); + }; + } +]); +'use strict'; + +angular.module('users').controller('SettingsController', ['$scope', '$rootScope', '$http', '$state', 'Users', + function($scope, $rootScope, $http, $state, Users) { + $scope.user = $rootScope.user; + + // Check if there are additional accounts + $scope.hasConnectedAdditionalSocialAccounts = function(provider) { + for (var i in $scope.user.additionalProvidersData) { + return true; + } + return false; + }; + + // 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.user = response; + }).error(function(response) { + $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.user = response; + }, function(response) { + $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.passwordDetails = null; + }).error(function(response) { + $scope.error = response.message; + }); + }; + + } +]); +'use strict'; + +angular.module('users').controller('VerifyController', ['$scope', '$state', '$rootScope', 'User', 'Auth', '$stateParams', + function($scope, $state, $rootScope, User, Auth, $stateParams) { + + $scope.isResetSent = false; + $scope.credentials = {}; + $scope.error = ''; + + // Submit forgotten password account id + $scope.resendVerifyEmail = function() { + // console.log($scope.credentials); + // console.log($scope.credentials.email); + User.resendVerifyEmail($scope.credentials.email).then( + function(response){ + console.log(response); + $scope.success = response.message; + $scope.credentials = null; + $scope.isResetSent = true; + }, + function(error){ + $scope.error = error; + $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){ + console.log('Success: '+response.message); + $scope.success = response.message; + $scope.isResetSent = true; + $scope.credentials.email = null; + }, + function(error){ + console.log('Error: '+error.message); + $scope.isResetSent = false; + $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) { + console.log('Using local current user.'); + console.log(service._currentUser); + return service._currentUser; + } + else if ($window.user){ + console.log('Using cached current user.'); + console.log($window.user); + service._currentUser = $window.user; + return service._currentUser; + } + else{ + console.log('Fetching current user from the server.'); + 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; + console.log('User.getCurrent() err', response); + 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).success(function(response) { + deferred.resolve(response); + }).error(function(error) { + deferred.reject(error.message || error); + }); + + return deferred.promise; + }, + logout: function() { + + var deferred = $q.defer(); + $http.get('/auth/signout').success(function(response) { + deferred.resolve(null); + }).error(function(error) { + deferred.reject(error.message || error); + }); + + return deferred.promise; + }, + signup: function(credentials) { + + var deferred = $q.defer(); + $http.post('/auth/signup', credentials).success(function(response) { + // If successful we assign the response to the global user model + deferred.resolve(response); + }).error(function(error) { + deferred.reject(error.message || error); + }); + + return deferred.promise; + }, + + resendVerifyEmail: function(_email) { + + var deferred = $q.defer(); + $http.post('/auth/verify', {email: _email}).success(function(response) { + deferred.resolve(response); + }).error(function(error) { + deferred.reject(error.message || error); + }); + + 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).success(function(response) { + deferred.resolve(response); + }).error(function(error) { + deferred.reject(error); + }); + + return deferred.promise; + }, + + resetPassword: function(passwordDetails, token) { + + var deferred = $q.defer(); + $http.get('/auth/password/'+token, passwordDetails).success(function(response) { + deferred.resolve(); + }).error(function(error) { + deferred.reject(error.message || error); + }); + + return deferred.promise; + }, + + // Submit forgotten password account id + askForPasswordReset: function(credentials) { + + var deferred = $q.defer(); + $http.post('/auth/forgot', credentials).success(function(response) { + // Show user success message and clear form + deferred.resolve(response); + }).error(function(error) { + // Show user error message + deferred.reject(error.message || error); + }); + + 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' + } + }); + } +]); \ No newline at end of file diff --git a/public/dist/application.min.css b/public/dist/application.min.css new file mode 100644 index 00000000..51352369 --- /dev/null +++ b/public/dist/application.min.css @@ -0,0 +1,4 @@ +.image-background,.opacity-background{position:fixed;height:100%;width:100%;top:0;left:0}body{overflow-x:hidden}.navbar-inverse{background-color:#fafafa;border:0}.navbar .navbar-brand{font-size:1.6em;font-weight:900;color:#ff8383}.navbar .navbar-brand:hover,.navbar .navbar-brand:visited{color:#FA787E}.navbar li.dropdown a.dropdown-toggle:hover>*{color:#000}.navbar li.dropdown.open a.dropdown-toggle:hover>*{color:#fff}.navbar .navbar-brand span{text-decoration:underline}.admin-form .panel-heading a:hover,.current-fields .tool-panel>.panel-default .panel-heading a:hover,.footer-basic-centered .footer-links a,.undecorated-link:hover{text-decoration:none}.nav.navbar-nav.navbar-right li{padding-right:20px}.navbar li.dropdown a.dropdown-toggle>*,.navbar-inverse .navbar-nav>li>a{color:#838383}.navbar li.dropdown.open a.dropdown-toggle>*,.navbar-inverse .navbar-nav .active>a,.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{background-color:#838383;color:#fff!important}.navbar-inverse .navbar-toggle{background-color:#ddd;border:none}.navbar-inverse .navbar-collapse{border:none}.ng-cloak,.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.browsehappy.jumbotron.hide,body.ng-cloak{display:block}section.hero-section{width:100%}section.hero-section .jumbotron{background-color:transparent;color:#fff}.image-background{z-index:-98;background-image:url(http://yourplaceandmine.ie/wp-content/uploads/2014/09/Daingean-meeting-048_13-1080x675.jpg);background-repeat:no-repeat;background-position:0 50%;background-size:cover}.opacity-background{background-color:#000;background-color:rgba(0,0,0,.5);z-index:-97}section.hero-section .jumbotron .signup-btn{background-color:#FA787E;border:none;font-size:2em;padding:.3em .9em;color:#fff}.row-height{display:table;table-layout:fixed;height:100%;width:100%}.col-height{display:table-cell;float:none;height:100%}.col-top{vertical-align:top}.col-middle{vertical-align:middle}.col-bottom{vertical-align:bottom}@media (min-width:480px){.row-xs-height{display:table;table-layout:fixed;height:100%;width:100%}.col-xs-height{display:table-cell;float:none;height:100%}.col-xs-top{vertical-align:top}.col-xs-middle{vertical-align:middle}.col-xs-bottom{vertical-align:bottom}}@media (min-width:768px){.row-sm-height{display:table;table-layout:fixed;height:100%;width:100%}.col-sm-height{display:table-cell;float:none;height:100%}.col-sm-top{vertical-align:top}.col-sm-middle{vertical-align:middle}.col-sm-bottom{vertical-align:bottom}}@media (min-width:992px){.row-md-height{display:table;table-layout:fixed;height:100%;width:100%}.col-md-height{display:table-cell;float:none;height:100%}.col-md-top{vertical-align:top}.col-md-middle{vertical-align:middle}.col-md-bottom{vertical-align:bottom}}@media (min-width:1200px){.row-lg-height{display:table;table-layout:fixed;height:100%;width:100%}.col-lg-height{display:table-cell;float:none;height:100%}.col-lg-top{vertical-align:top}.col-lg-middle{vertical-align:middle}.col-lg-bottom{vertical-align:bottom}}.footer-basic-centered{background-color:#292c2f;box-shadow:0 1px 1px 0 rgba(0,0,0,.12);box-sizing:border-box;width:100%;text-align:center;font:400 18px sans-serif;padding:45px;margin-top:80px}.footer-basic-centered .footer-company-motto{color:#8d9093;font-size:24px;margin:0}.footer-basic-centered .footer-company-name{color:#8f9296;font-size:14px;margin:0}.footer-basic-centered .footer-links{list-style:none;font-weight:700;color:#fff;padding:35px 0 23px;margin:0}.footer-basic-centered .footer-links a{display:inline-block;color:inherit}@media (max-width:600px){.footer-basic-centered{padding:35px}.footer-basic-centered .footer-company-motto{font-size:18px}.footer-basic-centered .footer-company-name{font-size:12px}.footer-basic-centered .footer-links{font-size:14px;padding:25px 0 20px}.footer-basic-centered .footer-links a{line-height:1.8}}/*! + * "Fork me on GitHub" CSS ribbon v0.1.1 | MIT License + * https://github.com/simonwhitaker/github-fork-ribbon-css +*/.github-fork-ribbon{position:absolute;padding:2px 0;background-color:#a00;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0)),to(rgba(0,0,0,.15)));background-image:-webkit-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-moz-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-ms-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:-o-linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,.15));background-image:linear-gradient(to bottom,rgba(0,0,0,0),rgba(0,0,0,.15));-webkit-box-shadow:0 2px 3px 0 rgba(0,0,0,.5);-moz-box-shadow:0 2px 3px 0 rgba(0,0,0,.5);box-shadow:0 2px 3px 0 rgba(0,0,0,.5);font:700 13px "Helvetica Neue",Helvetica,Arial,sans-serif;z-index:9999;pointer-events:auto}.github-fork-ribbon a,.github-fork-ribbon a:hover{color:#fff;text-decoration:none;text-shadow:0 -1px rgba(0,0,0,.5);text-align:center;width:200px;line-height:20px;display:inline-block;padding:2px 0;border-width:1px 0;border-style:dotted;border-color:#fff;border-color:rgba(255,255,255,.7)}.github-fork-ribbon-wrapper{width:150px;height:150px;position:absolute;overflow:hidden;top:0;z-index:9998;pointer-events:none}.github-fork-ribbon-wrapper.fixed{position:fixed}.github-fork-ribbon-wrapper.left{left:0}.github-fork-ribbon-wrapper.right{right:0}.github-fork-ribbon-wrapper.left-bottom{position:fixed;top:inherit;bottom:0;left:0}.github-fork-ribbon-wrapper.right-bottom{position:fixed;top:inherit;bottom:0;right:0}.github-fork-ribbon-wrapper.right .github-fork-ribbon{top:42px;right:-43px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.github-fork-ribbon-wrapper.left .github-fork-ribbon{top:42px;left:-43px;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.github-fork-ribbon-wrapper.left-bottom .github-fork-ribbon{top:80px;left:-43px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.github-fork-ribbon-wrapper.right-bottom .github-fork-ribbon{top:80px;right:-43px;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);-o-transform:rotate(-45deg);transform:rotate(-45deg)}.custom-select{position:relative;display:block;padding:0}.custom-select select{width:100%;margin:0;background:0 0;border:1px solid transparent;border-radius:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;appearance:none;-webkit-appearance:none;-moz-appearance:none;font-size:1em;font-family:helvetica,sans-serif;font-weight:700;color:#444;padding:.6em 1.9em .5em .8em;line-height:1.3}.custom-select option,.modal-header{font-weight:400}.custom-select::after{content:"";position:absolute;width:9px;height:8px;top:50%;right:1em;margin-top:-4px;background-image:url(http://filamentgroup.com/files/select-arrow.png);background-repeat:no-repeat;background-size:100%;z-index:2;pointer-events:none}.container.admin-form,section.content>section>section.container{margin-top:70px}.custom-select:hover{border:1px solid #888}.custom-select select:focus{outline:0;box-shadow:0 0 1px 3px rgba(180,222,250,1);background-color:transparent;color:#222;border:1px solid #aaa}.custom-select::after,x:-o-prefocus{display:none}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.custom-select select::-ms-expand{display:none}.custom-select select:focus::-ms-value{background:0 0;color:#222}}.custom-select select:-moz-focusring{color:transparent;text-shadow:0 0 0 #000}.panel-default.startPage{border-style:dashed;border-color:#a9a9a9;border-width:3px}.busy-updating-wrapper{text-align:center;font-size:20px;position:fixed;bottom:0;right:55px;z-index:1}.busy-submitting-wrapper{position:fixed;top:50%;left:0;right:0;bottom:0}.form-item,.letter,div.form-fields{position:relative}.dropzone h4.panel-title{height:17px;overflow:hidden}.public-form input,.public-form textarea{background-color:rgba(0,0,0,0);border:2px dashed #ddd!important}.public-form input:focus,.public-form textarea:focus{border:2px dashed #ddd!important;outline:0}.public-form input.no-border,.public-form textarea.no-border{border:none!important}section.content p.breakwords{word-break:break-all}.btn{border:1px solid #c6c6c6}.btn[type=submit]{font-size:1.5em;padding:.35em 1.2em}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;font-size:18px}.input-block{display:block;width:100%}.modal-footer input[type=text]{min-height:34px;padding:7px 8px;font-size:13px;color:#333;vertical-align:middle;background-color:#fff;background-repeat:no-repeat;background-position:right 8px center;border:1px solid #ccc;border-radius:3px;box-shadow:inset 0 1px 2px rgba(0,0,0,.075)}.modal-footer input[type=text]:focus{outline:0}.modal-body>.modal-body-alert{color:#796620;background-color:#f8eec7;border-color:#f2e09a;margin:-16px -15px 15px;padding:10px 15px;border-style:solid;border-width:1px 0}div.form-fields{padding-top:35vh}.letter{display:-moz-inline-stack;display:inline-block;vertical-align:top;zoom:1;width:16px;padding:0;height:17px;font-size:12px;line-height:19px;border:1px solid #000;border:1px solid rgba(0,0,0,.2);margin-right:7px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;text-align:center;font-weight:700}div.form-submitted>.field.row{padding-bottom:2%;margin-top:35vh}div.form-submitted>.field.row>div{font-size:1.7em}form .accordion-edit{width:inherit}.ui-datepicker.ui-widget{z-index:99!important}form .row.field{padding:1em 0 0;width:inherit}form .row.field>.field-title{margin-top:.5em;font-size:1.2em;padding-bottom:1.8em;width:inherit}form .row.field>.field-input{font-size:1.4em;color:#777}form.submission-form .row.field.statement>.field-title{font-size:1.7em}form.submission-form .row.field.statement>.field-input{font-size:1em;color:#ddd}form.submission-form .select.radio>.field-input input,form.submission-form .select>.field-input input{width:20%}form.submission-form .field.row.radio .btn.activeBtn{background-color:#000!important;background-color:rgba(0,0,0,.7)!important;color:#fff}form.submission-form .field.row.radio .btn{margin-right:1.2em}form.submission-form .select>.field-input .btn{text-align:left;margin-bottom:.7em}form.submission-form .select>.field-input .btn>span{font-size:1.1em}form .field-input>textarea{padding:.45em .9em;width:100%;line-height:160%}form .field-input>input.hasDatepicker{padding:.45em .9em;width:50%;line-height:160%}form .field-input>input.text-field-input{padding:.45em .9em;width:100%;line-height:160%}form .required-error{color:#ddd;font-size:.8em}form .row.field.dropdown>.field-input input{height:34px;border-width:0 0 2px;border-radius:5px}form .row.field.dropdown>.field-input input:focus{border:none}form .row.field.dropdown>.field-input .ui-select-match{border:0 solid grey;border-width:0 0 2px;border-radius:5px}form .dropdown>.field-input .ui-select-choices-row-inner{border-radius:3px;margin:5px;padding:10px;background-color:rgba(0,0,0,.05)}form .dropdown>.field-input .ui-select-choices-row-inner.active,form .dropdown>.field-input .ui-select-choices-row-inner.active:focus{background-color:rgba(0,0,0,.1)}.config-form{max-width:100%}.config-form>.row{padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}div.config-form .row.field{padding-top:1.5em}div.config-form>.row>.container:nth-of-type(odd){border-right:1px #ddd solid}div.config-form.design>.row>.container:nth-of-type(odd){border-right:none}div.config-form .row>.field-input{padding-left:.1em}div.config-form .row>.field-input label{padding-left:1.3em;display:block}.admin-form>.page-header{padding-bottom:0;margin-bottom:40px}.admin-form>.page-header h1{margin-bottom:0;margin-top:0}.admin-form>.page-header>.col-xs-3{padding-top:1.4em}.admin-form .form-controls .row{padding:5px}.admin-form .page-header{border:none}.admin-form .tab-content{padding-top:3em}.admin-form .panel-heading{background-color:#f1f1f1}.admin-form .panel-heading:hover{background-color:#fff;cursor:pointer}.current-fields .panel-body .row.description textarea,.current-fields .panel-body .row.question input[type=text]{width:100%}.current-fields .panel-body .row.options input[type=text]{width:80%}.current-fields .tool-panel>.panel-default:hover{border-color:#9d9d9d;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading{background-color:#fff;color:#9d9d9d!important}.current-fields .tool-panel>.panel-default .panel-heading:hover{background-color:#eee;color:#000!important;cursor:pointer}.current-fields .tool-panel>.panel-default .panel-heading a{color:inherit}.submissions-table .table-outer.row{margin:1.5em 0 2em!important}.submissions-table .table-outer .col-xs-12{padding-left:0!important;border:1px solid #ddd;overflow-x:scroll;border-radius:3px}.submissions-table .table>thead>tr>th{min-width:8em}.submissions-table .table>tbody>tr.selected{background-color:#efefef}.admin-form .add-field{background-color:#ddd;padding:0 2%;border-radius:3px}.admin-form .add-field .col-xs-6{padding:.25em .4em}.admin-form .add-field .col-xs-6 .panel-heading{border-width:1px;border-style:solid;border-color:#bbb;border-radius:4px}.admin-form .oscar-field-select{margin:10px 0}.view-form-btn.span{padding-right:.6em}.status-light.status-light-off{color:#BE0000}.status-light.status-light-on{color:#3C0}section.public-form{padding:0 10%}section.public-form .form-submitted{height:100vh}section.public-form .btn{border:1px solid}.form-item{text-align:center;border-bottom:6px inset #ccc;background-color:#eee;width:180px;height:215px;margin-bottom:45px}.form-item.create-new input[type=text]{width:inherit;color:#000;border:none}.form-item.create-new{background-color:#838383;color:#fff}.form-item.create-new.new-form{background-color:#ff8383;z-index:11}.form-item.create-new.new-form:hover{background-color:#ff6464}.form-item.new-form input[type=text]{margin-top:.2em;width:inherit;color:#000;border:none;padding:.3em .6em}.form-item.new-form .custom-select{margin-top:.2em}.form-item.new-form .custom-select select{background-color:#fff}.form-item.new-form .details-row{margin-top:1em}.form-item.new-form .details-row.submit{margin-top:1.7em}.form-item.new-form .details-row.submit .btn{font-size:.95em}.form-item.new-form .title-row{margin-top:1em;top:0}.overlay{position:fixed;top:0;left:0;height:100%;width:100%;background-color:#000;background-color:rgba(0,0,0,.5);z-index:10}.overlay.submitform{background-color:#fff;background-color:rgba(256,256,256,.8)}.activeField,.activeField input{background-color:transparent}.field-directive{z-index:9;padding:10% 10% 10% 0;border:25px solid transparent;position:relative}.activeField{z-index:11;position:relative}.activeField.field-directive{display:inline-block;border-radius:7px;width:100%;border:25px solid transparent}.form-item.create-new:hover,.form-item:hover{border-bottom:8px inset #ccc;background-color:#d9d9d9}.form-item.create-new:hover{background-color:#515151}.form-item>.row.footer{position:absolute;bottom:0;left:30%}.form-item .title-row{position:relative;top:15px;padding-top:3em;padding-bottom:3.65em}.form-item .title-row h4{font-size:1.3em}.form-item.create-new .title-row{padding:0}.form-item.create-new .title-row h4{font-size:7em}.form-item .details-row{margin-top:3.2em}.form-item .details-row small{font-size:.6em}.form-item.create-new .details-row small{font-size:.95em}.row.auth form .field-input select{padding:.45em .9em;width:100%;background:0 0;font-size:16px;border:1px solid #ccc;height:34px}@media (min-width:992px){.nav-users{position:fixed}}.remove-account-container{display:inline-block;position:relative}.btn-remove-account{top:10px;right:10px;position:absolute}section.auth{margin-top:5em}section.auth>h3{font-size:3em;font-weight:500;color:#777}section.auth.signup-view>h3{font-size:4.4em;padding-bottom:.5em} \ No newline at end of file diff --git a/public/dist/application.min.js b/public/dist/application.min.js new file mode 100644 index 00000000..745b18c0 --- /dev/null +++ b/public/dist/application.min.js @@ -0,0 +1,4 @@ +function removeDateFieldsFunc(o){function eachObject(v,k){"lastModified"!==k&&"created"!==k||delete clone[i][k]}for(var clone=_.clone(o),i=0;i'),$templateCache.put("../public/modules/core/views/home.client.view.html",'

Craft beautiful forms in seconds.

Create your next ______.

Tell a story with a form.

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

Create a new form
Name
Language

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

{{pageData.introTitle}}

{{pageData.introParagraph}}

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

{{field.title}} *(required)

'),$templateCache.put("../public/modules/forms/views/directiveViews/field/dropdown.html",'
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/file.html",'
{{field.title}} (* required)
{{field.file.originalname}}
Upload your File
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/hidden.html",''),$templateCache.put("../public/modules/forms/views/directiveViews/field/legal.html",'
'),$templateCache.put("../public/modules/forms/views/directiveViews/field/natural.html",'

{{field.title}} *(required)


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

{{field.title}} *(required)

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

{{field.title}} *(required)


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

{{field.title}} *(required)

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

{{field.title}}

{{field.description}}


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

{{field.title}} *(required)

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

{{field.title}} *(required)

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

{{field.title}} *(required)

{{field.description}}


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

Edit Start Page


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

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

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

\n Click on Fields to add them here\n

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

You need to be logged in to access this page

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

Sign into your account

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

Restore your password

Enter your account email.

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

Password reset is invalid

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

Password successfully reset

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

Reset your password

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

Change your password

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

Edit your profile

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

Connected social accounts:

Connect other social accounts:

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

Resend your account verification email

Enter your account email.

{{error}}

Verification Email has been Sent

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

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

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

Account successfuly activated

Continue to login page

Verification link is invalid or has expired

Resend your verification email Signin to your account
')}]);var ApplicationConfiguration=function(){var applicationModuleName="NodeForm",applicationModuleVendorDependencies=["duScroll","ui.select","cgBusy","ngSanitize","vButton","ngResource","NodeForm.templates","ui.router","ui.bootstrap","ui.utils","ngRaven"],registerModule=function(moduleName,dependencies){angular.module(moduleName,dependencies||[]),angular.module(applicationModuleName).requires.push(moduleName)};return{applicationModuleName:applicationModuleName,applicationModuleVendorDependencies:applicationModuleVendorDependencies,registerModule:registerModule}}();angular.module(ApplicationConfiguration.applicationModuleName,ApplicationConfiguration.applicationModuleVendorDependencies),angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider",function($locationProvider){$locationProvider.hashPrefix("!")}]),angular.module(ApplicationConfiguration.applicationModuleName).constant("APP_PERMISSIONS",{viewAdminSettings:"viewAdminSettings",editAdminSettings:"editAdminSettings",editForm:"editForm",viewPrivateForm:"viewPrivateForm"}),angular.module(ApplicationConfiguration.applicationModuleName).constant("USER_ROLES",{admin:"admin",normal:"user",superuser:"superuser"}),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","$state","$stateParams",function($rootScope,Auth,$state,$stateParams){$rootScope.$state=$state,$rootScope.$stateParams=$stateParams,$rootScope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState){$state.previous=fromState,console.log("toState: "+toState.name),"home"===toState.name||"signin"===toState.name||"resendVerifyEmail"===toState.name||"verify"===toState.name||"signup"===toState.name||"signup-success"===toState.name?Auth.isAuthenticated()&&(event.preventDefault(),console.log("go to forms"),$state.go("listForms")):"access_denied"===toState.name||Auth.isAuthenticated()||"submitForm"===toState.name||(console.log("go to home"),event.preventDefault(),$state.go("home"))})}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","User","Authorizer","$state","$stateParams",function($rootScope,Auth,User,Authorizer,$state,$stateParams){$rootScope.$on("$stateChangeStart",function(event,next){var authenticator,permissions,user;permissions=next&&next.data&&next.data.permissions?next.data.permissions:null,Auth.ensureHasCurrentUser(User),user=Auth.currentUser,user&&(authenticator=new Authorizer(user),null!=permissions&&(authenticator.canAccess(permissions)||(event.preventDefault(),console.log("access denied"),$state.go("access_denied"))))})}]),angular.element(document).ready(function(){"#_=_"===window.location.hash&&(window.location.hash="#!"),angular.bootstrap(document,[ApplicationConfiguration.applicationModuleName])}),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.router.tabs","colorpicker.module","ui.date","ui.sortable","angular-input-stars","users"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function($stateProvider,$urlRouterProvider,Authorization){$urlRouterProvider.otherwise("/forms")}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User",function($rootScope,$scope,Menus,$state,Auth,User){$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.authentication=$rootScope.authentication=Auth,$rootScope.languages=$scope.languages=["english","french","spanish"],$scope.isCollapsed=!1,$rootScope.hideNav=!1,$scope.menu=Menus.getMenu("topbar"),$scope.signout=function(){var promise=User.logout();promise.then(function(){Auth.logout(),Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user=null,$state.go("home")},function(reason){console.log("Logout Failed: "+reason)})},$scope.toggleCollapsibleMenu=function(){$scope.isCollapsed=!$scope.isCollapsed},$scope.$on("$stateChangeSuccess",function(event,toState,toParams,fromState,fromParams){$scope.isCollapsed=!1,$rootScope.hideNav=!1,angular.isDefined(toState.data)&&angular.isDefined(toState.data.hideNav)&&($rootScope.hideNav=toState.data.hideNav)})}]),angular.module("core").controller("HomeController",["$rootScope","$scope","User","$state",function($rootScope,$scope,User,$state){$scope=$rootScope}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var shouldRender=function(user){if(!user)return this.isPublic;if(~this.roles.indexOf("*"))return!0;for(var userRoleIndex in user.roles)for(var roleIndex in this.roles)if(console.log(this.roles[roleIndex]),console.log(this.roles[roleIndex]===user.roles[userRoleIndex]),this.roles[roleIndex]===user.roles[userRoleIndex])return!0;return!1};this.validateMenuExistance=function(menuId){if(menuId&&menuId.length){if(this.menus[menuId])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(menuId){return this.validateMenuExistance(menuId),this.menus[menuId]},this.addMenu=function(menuId,isPublic,roles){return this.menus[menuId]={isPublic:isPublic||!1,roles:roles||this.defaultRoles,items:[],shouldRender:shouldRender},this.menus[menuId]},this.removeMenu=function(menuId){this.validateMenuExistance(menuId),delete this.menus[menuId]},this.addMenuItem=function(menuId,menuItemTitle,menuItemURL,menuItemType,menuItemUIRoute,isPublic,roles,position){return this.validateMenuExistance(menuId),this.menus[menuId].items.push({title:menuItemTitle,link:menuItemURL,menuItemType:menuItemType||"item",menuItemClass:menuItemType,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].roles:roles,position:position||0,items:[],shouldRender:shouldRender}),this.menus[menuId]},this.addSubMenuItem=function(menuId,rootMenuItemURL,menuItemTitle,menuItemURL,menuItemUIRoute,isPublic,roles,position){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===rootMenuItemURL&&this.menus[menuId].items[itemIndex].items.push({title:menuItemTitle,link:menuItemURL,uiRoute:menuItemUIRoute||"/"+menuItemURL,isPublic:null===isPublic||"undefined"==typeof isPublic?this.menus[menuId].items[itemIndex].isPublic:isPublic,roles:null===roles||"undefined"==typeof roles?this.menus[menuId].items[itemIndex].roles:roles,position:position||0,shouldRender:shouldRender});return this.menus[menuId]},this.removeMenuItem=function(menuId,menuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)this.menus[menuId].items[itemIndex].link===menuItemURL&&this.menus[menuId].items.splice(itemIndex,1);return this.menus[menuId]},this.removeSubMenuItem=function(menuId,submenuItemURL){this.validateMenuExistance(menuId);for(var itemIndex in this.menus[menuId].items)for(var subitemIndex in this.menus[menuId].items[itemIndex].items)this.menus[menuId].items[itemIndex].items[subitemIndex].link===submenuItemURL&&this.menus[menuId].items[itemIndex].items.splice(subitemIndex,1);return this.menus[menuId]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("forms").run(["Menus",function(Menus){Menus.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("formValidity",function(){return function(formObj){if(formObj&&formObj.form_fields&&formObj.visible_form_fields){var formKeys=Object.keys(formObj),fields=(formKeys.filter(function(key){return"$"!==key[0]}),formObj.form_fields),valid_count=fields.filter(function(field){return"object"==typeof field&&"statement"!==field.fieldType&&"rating"!==field.fieldType?!!field.fieldValue:void 0}).length;return valid_count-(formObj.form_fields.length-formObj.visible_form_fields.length)}return 0}}).config(["$provide",function($provide){$provide.decorator("accordionDirective",["$delegate",function($delegate){var directive=$delegate[0];return directive.replace=!0,$delegate}])}]),angular.module("forms").config(["$stateProvider",function($stateProvider){$stateProvider.state("listForms",{url:"/forms",templateUrl:"modules/forms/views/list-forms.client.view.html"}).state("submitForm",{url:"/forms/:formId",templateUrl:"modules/forms/views/submit-form.client.view.html",data:{hideNav:!0},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"SubmitFormController",controllerAs:"ctrl"}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/views/admin-form.client.view.html",data:{permissions:["editForm"]},resolve:{Forms:"Forms",myForm:["Forms","$stateParams",function(Forms,$stateParams){return Forms.get({formId:$stateParams.formId}).$promise}]},controller:"AdminFormController"}).state("viewForm.configure",{url:"/configure",templateUrl:"modules/forms/views/adminTabs/configure.html"}).state("viewForm.design",{url:"/design",templateUrl:"modules/forms/views/adminTabs/design.html"}).state("viewForm.analyze",{url:"/analyze",templateUrl:"modules/forms/views/adminTabs/analyze.html"}).state("viewForm.create",{url:"/create",templateUrl:"modules/forms/views/adminTabs/create.html"})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http","$uibModal","myForm",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http,$uibModal,myForm){$scope=$rootScope,$scope.animationsEnabled=!0,$scope.myform=myForm,$rootScope.saveInProgress=!1,CurrentForm.setForm($scope.myform),$scope.tabData=[{heading:"Create",route:"viewForm.create"},{heading:"Design",route:"viewForm.design"},{heading:"Configure",route:"viewForm.configure"},{heading:"Analyze",route:"viewForm.analyze"}],$scope.setForm=function(form){$scope.myform=form},$rootScope.resetForm=function(){$scope.myform=Forms.get({formId:$stateParams.formId})},$scope.openDeleteModal=function(){$scope.deleteModal=$uibModal.open({animation:$scope.animationsEnabled,templateUrl:"myModalContent.html",controller:"AdminFormController",resolve:{myForm:function(){return $scope.myform}}}),$scope.deleteModal.result.then(function(selectedItem){$scope.selected=selectedItem},function(){console.log("Modal dismissed at: "+new Date)})},$scope.cancelDeleteModal=function(){$scope.deleteModal&&$scope.deleteModal.dismiss("cancel")},$scope.removeCurrentForm=function(){if($scope.deleteModal&&$scope.deleteModal.opened){$scope.deleteModal.close();var form_id=$scope.myform._id;if(!form_id)throw new Error("Error - removeCurrentForm(): $scope.myform._id does not exist");$http["delete"]("/forms/"+form_id).success(function(data,status,headers){console.log("form deleted successfully"),$state.go("listForms",{},{reload:!0})}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}},$scope.update=$rootScope.update=function(updateImmediately,cb){var continueUpdate=!0;if(updateImmediately||(continueUpdate=!$rootScope.saveInProgress),continueUpdate){var err=null;updateImmediately||($rootScope.saveInProgress=!0),$scope.updatePromise=$http.put("/forms/"+$scope.myform._id,{form:$scope.myform}).then(function(response){$rootScope.myform=$scope.myform=response.data})["catch"](function(response){console.log("Error occured during form UPDATE.\n"),err=response.data})["finally"](function(){updateImmediately||($rootScope.saveInProgress=!1),"function"==typeof cb&&cb(err)})}}}]),angular.module("forms").controller("ListFormsController",["$rootScope","$scope","$stateParams","$state","Forms","CurrentForm","$http",function($rootScope,$scope,$stateParams,$state,Forms,CurrentForm,$http){$scope=$rootScope,$scope.forms={},$scope.showCreateModal=!1,$scope.findAll=function(){Forms.query(function(_forms){$scope.myforms=_forms})},$scope.openCreateModal=function(){$scope.showCreateModal||($scope.showCreateModal=!0)},$scope.closeCreateModal=function(){$scope.showCreateModal&&($scope.showCreateModal=!1)},$scope.setForm=function(form){$scope.myform=form},$scope.goToWithId=function(route,id){$state.go(route,{formId:id},{reload:!0})},$scope.duplicateForm=function(form_index){var form=_.cloneDeep($scope.myforms[form_index]);delete form._id,$http.post("/forms",{form:form}).success(function(data,status,headers){$scope.myforms.splice(form_index+1,0,data)}).error(function(errorResponse){console.error(errorResponse),null===errorResponse&&($scope.error=errorResponse.data.message)})},$scope.createNewForm=function(){var form={};form.title=$scope.forms.createForm.title.$modelValue,form.language=$scope.forms.createForm.language.$modelValue,$scope.forms.createForm.$valid&&$scope.forms.createForm.$dirty&&$http.post("/forms",{form:form}).success(function(data,status,headers){console.log("new form created"),$scope.goToWithId("viewForm.create",data._id+"")}).error(function(errorResponse){console.error(errorResponse),$scope.error=errorResponse.data.message})},$scope.removeForm=function(form_index){if(form_index>=$scope.myforms.length||0>form_index)throw new Error("Error: form_index in removeForm() must be between 0 and "+$scope.myforms.length-1);$http["delete"]("/forms/"+$scope.myforms[form_index]._id).success(function(data,status,headers){console.log("form deleted successfully"),$scope.myforms.splice(form_index,1)}).error(function(error){console.log("ERROR: Form could not be deleted."),console.error(error)})}}]),angular.module("forms").controller("SubmitFormController",["$scope","$rootScope","$state","myForm","Auth",function($scope,$rootScope,$state,myForm,Auth){$scope.authentication=Auth,$scope.myform=myForm,$scope.myform.isLive?$scope.hideNav=$rootScope.hideNav=!0:$scope.authentication.isAuthenticated()?$scope.hideNav=$rootScope.hideNav=!1:($scope.hideNav=$rootScope.hideNav=!0,$state.go("access_denied"))}]),_.mixin({removeDateFields:removeDateFieldsFunc}),angular.module("forms").directive("autoSaveForm",["$rootScope","$timeout",function($rootScope,$timeout){return{require:["^form"],restrict:"AE",link:function($scope,$element,$attrs,$ctrls){angular.element(document).ready(function(){var $formCtrl=$ctrls[0],savePromise=null;$rootScope.finishedRender=!1,$scope.$on("editFormFields Started",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!1}),$scope.$on("editFormFields Finished",function(ngRepeatFinishedEvent){$rootScope.finishedRender=!0}),$scope.anyDirtyAndTouched=function(form){var propCount=0;for(var prop in form)if(form.hasOwnProperty(prop)&&"$"!==prop[0]&&(propCount++,form[prop].$touched&&form[prop].$dirty))return!0;return!1};var debounceSave=function(){$rootScope.saveInProgress=!0,$rootScope[$attrs.autoSaveCallback](!0,function(err){err?(console.error("Error form data NOT persisted"),console.error(err)):(console.log("\n\nForm data persisted -- setting pristine flag"),$formCtrl.$setPristine(),$formCtrl.$setUntouched())})};$scope.$watch(function(newValue,oldValue){console.log("introParagraphStartPage.$dirty: "+$scope.editForm.introParagraphStartPage.$dirty),console.log("introParagraphStartPage.$touched: "+$scope.editForm.introParagraphStartPage.$touched),$rootScope.finishedRender&&$scope.anyDirtyAndTouched($scope.editForm)&&!$rootScope.saveInProgress&&(console.log("Form saving started"),debounceSave(),console.log("introParagraphStartPage.$dirty AFTER: "+$scope.editForm.introParagraphStartPage.$dirty))}),$scope.$watch($attrs.autoSaveWatch,function(newValue,oldValue){newValue=angular.copy(newValue),oldValue=angular.copy(oldValue),newValue.form_fields=_.removeDateFields(newValue.form_fields),oldValue.form_fields=_.removeDateFields(oldValue.form_fields);var changedFields=!_.isEqual(oldValue.form_fields,newValue.form_fields)||!_.isEqual(oldValue.startPage,newValue.startPage),changedFieldMap=!1;oldValue.hasOwnProperty("plugins.oscarhost.settings.fieldMap")&&(changedFieldMap=!!oldValue.plugins.oscarhost.settings.fieldMap&&!_.isEqual(oldValue.plugins.oscarhost.settings.fieldMap,newValue.plugins.oscarhost.settings.fieldMap)),(newValue||oldValue)&&oldValue&&(0===oldValue.form_fields.length&&($rootScope.finishedRender=!0),$rootScope.finishedRender&&(changedFields&&!$formCtrl.$dirty||changedFieldMap)&&!$rootScope.saveInProgress?(savePromise&&($timeout.cancel(savePromise),savePromise=null),savePromise=$timeout(function(){debounceSave()})):$rootScope.finishedRender&&$rootScope.saveInProgress&&($rootScope.saveInProgress=!1))},!0)})}}}]),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","CurrentForm",function($rootScope,$http,Upload,CurrentForm){return{templateUrl:"modules/forms/views/directiveViews/form/configure-form.client.view.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:["$scope",function($scope){console.log($scope.myform),CurrentForm.getForm().plugins?CurrentForm.getForm().plugins.oscarhost.baseUrl&&($scope.oscarhostAPI=!0):$scope.oscarhostAPI=!1,$scope.log="",$scope.pdfLoading=!1,$scope.languages=$rootScope.languages,this._current_upload=null,$scope.resetForm=$rootScope.resetForm,$scope.update=$rootScope.update,this._unbindedPdfFields=$scope.pdfFields,$scope.cancelUpload=function(){this._current_upload.abort(),$scope.pdfLoading=!1,$scope.removePDF()},$scope.removePDF=function(){$scope.myform.pdf=null,$scope.myform.isGenerated=!1,$scope.myform.autofillPDFs=!1,console.log("form.pdf: "+$scope.myform.pdf+" REMOVED")},$scope.uploadPDF=function(files){if(files&&files.length){var file=files[0];console.log(file),this._current_upload=Upload.upload({url:"/upload/pdf",fields:{user:$scope.user,form:$scope.myform},file:file}).progress(function(evt){var progressPercentage=parseInt(100*evt.loaded/evt.total);$scope.log="progress: "+progressPercentage+"% "+evt.config.file.name+"\n"+$scope.log,$scope.pdfLoading=!0}).success(function(data,status,headers,config){$scope.log="file "+data.originalname+" uploaded as "+data.name+". JSON: "+JSON.stringify(data)+"\n"+$scope.log,$scope.myform.pdf=angular.fromJson(angular.toJson(data)),$scope.pdfLoading=!1,console.log($scope.log),$scope.$$phase||$scope.$digest||$scope.$apply()}).error(function(err){$scope.pdfLoading=!1,console.log("Error occured during upload.\n"),console.log(err)})}}}]}}]),angular.module("forms").directive("editFormDirective",["$rootScope","FormFields",function($rootScope,FormFields){return{templateUrl:"modules/forms/views/directiveViews/form/edit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:["$scope",function($scope){for(var field_ids=_($scope.myform.form_fields).pluck("_id"),i=0;i0){$scope.myform.plugins.oscarhost.settings.fieldMap||($scope.myform.plugins.oscarhost.settings.fieldMap={});var oscarhostFields=$scope.myform.plugins.oscarhost.settings.validFields,currentFields=_($scope.myform.plugins.oscarhost.settings.fieldMap).invert().keys().value();return $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id)&&(currentFields=_(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id])),_(oscarhostFields).difference(currentFields).value()}return[]},$scope.dropzone={handle:" .handle",containment:".dropzoneContainer",cursor:"grabbing"},$scope.addNewField=function(modifyForm,fieldType){$scope.addField.lastAddedID++;for(var fieldTitle,i=0;i<$scope.addField.types.length;i++)if($scope.addField.types[i].name===fieldType){$scope.addField.types[i].lastAddedID++,fieldTitle=$scope.addField.types[i].value+$scope.addField.types[i].lastAddedID;break}var newField={title:fieldTitle,fieldType:fieldType,fieldValue:"",required:!0,disabled:!1,deletePreserved:!1};return modifyForm&&$scope.myform.form_fields.push(newField),newField},$scope.deleteField=function(field_index){var currFieldId=$scope.myform.form_fields[field_index]._id;$scope.myform.hasOwnProperty("plugins.oscarhost.baseUrl")&&delete $scope.myform.plugins.oscarhost.settings.fieldMap[currFieldId],$scope.myform.form_fields.splice(field_index,1)},$scope.duplicateField=function(field_index){var currField=_.cloneDeep($scope.myform.form_fields[field_index]);currField._id="cloned"+_.uniqueId(),currField.title+=" copy",$scope.myform.form_fields.splice(field_index+1,0,currField)},$scope.addButton=function(){var newButton={};newButton.bgColor="#ddd",newButton.color="#ffffff",newButton.text="Button",newButton._id=Math.floor(1e5*Math.random()),$scope.myform.startPage.buttons.push(newButton)},$scope.deleteButton=function(button){for(var currID,i=0;i<$scope.myform.startPage.buttons.length;i++)if(currID=$scope.myform.startPage.buttons[i]._id,console.log(currID),currID===button._id){$scope.myform.startPage.buttons.splice(i,1);break}},$scope.addOption=function(field_index){var currField=$scope.myform.form_fields[field_index];if(console.log(field_index),console.log(currField),"checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType){currField.fieldOptions||($scope.myform.form_fields[field_index].fieldOptions=[]);var lastOptionID=0;currField.fieldOptions[currField.fieldOptions.length-1]&&(lastOptionID=currField.fieldOptions[currField.fieldOptions.length-1].option_id);var newOption={option_id:Math.floor(1e5*Math.random()),option_title:"Option "+lastOptionID,option_value:"Option "+lastOptionID};$scope.myform.form_fields[field_index].fieldOptions.push(newOption)}},$scope.deleteOption=function(field_index,option){var currField=$scope.myform.form_fields[field_index];if("checkbox"===currField.fieldType||"dropdown"===currField.fieldType||"radio"===currField.fieldType)for(var i=0;i',restrict:"E",scope:{typeName:"@"},controller:["$scope",function($scope){var iconTypeMap={textfield:"fa fa-pencil-square-o",dropdown:"fa fa-th-list",date:"fa fa-calendar",checkbox:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",email:"fa fa-envelope-o",textarea:"fa fa-pencil-square",legal:"fa fa-legal",file:"fa fa-cloud-upload",rating:"fa fa-star-half-o",link:"fa fa-link",scale:"fa fa-sliders",stripe:"fa fa-credit-card",statement:"fa fa-quote-left",yes_no:"fa fa-toggle-on",number:"fa fa-slack"};$scope.typeIcon=iconTypeMap[$scope.typeName]}]}});var __indexOf=[].indexOf||function(item){for(var i=0,l=this.length;l>i;i++)if(i in this&&this[i]===item)return i;return-1};angular.module("forms").directive("fieldDirective",["$http","$compile","$rootScope","$templateCache",function($http,$compile,$rootScope,$templateCache){var getTemplateUrl=function(fieldType){var type=fieldType,templateUrl="modules/forms/views/directiveViews/field/",supported_fields=["textfield","textarea","date","dropdown","hidden","password","radio","legal","statement","rating","yes_no","number","natural"];return __indexOf.call(supported_fields,type)>=0&&(templateUrl=templateUrl+type+".html"),$templateCache.get("../public/"+templateUrl)};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&",design:"=",index:"="},link:function(scope,element){scope.setActiveField=$rootScope.setActiveField,"date"===scope.field.fieldType&&(scope.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0});var fieldType=scope.field.fieldType;if("number"===scope.field.fieldType||"textfield"===scope.field.fieldType||"email"===scope.field.fieldType||"link"===scope.field.fieldType){switch(scope.field.fieldType){case"textfield":scope.field.input_type="text";break;case"email":scope.field.input_type="email",scope.field.placeholder="joesmith@example.com";break;case"number":scope.field.input_type="number";break;default:scope.field.input_type="url",scope.field.placeholder="http://example.com"}fieldType="textfield"}var template=getTemplateUrl(fieldType);element.html(template).show(),$compile(element.contents())(scope)}}}]),angular.module("forms").directive("onEnterKey",["$rootScope",function($rootScope){return{restrict:"A",link:function($scope,$element,$attrs){$element.bind("keydown keypress",function(event){var keyCode=event.which||event.keyCode;console.log($attrs.onEnterKey),13===keyCode&&($rootScope.$apply(function(){$rootScope.$eval($attrs.onEnterKey)}),event.preventDefault())})}}}]),angular.module("forms").directive("onFinishRender",["$rootScope","$timeout",function($rootScope,$timeout){return{restrict:"A",link:function(scope,element,attrs){if(element.attr("ng-repeat")||element.attr("data-ng-repeat")){var broadcastMessage=attrs.onFinishRender||"ngRepeat";scope.$first&&!scope.$last?scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Started")}):scope.$last&&scope.$evalAsync(function(){$rootScope.$broadcast(broadcastMessage+" Finished")})}}}}]),angular.module("forms").directive("submitFormDirective",["$http","TimeCounter","$filter","$rootScope","Auth",function($http,TimeCounter,$filter,$rootScope,Auth){return{templateUrl:"modules/forms/views/directiveViews/form/submit-form.client.view.html",restrict:"E",scope:{myform:"="},controller:["$document","$window","$scope",function($document,$window,$scope){$scope.authentication=$rootScope.authentication,$scope.noscroll=!1,$scope.forms={},$scope.form_fields_count=$scope.myform.visible_form_fields.filter(function(field){return"statement"!==field.fieldType&&"rating"!==field.fieldType; +}).length,$scope.reloadForm=function(){$scope.myform.submitted=!1,$scope.myform.form_fields=_.chain($scope.myform.visible_form_fields).map(function(field){return field.fieldValue="",field}).value(),$scope.loading=!1,$scope.error="",$scope.selected={_id:"",index:0},$scope.setActiveField($scope.myform.visible_form_fields[0]._id,0,!1),console.log($scope.selected),TimeCounter.restartClock()},$window.onscroll=function(){$scope.scrollPos=document.body.scrollTop||document.documentElement.scrollTop||0;var elemBox=document.getElementsByClassName("activeField")[0].getBoundingClientRect();if($scope.fieldTop=elemBox.top,$scope.fieldBottom=elemBox.bottom,!$scope.noscroll){if($scope.selected.index===$scope.myform.form_fields.length-1&&$scope.fieldBottom<200){var field_index=$scope.selected.index+1,field_id="submit_field";$scope.setActiveField(field_id,field_index,!1)}else if($scope.selected.index===$scope.myform.form_fields.length){if($scope.fieldTop>200){var field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id;$scope.setActiveField(field_id,field_index,!1)}}else if($scope.fieldBottom<0){var field_index=$scope.selected.index+1,field_id=$scope.myform.form_fields[field_index]._id;$scope.setActiveField(field_id,field_index,!1)}else if(0!==$scope.selected.index&&$scope.fieldTop>0){var field_index=$scope.selected.index-1,field_id=$scope.myform.form_fields[field_index]._id;$scope.setActiveField(field_id,field_index,!1)}$scope.$apply()}},$scope.setActiveField=$rootScope.setActiveField=function(field_id,field_index,animateScroll){return null===$scope.selected||$scope.selected._id===field_id?(console.log("not scrolling"),void console.log($scope.selected)):(console.log("field_id: "+field_id),console.log("field_index: "+field_index),console.log($scope.selected),$scope.selected._id=field_id,$scope.selected.index=field_index,void(animateScroll&&($scope.noscroll=!0,setTimeout(function(){$document.scrollToElement(angular.element(".activeField"),-10,200).then(function(){$scope.noscroll=!1,document.querySelectorAll(".activeField .focusOn")[0].focus()})},20))))},$rootScope.nextField=$scope.nextField=function(){if(console.log("nextfield"),$scope.selected.index<$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id=$scope.myform.form_fields[selected_index]._id;$rootScope.setActiveField(selected_id,selected_index,!0)}else if($scope.selected.index===$scope.myform.form_fields.length-1){var selected_index=$scope.selected.index+1,selected_id="submit_field";$rootScope.setActiveField(selected_id,selected_index,!0)}},$rootScope.prevField=$scope.prevField=function(){if($scope.selected.index>0){var selected_index=$scope.selected.index-1,selected_id=$scope.myform.form_fields[selected_index]._id;$scope.setActiveField(selected_id,selected_index,!0)}},$scope.exitStartPage=function(){$scope.myform.startPage.showStart=!1,$scope.myform.form_fields.length>0&&($scope.selected._id=$scope.myform.form_fields[0]._id)},$scope.submitForm=function(){var _timeElapsed=TimeCounter.stopClock();$scope.loading=!0;var form=_.cloneDeep($scope.myform);form.timeElapsed=_timeElapsed,form.percentageComplete=$filter("formValidity")($scope.myform)/$scope.myform.visible_form_fields.length*100,delete form.visible_form_fields,$scope.submitPromise=$http.post("/forms/"+$scope.myform._id,form).success(function(data,status,headers){console.log("form submitted successfully"),setTimeout(function(){$scope.myform.submitted=!0,$scope.loading=!1},20)}).error(function(error){setTimeout(function(){$scope.loading=!1,console.log(error),$scope.error=error.message},20)})},$scope.reloadForm()}]}}]),angular.module("forms").service("CurrentForm",function(){var _form={};this.getForm=function(){return _form},this.setForm=function(form){_form=form}}),angular.module("forms").service("FormFields",[function(){this.types=[{name:"textfield",value:"Short Text"},{name:"email",value:"Email"},{name:"radio",value:"Multiple Choice"},{name:"dropdown",value:"Dropdown"},{name:"date",value:"Date"},{name:"textarea",value:"Paragraph Text"},{name:"yes_no",value:"Yes/No"},{name:"legal",value:"Legal"},{name:"rating",value:"Rating"},{name:"link",value:"Link"},{name:"number",value:"Numbers"},{name:"statement",value:"Statement"}]}]),angular.module("forms").factory("Forms",["$resource",function($resource){return $resource("/forms/:formId",{formId:"@_id"},{query:{method:"GET",isArray:!0},get:{method:"GET",transformResponse:function(data,header){var form=angular.fromJson(data);return console.log(form),form.visible_form_fields=_.filter(form.form_fields,function(field){return field.deletePreserved===!1}),form}},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").factory("Submissions",["$resource",function($resource){return $resource("forms/:formID/submissions/:submissionId",{submissionId:"@_id",formId:"@_id"},{query:{method:"GET",isArray:!0},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("forms").service("TimeCounter",[function(){var _startTime,_endTime,that=this;this.timeSpent=0,this.restartClock=function(){_startTime=Date.now(),_endTime=_startTime},this.stopClock=function(){return _startTime?(_endTime=Date.now(),that.timeSpent=Math.abs(_endTime.valueOf()-_startTime.valueOf())/1e3,that.timeSpent):new Error("Clock has not been started")},this.clockStarted=function(){return!!this._startTime}}]),angular.module("users").config(["$httpProvider",function($httpProvider){$httpProvider.interceptors.push(["$q","$location",function($q,$location){return{responseError:function(response){return"/users/me"!==$location.path()&&response.config&&"/users/me"!==response.config.url&&(console.log("intercepted rejection of ",response.config.url,response.status),401===response.status?($location.nextAfterLogin=$location.path(),$location.path("/signin")):403===response.status&&$location.path("/access_denied")),$q.reject(response)}}}])}]),angular.module("users").config(["$stateProvider",function($stateProvider){var checkLoggedin=function($q,$timeout,$state,User,Auth){var deferred=$q.defer();return Auth.currentUser&&Auth.currentUser.email?$timeout(deferred.resolve):Auth.currentUser=User.getCurrent(function(){Auth.login(),$timeout(deferred.resolve())},function(){Auth.logout(),$timeout(deferred.reject()),$state.go("sigin",{reload:!0})}),deferred.promise};checkLoggedin.$inject=["$q","$timeout","$state","User","Auth"],$stateProvider.state("profile",{resolve:{loggedin:checkLoggedin},url:"/settings/profile",templateUrl:"modules/users/views/settings/edit-profile.client.view.html"}).state("password",{resolve:{loggedin:checkLoggedin},url:"/settings/password",templateUrl:"modules/users/views/settings/change-password.client.view.html"}).state("accounts",{resolve:{loggedin:checkLoggedin},url:"/settings/accounts",templateUrl:"modules/users/views/settings/social-accounts.client.view.html"}).state("signup",{url:"/signup",templateUrl:"modules/users/views/authentication/signup.client.view.html"}).state("signup-success",{url:"/signup-success",templateUrl:"modules/users/views/authentication/signup-success.client.view.html"}).state("signin",{url:"/signin",templateUrl:"modules/users/views/authentication/signin.client.view.html"}).state("access_denied",{url:"/access_denied",templateUrl:"modules/users/views/authentication/access-denied.client.view.html"}).state("resendVerifyEmail",{url:"/verify",templateUrl:"modules/users/views/verify/resend-verify-email.client.view.html"}).state("verify",{url:"/verify/:token",templateUrl:"modules/users/views/verify/verify-account.client.view.html"}).state("forgot",{url:"/password/forgot",templateUrl:"modules/users/views/password/forgot-password.client.view.html"}).state("reset-invalid",{url:"/password/reset/invalid",templateUrl:"modules/users/views/password/reset-password-invalid.client.view.html"}).state("reset-success",{url:"/password/reset/success",templateUrl:"modules/users/views/password/reset-password-success.client.view.html"}).state("reset",{url:"/password/reset/:token",templateUrl:"modules/users/views/password/reset-password.client.view.html"})}]),angular.module("users").controller("AuthenticationController",["$scope","$location","$state","$rootScope","User","Auth",function($scope,$location,$state,$rootScope,User,Auth){$scope=$rootScope,$scope.credentials={},$scope.error="",$scope.signin=function(){$scope.credentials.email=$scope.credentials.username,User.login($scope.credentials).then(function(response){Auth.login(response),$scope.user=$rootScope.user=Auth.ensureHasCurrentUser(User),"home"!==$state.previous.name&&"verify"!==$state.previous.name&&""!==$state.previous.name?$state.go($state.previous.name):$state.go("listForms")},function(error){$rootScope.user=Auth.ensureHasCurrentUser(User),$scope.user=$rootScope.user,$scope.error=error,console.log("loginError: "+error)})},$scope.signup=function(){console.log($scope.credentials),User.signup($scope.credentials).then(function(response){console.log("signup-success"),$state.go("signup-success")},function(error){console.log("Error: "),console.log(error),error?($scope.error=error,console.log(error)):console.log("No response received")})}}]),angular.module("users").controller("PasswordController",["$scope","$stateParams","$state","User",function($scope,$stateParams,$state,User){$scope.error="",$scope.askForPasswordReset=function(){User.askForPasswordReset($scope.credentials).then(function(response){$scope.success=response.message,$scope.credentials=null},function(error){$scope.error=error,$scope.credentials=null})},$scope.resetUserPassword=function(){$scope.success=$scope.error=null,User.resetPassword($scope.passwordDetails,$stateParams.token).then(function(response){$scope.success=response.message,$scope.passwordDetails=null,$state.go("reset-success")},function(error){$scope.error=error.message||error,$scope.passwordDetails=null})}}]),angular.module("users").controller("SettingsController",["$scope","$rootScope","$http","$state","Users",function($scope,$rootScope,$http,$state,Users){$scope.user=$rootScope.user,$scope.hasConnectedAdditionalSocialAccounts=function(provider){for(var i in $scope.user.additionalProvidersData)return!0;return!1},$scope.isConnectedSocialAccount=function(provider){return $scope.user.provider===provider||$scope.user.additionalProvidersData&&$scope.user.additionalProvidersData[provider]},$scope.removeUserSocialAccount=function(provider){$scope.success=$scope.error=null,$http["delete"]("/users/accounts",{params:{provider:provider}}).success(function(response){$scope.success=!0,$scope.user=response}).error(function(response){$scope.error=response.message})},$scope.updateUserProfile=function(isValid){if(isValid){$scope.success=$scope.error=null;var user=new Users($scope.user);user.$update(function(response){$scope.success=!0,$scope.user=response},function(response){$scope.error=response.data.message})}else $scope.submitted=!0},$scope.changeUserPassword=function(){$scope.success=$scope.error=null,$http.post("/users/password",$scope.passwordDetails).success(function(response){$scope.success=!0,$scope.passwordDetails=null}).error(function(response){$scope.error=response.message})}}]),angular.module("users").controller("VerifyController",["$scope","$state","$rootScope","User","Auth","$stateParams",function($scope,$state,$rootScope,User,Auth,$stateParams){$scope.isResetSent=!1,$scope.credentials={},$scope.error="",$scope.resendVerifyEmail=function(){User.resendVerifyEmail($scope.credentials.email).then(function(response){console.log(response),$scope.success=response.message,$scope.credentials=null,$scope.isResetSent=!0},function(error){$scope.error=error,$scope.credentials.email=null,$scope.isResetSent=!1})},$scope.validateVerifyToken=function(){$stateParams.token&&(console.log($stateParams.token),User.validateVerifyToken($stateParams.token).then(function(response){console.log("Success: "+response.message),$scope.success=response.message,$scope.isResetSent=!0,$scope.credentials.email=null},function(error){console.log("Error: "+error.message),$scope.isResetSent=!1,$scope.error=error,$scope.credentials.email=null}))}}]),angular.module("users").factory("Auth",["$window",function($window){var userState={isLoggedIn:!1},service={_currentUser:null,get currentUser(){return this._currentUser},ensureHasCurrentUser:function(User){return service._currentUser&&service._currentUser.username?(console.log("Using local current user."),console.log(service._currentUser),service._currentUser):$window.user?(console.log("Using cached current user."),console.log($window.user),service._currentUser=$window.user,service._currentUser):(console.log("Fetching current user from the server."),void User.getCurrent().then(function(user){return service._currentUser=user,userState.isLoggedIn=!0,$window.user=service._currentUser,service._currentUser},function(response){return userState.isLoggedIn=!1,service._currentUser=null,$window.user=null,console.log("User.getCurrent() err",response),null}))},isAuthenticated:function(){return!!service._currentUser},getUserState:function(){return userState},login:function(new_user){userState.isLoggedIn=!0,service._currentUser=new_user},logout:function(){$window.user=null,userState.isLoggedIn=!1,service._currentUser=null}};return service}]),angular.module("users").service("Authorizer",["APP_PERMISSIONS","USER_ROLES",function(APP_PERMISSIONS,USER_ROLES){return function(user){return{canAccess:function(permissions){var i,len,permission;for(angular.isArray(permissions)||(permissions=[permissions]),i=0,len=permissions.length;len>i;i++){if(permission=permissions[i],null===APP_PERMISSIONS[permission])throw"Bad permission value";if(!user||!user.roles)return!1;switch(permission){case APP_PERMISSIONS.viewAdminSettings:case APP_PERMISSIONS.editAdminSettings:return user.roles.indexOf(USER_ROLES.admin)>-1;case APP_PERMISSIONS.viewPrivateForm:case APP_PERMISSIONS.editForm:return user.roles.indexOf(USER_ROLES.admin)>-1||user.roles.indexOf(USER_ROLES.normal)>-1}}return!1}}}}]),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function($window,$q,$timeout,$http,$state){var userService={getCurrent:function(){var deferred=$q.defer();return $http.get("/users/me").success(function(response){deferred.resolve(response)}).error(function(){deferred.reject("User's session has expired")}),deferred.promise},login:function(credentials){var deferred=$q.defer();return $http.post("/auth/signin",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},logout:function(){var deferred=$q.defer();return $http.get("/auth/signout").success(function(response){deferred.resolve(null)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},signup:function(credentials){var deferred=$q.defer();return $http.post("/auth/signup",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},resendVerifyEmail:function(_email){var deferred=$q.defer();return $http.post("/auth/verify",{email:_email}).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},validateVerifyToken:function(token){var validTokenRe=/^([A-Za-z0-9]{48})$/g;if(!validTokenRe.test(token))throw new Error("Error token: "+token+" is not a valid verification token");var deferred=$q.defer();return $http.get("/auth/verify/"+token).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error)}),deferred.promise},resetPassword:function(passwordDetails,token){var deferred=$q.defer();return $http.get("/auth/password/"+token,passwordDetails).success(function(response){deferred.resolve()}).error(function(error){deferred.reject(error.message||error)}),deferred.promise},askForPasswordReset:function(credentials){var deferred=$q.defer();return $http.post("/auth/forgot",credentials).success(function(response){deferred.resolve(response)}).error(function(error){deferred.reject(error.message||error)}),deferred.promise}};return userService}]),angular.module("users").factory("Users",["$resource",function($resource){return $resource("users",{},{update:{method:"PUT"}})}]); \ No newline at end of file diff --git a/public/modules/forms/config/forms.client.routes.js b/public/modules/forms/config/forms.client.routes.js index f4da84dc..5e5f44c6 100644 --- a/public/modules/forms/config/forms.client.routes.js +++ b/public/modules/forms/config/forms.client.routes.js @@ -1,9 +1,8 @@ 'use strict'; // Setting up route -angular.module('forms').config([ - '$stateProvider', - +angular.module('forms').config(['$stateProvider', + function($stateProvider) { // Forms state routing $stateProvider. @@ -46,7 +45,7 @@ angular.module('forms').config([ templateUrl: 'modules/forms/views/adminTabs/design.html' }).state('viewForm.analyze', { url: '/analyze', - templateUrl: 'modules/forms/views/adminTabs/analyze.html' + templateUrl: 'modules/forms/views/adminTabs/analyze.html', }).state('viewForm.create', { url: '/create', templateUrl: 'modules/forms/views/adminTabs/create.html' diff --git a/public/modules/forms/controllers/admin-form.client.controller.js b/public/modules/forms/controllers/admin-form.client.controller.js index fff79ad9..ec11a342 100644 --- a/public/modules/forms/controllers/admin-form.client.controller.js +++ b/public/modules/forms/controllers/admin-form.client.controller.js @@ -1,12 +1,8 @@ 'use strict'; // Forms controller -angular.module('forms').controller('AdminFormController', [ - '$rootScope', '$scope', '$stateParams', '$state', 'Forms', - 'CurrentForm', '$http', '$uibModal', 'myForm', - - function($rootScope, $scope, $stateParams, $state, Forms, - CurrentForm, $http, $uibModal, myForm) { +angular.module('forms').controller('AdminFormController', ['$rootScope', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm', '$http', '$uibModal', 'myForm', + function($rootScope, $scope, $stateParams, $state, Forms, CurrentForm, $http, $uibModal, myForm) { $scope = $rootScope; $scope.animationsEnabled = true; @@ -43,8 +39,8 @@ angular.module('forms').controller('AdminFormController', [ }); }; - /* - ** DeleteModal Functions + /* + ** DeleteModal Functions */ $scope.openDeleteModal = function(){ $scope.deleteModal = $uibModal.open({ @@ -76,15 +72,15 @@ angular.module('forms').controller('AdminFormController', [ if($scope.deleteModal && $scope.deleteModal.opened){ $scope.deleteModal.close(); - + var form_id = $scope.myform._id; if(!form_id) throw new Error('Error - removeCurrentForm(): $scope.myform._id does not exist'); - + $http.delete('/forms/'+form_id) .success(function(data, status, headers){ console.log('form deleted successfully'); - $state.go('listForms', {}, {reload: true}); + $state.go('listForms', {}, {reload: true}); }).error(function(error){ console.log('ERROR: Form could not be deleted.'); @@ -100,7 +96,7 @@ angular.module('forms').controller('AdminFormController', [ if(!updateImmediately){ continueUpdate = !$rootScope.saveInProgress; } - + //Update form **if we are not currently updating** or if **shouldUpdateNow flag is set** if(continueUpdate){ var err = null; @@ -115,12 +111,12 @@ angular.module('forms').controller('AdminFormController', [ console.log('Error occured during form UPDATE.\n'); // console.log(response.data); err = response.data; - }).finally(function() { + }).finally(function() { // console.log('finished updating'); if(!updateImmediately){$rootScope.saveInProgress = false; } if( (typeof cb) === 'function'){ - cb(err); + cb(err); } }); } @@ -128,4 +124,4 @@ angular.module('forms').controller('AdminFormController', [ } -]); +]); \ No newline at end of file diff --git a/public/modules/forms/directives/configure-form.client.directive.js b/public/modules/forms/directives/configure-form.client.directive.js index 936ed5f0..68062a38 100644 --- a/public/modules/forms/directives/configure-form.client.directive.js +++ b/public/modules/forms/directives/configure-form.client.directive.js @@ -1,7 +1,6 @@ 'use strict'; -angular.module('forms').directive('configureFormDirective', [ - '$rootScope', '$http', 'Upload', 'CurrentForm', +angular.module('forms').directive('configureFormDirective', ['$rootScope', '$http', 'Upload', 'CurrentForm', function ($rootScope, $http, Upload, CurrentForm) { return { templateUrl: 'modules/forms/views/directiveViews/form/configure-form.client.view.html', @@ -22,7 +21,7 @@ angular.module('forms').directive('configureFormDirective', [ $scope.log = ''; $scope.pdfLoading = false; $scope.languages = $rootScope.languages; - + this._current_upload = null; $scope.resetForm = $rootScope.resetForm; $scope.update = $rootScope.update; @@ -67,7 +66,7 @@ angular.module('forms').directive('configureFormDirective', [ var progressPercentage = parseInt(100.0 * evt.loaded / evt.total); $scope.log = 'progress: ' + progressPercentage + '% ' + evt.config.file.name + '\n' + $scope.log; - + $scope.pdfLoading = true; }).success(function (data, status, headers, config) { $scope.log = 'file ' + data.originalname + ' uploaded as '+ data.name +'. JSON: ' + JSON.stringify(data) + '\n' + $scope.log; @@ -92,4 +91,4 @@ angular.module('forms').directive('configureFormDirective', [ } }; } -]); +]); \ No newline at end of file diff --git a/public/modules/forms/directives/edit-form.client.directive.js b/public/modules/forms/directives/edit-form.client.directive.js index 74c20c06..066e60e9 100644 --- a/public/modules/forms/directives/edit-form.client.directive.js +++ b/public/modules/forms/directives/edit-form.client.directive.js @@ -1,7 +1,6 @@ 'use strict'; -angular.module('forms').directive('editFormDirective', [ - '$rootScope', 'FormFields', +angular.module('forms').directive('editFormDirective', ['$rootScope', 'FormFields', function ($rootScope, FormFields) { return { templateUrl: 'modules/forms/views/directiveViews/form/edit-form.client.view.html', @@ -46,7 +45,7 @@ angular.module('forms').directive('editFormDirective', [ if( $scope.myform.plugins.oscarhost.settings.fieldMap.hasOwnProperty(field_id) ){ currentFields = _(currentFields).difference($scope.myform.plugins.oscarhost.settings.fieldMap[field_id]); - } + } //Get all oscarhostFields that haven't been mapped to a formfield return _(oscarhostFields).difference(currentFields).value(); @@ -74,9 +73,9 @@ angular.module('forms').directive('editFormDirective', [ var fieldTitle; for(var i = 0; i < $scope.addField.types.length; i++){ - if($scope.addField.types[i].name === fieldType){ + if($scope.addField.types[i].name === fieldType){ $scope.addField.types[i].lastAddedID++; - fieldTitle = $scope.addField.types[i].value+$scope.addField.types[i].lastAddedID; + fieldTitle = $scope.addField.types[i].value+$scope.addField.types[i].lastAddedID; break; } } @@ -91,12 +90,12 @@ angular.module('forms').directive('editFormDirective', [ // console.log('\n\n---------\nAdded field CLIENT'); // console.log(newField); // newField._id = _.uniqueId(); - + // put newField into fields array if(modifyForm){ $scope.myform.form_fields.push(newField); } - return newField; + return newField; }; // Delete particular field on button click @@ -110,7 +109,7 @@ angular.module('forms').directive('editFormDirective', [ $scope.myform.form_fields.splice(field_index, 1); }; $scope.duplicateField = function (field_index){ - var currField = _.cloneDeep($scope.myform.form_fields[field_index]); + var currField = _.cloneDeep($scope.myform.form_fields[field_index]); currField._id = 'cloned'+_.uniqueId(); currField.title += ' copy'; @@ -159,8 +158,8 @@ angular.module('forms').directive('editFormDirective', [ $scope.addOption = function(field_index){ var currField = $scope.myform.form_fields[field_index]; console.log(field_index); - console.log(currField); - + console.log(currField); + if(currField.fieldType === 'checkbox' || currField.fieldType === 'dropdown' || currField.fieldType === 'radio'){ if(!currField.fieldOptions) $scope.myform.form_fields[field_index].fieldOptions = []; @@ -210,7 +209,7 @@ angular.module('forms').directive('editFormDirective', [ }; }, - + }; } ]); diff --git a/public/modules/forms/directives/edit-submissions-form.client.directive.js b/public/modules/forms/directives/edit-submissions-form.client.directive.js index e8bb87e6..fb2954e8 100644 --- a/public/modules/forms/directives/edit-submissions-form.client.directive.js +++ b/public/modules/forms/directives/edit-submissions-form.client.directive.js @@ -1,7 +1,6 @@ 'use strict'; -angular.module('forms').directive('editSubmissionsFormDirective', [ - '$rootScope', '$http', +angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', '$http', function ($rootScope, $http) { return { templateUrl: 'modules/forms/views/directiveViews/form/edit-submissions-form.client.view.html', @@ -50,7 +49,7 @@ angular.module('forms').directive('editSubmissionsFormDirective', [ defaultFormFields = _.cloneDeep($scope.myform.form_fields); // console.log('before textField2: '+data[0].form_fields[1].fieldValue); - + //Iterate through form's submissions for(var i=0; i 200){ + if($scope.fieldTop > 200){ var field_index = $scope.selected.index-1; var field_id = $scope.myform.form_fields[field_index]._id; $scope.setActiveField(field_id, field_index, false); @@ -70,11 +70,11 @@ angular.module('forms').directive('submitFormDirective', ['$http', 'TimeCounter' }else if ( $scope.selected.index !== 0 && $scope.fieldTop > 0) { var field_index = $scope.selected.index-1; var field_id = $scope.myform.form_fields[field_index]._id; - $scope.setActiveField(field_id, field_index, false); + $scope.setActiveField(field_id, field_index, false); } //console.log('$scope.selected.index: '+$scope.selected.index); //console.log('scroll pos: '+$scope.scrollPos+' fieldTop: '+$scope.fieldTop+' fieldBottom: '+$scope.fieldBottom); - $scope.$apply(); + $scope.$apply(); } }; @@ -127,23 +127,23 @@ angular.module('forms').directive('submitFormDirective', ['$http', 'TimeCounter' $scope.setActiveField(selected_id, selected_index, true); } }; - + /* ** Form Display Functions */ $scope.exitStartPage = function(){ $scope.myform.startPage.showStart = false; - if($scope.myform.form_fields.length > 0){ + if($scope.myform.form_fields.length > 0){ $scope.selected._id = $scope.myform.form_fields[0]._id; } }; $scope.submitForm = function(){ var _timeElapsed = TimeCounter.stopClock(); - $scope.loading = true; + $scope.loading = true; var form = _.cloneDeep($scope.myform); form.timeElapsed = _timeElapsed; - + form.percentageComplete = $filter('formValidity')($scope.myform)/$scope.myform.visible_form_fields.length*100; delete form.visible_form_fields; diff --git a/public/modules/users/config/users.client.routes.js b/public/modules/users/config/users.client.routes.js index bc3080d8..3565ec2d 100755 --- a/public/modules/users/config/users.client.routes.js +++ b/public/modules/users/config/users.client.routes.js @@ -1,8 +1,7 @@ 'use strict'; // Setting up route -angular.module('users').config([ - '$stateProvider', +angular.module('users').config(['$stateProvider', function($stateProvider) { var checkLoggedin = function($q, $timeout, $state, User, Auth) { @@ -68,7 +67,7 @@ angular.module('users').config([ url: '/access_denied', templateUrl: 'modules/users/views/authentication/access-denied.client.view.html' }). - + state('resendVerifyEmail', { url: '/verify', templateUrl: 'modules/users/views/verify/resend-verify-email.client.view.html' @@ -95,4 +94,4 @@ angular.module('users').config([ templateUrl: 'modules/users/views/password/reset-password.client.view.html' }); } -]); +]); \ No newline at end of file diff --git a/public/populate_template_cache.js b/public/populate_template_cache.js new file mode 100644 index 00000000..49b95f19 --- /dev/null +++ b/public/populate_template_cache.js @@ -0,0 +1,323 @@ +angular.module('NodeForm.templates', []).run(['$templateCache', function($templateCache) { + "use strict"; + $templateCache.put("../public/modules/core/views/header.client.view.html", + "
"); + $templateCache.put("../public/modules/core/views/home.client.view.html", + "

TellForm

Craft beautiful forms in seconds.

Craft beautiful forms.

TellForm is an opensource alternative to TypeForm that can create stunning forms from PDFs or from scratch

TellForm is an opensource alternative to TypeForm that can create stunning forms from PDFs or from scratch

Create your next ______.

Tell a story with a form.

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

Create a new form
Name
Language

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

Change how your Form Looks

Change how your Form Looks

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

{{pageData.introTitle}}

{{pageData.introParagraph}}

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

{{field.title}} *(required)

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

{{field.title}} *(required)

{{$select.selected.option_value}}

"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/file.html", + "
{{field.title}} (* required)
{{field.file.originalname}}
Upload your File
"); + $templateCache.put("../public/modules/forms/views/directiveViews/field/hidden.html", + ""); + $templateCache.put("../public/modules/forms/views/directiveViews/field/legal.html", + "

{{field.title}} *(required)


{{field.description}}


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

{{field.title}} *(required)


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

{{field.title}} *(required)

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

{{field.title}} *(required)


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

{{field.title}} *(required)

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

{{field.title}}

{{field.description}}


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

{{field.title}} *(required)

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

{{field.title}} *(required)

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

{{field.title}} *(required)

{{field.description}}


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

PDF Generation/EMR

PDF Generation/EMR

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


Advanced Settings

Advanced Settings

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

Click to Add New Field

Add New Field

Add Field

Start Page

Preview Start Page

    {{myform.startPage.introTitle}}

    {{myform.startPage.introParagraph}}

Edit Start Page


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

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

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

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

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

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

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

You need to be logged in to access this page

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

Sign into your account

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

Signup Successful

You've successfully registered an account at TellForm.

But your account is not activated yet



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

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

Signup with your email

Couldn't submit form due to errors:

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

Restore your password

Enter your account email.

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

Password reset is invalid

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

Password successfully reset

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

Reset your password

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

Change your password


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

Edit your profile

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

Language
Email (also your username)
"); + $templateCache.put("../public/modules/users/views/settings/social-accounts.client.view.html", + "

Connected social accounts:

Connect other social accounts:

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

Resend your account verification email

Enter your account email.

{{error}}

Verification Email has been Sent

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

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

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

Account successfuly activated

Continue to login page

Verification link is invalid or has expired

Resend your verification email Signin to your account
"); +}]);