From 76d6d54cd5932d0d272a455b26977cb6fd35f964 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 11:54:40 -0700 Subject: [PATCH 01/29] got edit-submissions-form directive tests to pass --- app/models/form.server.model.js | 1 - package.json | 2 +- public/dist/form_populate_template_cache.js | 18 +- .../header.client.controller.test.js | 29 + .../modules/forms/admin/config/i18n/german.js | 1 - .../edit-submissions-form.client.directive.js | 117 +++- .../services/form-fields.client.service.js | 1 - .../admin-form.client.controller.test.js | 18 +- .../list-forms.client.controller.test.js | 34 +- ...-form-submissions.client.directive.test.js | 62 +- .../edit-form.client.directive.test.js | 18 + tests/client/mockData.js | 588 ++++++++++++++++++ 12 files changed, 807 insertions(+), 82 deletions(-) create mode 100644 tests/client/mockData.js diff --git a/app/models/form.server.model.js b/app/models/form.server.model.js index b20d1a9e..0262c881 100644 --- a/app/models/form.server.model.js +++ b/app/models/form.server.model.js @@ -71,7 +71,6 @@ var VisitorDataSchema = new Schema({ userAgent: { type: String } - }); var formSchemaOptions = { diff --git a/package.json b/package.json index 3700f6b0..c1e2f083 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "grunt-usemin": "^3.1.1", "grunt-wiredep": "^3.0.1", "istanbul": "^0.4.0", - "jasmine-core": "^2.4.1", + "jasmine-core": "^2.6", "karma": "~0.13.14", "karma-chrome-launcher": "~0.2.1", "karma-coverage": "~0.5.3", diff --git a/public/dist/form_populate_template_cache.js b/public/dist/form_populate_template_cache.js index e89e3c03..3e094dc7 100644 --- a/public/dist/form_populate_template_cache.js +++ b/public/dist/form_populate_template_cache.js @@ -1,4 +1,4 @@ -angular.module('TellForm-Form.form_templates', []).run(['$templateCache', function($templateCache) { +angular.module('TellForm-Form.form_templates', []).run(['$templateCache', function ($templateCache) { "use strict"; $templateCache.put("form_modules/forms/base/views/form-not-found.client.view.html", "

{{ 'FORM_404_HEADER' | translate }}

{{ 'FORM_404_BODY' | translate }}
"); @@ -10,26 +10,26 @@ angular.module('TellForm-Form.form_templates', []).run(['$templateCache', functi $templateCache.put("form_modules/forms/base/views/directiveViews/entryPage/startPage.html", "

{{pageData.introTitle}}

{{pageData.introParagraph}}

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

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

{{field.description}}

"); + "

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

{{field.description}}

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

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

{{field.description}}


"); + "
0\">

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

{{field.description}}


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

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


{{field.description}}


"); + "

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


{{field.description}}


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

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

{{field.description}}


"); + "
0\">

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

{{field.description}}


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

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

{{field.description}}

"); + "

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

{{field.description}}

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

{{field.title}}

{{field.description}}

{{field.description}}


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

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

{{ 'NEWLINE' | translate }}

{{field.description}}

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

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

{{field.description}}

{{ 'ENTER' | translate }}
"); + "

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

{{field.description}}

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

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

{{field.description}}


"); + "

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

{{field.description}}


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

{{myform.startPage.introTitle}}

{{myform.startPage.introParagraph}}

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

{{ 'ADVANCEMENT' | translate:translateAdvancementData }}

{{ 'FORM_SUCCESS' | translate }}

{{myform.endPage.title}}

{{myform.endPage.paragraph}}

"); }]); diff --git a/public/modules/core/tests/unit/controllers/header.client.controller.test.js b/public/modules/core/tests/unit/controllers/header.client.controller.test.js index 76ee4fb4..f2cebdc1 100755 --- a/public/modules/core/tests/unit/controllers/header.client.controller.test.js +++ b/public/modules/core/tests/unit/controllers/header.client.controller.test.js @@ -6,9 +6,38 @@ var scope, HeaderController; + var sampleUser = { + firstName: 'Full', + lastName: 'Name', + email: 'test@test.com', + username: 'test@test.com', + language: 'en', + password: 'password', + provider: 'local', + roles: ['user'], + _id: 'ed873933b1f1dea0ce12fab9' + }; + // Load the main application module beforeEach(module(ApplicationConfiguration.applicationModuleName)); + //Mock Authentication Service + beforeEach(module(function($provide) { + $provide.service('Auth', function() { + return { + ensureHasCurrentUser: function() { + return sampleUser; + }, + isAuthenticated: function() { + return true; + }, + getUserState: function() { + return true; + } + }; + }); + })); + beforeEach(inject(function($controller, $rootScope) { scope = $rootScope.$new(); diff --git a/public/modules/forms/admin/config/i18n/german.js b/public/modules/forms/admin/config/i18n/german.js index 0ea8d351..77d40107 100644 --- a/public/modules/forms/admin/config/i18n/german.js +++ b/public/modules/forms/admin/config/i18n/german.js @@ -84,7 +84,6 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid ADD_OPTION: 'Option hinzufügen', NUM_OF_STEPS: 'Anzahl der Schritte', CLICK_FIELDS_FOOTER: 'Klicken Sie auf Felder, um sie hier hinzuzufügen', - FORM: 'Formular', IF_THIS_FIELD: 'Wenn dieses Feld', IS_EQUAL_TO: 'ist gleich', IS_NOT_EQUAL_TO: 'ist nicht gleich', diff --git a/public/modules/forms/admin/directives/edit-submissions-form.client.directive.js b/public/modules/forms/admin/directives/edit-submissions-form.client.directive.js index de630bfa..e405da62 100644 --- a/public/modules/forms/admin/directives/edit-submissions-form.client.directive.js +++ b/public/modules/forms/admin/directives/edit-submissions-form.client.directive.js @@ -10,13 +10,33 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', myform: '=' }, controller: function($scope){ - $scope.table = { masterChecker: false, rows: [] }; - var getSubmissions = function(){ + $scope.deletionInProgress = false; + $scope.waitingForDeletion = false; + + //Waits until deletionInProgress is false before running getSubmissions + $scope.$watch("deletionInProgress",function(newVal, oldVal){ + if(newVal === oldVal) return; + + if(newVal === false && $scope.waitingForDeletion) { + $scope.getSubmissions(); + $scope.waitingForDeletion = false; + } + }); + + $scope.handleSubmissionsRefresh = function(){ + if(!$scope.deletionInProgress) { + $scope.getSubmissions(); + } else { + $scope.waitingForDeletion = true; + } + }; + + $scope.getSubmissions = function(cb){ $http({ method: 'GET', url: '/forms/'+$scope.myform._id+'/submissions' @@ -36,10 +56,19 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', } $scope.table.rows = submissions; - }); + + if(cb && typeof cb === 'function'){ + cb(); + } + }, function errorCallback(err){ + console.error(err); + if(cb && typeof cb === 'function'){ + cb(err); + } + }); }; - var getVisitors = function(){ + $scope.getVisitors = function(){ $http({ method: 'GET', url: '/forms/'+$scope.myform._id+'/visitors' @@ -52,8 +81,23 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', }); }; - getSubmissions(); - getVisitors(); + $scope.handleSubmissionsRefresh(); + $scope.getVisitors(); + + //Fetch submissions and visitor data every 1.67 min + var updateSubmissions = $interval($scope.handleSubmissionsRefresh, 100000); + var updateVisitors = $interval($scope.getVisitors, 1000000); + + //Prevent $intervals from running after directive is destroyed + $scope.$on('$destroy', function() { + if (updateSubmissions) { + $interval.cancel($scope.updateSubmissions); + } + + if (updateVisitors) { + $interval.cancel($scope.updateVisitors); + } + }); /* ** Analytics Functions @@ -72,14 +116,48 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', return (totalTime/numSubmissions).toFixed(0); })(); - var updateFields = $interval(getSubmissions, 100000); - var updateFields = $interval(getVisitors, 1000000); + $scope.DeviceStatistics = (function(){ + var newStatItem = function(){ + return { + visits: 0, + responses: 0, + completion: 0, + average_time: 0, + total_time: 0 + }; + }; - $scope.$on('$destroy', function() { - if (updateFields) { - $interval.cancel($scope.updateFields); + var stats = { + desktop: newStatItem(), + tablet: newStatItem(), + phone: newStatItem(), + other: newStatItem() + }; + + if($scope.myform.analytics && $scope.myform.analytics.visitors) { + var visitors = $scope.myform.analytics.visitors; + for (var i = 0; i < visitors.length; i++) { + var visitor = visitors[i]; + var deviceType = visitor.deviceType; + + stats[deviceType].visits++; + + if (visitor.isSubmitted) { + stats[deviceType].total_time = stats[deviceType].total_time + visitor.timeElapsed; + stats[deviceType].responses++; + } + + if(stats[deviceType].visits) { + stats[deviceType].completion = 100*(stats[deviceType].responses / stats[deviceType].visits).toFixed(2); + } + + if(stats[deviceType].responses){ + stats[deviceType].average_time = (stats[deviceType].total_time / stats[deviceType].responses).toFixed(0); + } + } } - }); + return stats; + })(); /* ** Table Functions @@ -109,25 +187,24 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope', //Delete selected submissions of Form $scope.deleteSelectedSubmissions = function(){ + $scope.deletionInProgress = true; var delete_ids = _.chain($scope.table.rows).filter(function(row){ return !!row.selected; }).pluck('_id').value(); - $http({ url: '/forms/'+$scope.myform._id+'/submissions', + return $http({ url: '/forms/'+$scope.myform._id+'/submissions', method: 'DELETE', data: {deleted_submissions: delete_ids}, headers: {'Content-Type': 'application/json;charset=utf-8'} }).success(function(data, status){ + $scope.deletionInProgress = true; //Remove deleted ids from table - var tmpArray = []; - for(var i=0; i<$scope.table.rows.length; i++){ - if(!$scope.table.rows[i].selected){ - tmpArray.push($scope.table.rows[i]); - } - } - $scope.table.rows = tmpArray; + $scope.table.rows = $scope.table.rows.filter(function(field){ + return !field.selected; + }); }) .error(function(err){ + $scope.deletionInProgress = true; console.error(err); }); }; diff --git a/public/modules/forms/admin/services/form-fields.client.service.js b/public/modules/forms/admin/services/form-fields.client.service.js index d6dae5eb..dd1d7dec 100644 --- a/public/modules/forms/admin/services/form-fields.client.service.js +++ b/public/modules/forms/admin/services/form-fields.client.service.js @@ -4,7 +4,6 @@ angular.module('forms').service('FormFields', [ '$rootScope', '$translate', '$window', function($rootScope, $translate, $window) { $translate.use($window.user.language); - console.log($translate.instant('SHORT_TEXT')); this.types = [ { diff --git a/public/modules/forms/tests/unit/controllers/admin-form.client.controller.test.js b/public/modules/forms/tests/unit/controllers/admin-form.client.controller.test.js index ba92adaf..b94d75b7 100644 --- a/public/modules/forms/tests/unit/controllers/admin-form.client.controller.test.js +++ b/public/modules/forms/tests/unit/controllers/admin-form.client.controller.test.js @@ -58,7 +58,7 @@ }; var newFakeModal = function(){ - var result = { + var modal = { opened: true, close: function( item ) { //The user clicked OK on the modal dialog, call the stored confirm callback with the selected item @@ -67,12 +67,19 @@ dismiss: function( type ) { //The user clicked cancel on the modal dialog, call the stored cancel callback this.opened = false; + }, + result: { + then: function (cb) { + if(cb && typeof cb === 'function'){ + cb(); + } + } } }; - return result; + return modal; }; - //Mock Users Service + //Mock myForm Service beforeEach(module(function($provide) { $provide.service('myForm', function($q) { return sampleForm; @@ -159,7 +166,6 @@ }); })); - //Mock $uibModal beforeEach(inject(function($uibModal) { var modal = newFakeModal(); @@ -199,7 +205,7 @@ expect(scope.myform).toEqualData(sampleForm); }); - it('$scope.removeCurrentForm() with valid form data should send a DELETE request with the id of form', function() { + it('$scope.removeCurrentForm() with valid form data should send a DELETE request with the id of form', inject(function($uibModal) { var controller = createAdminFormController(); //Set $state transition @@ -214,7 +220,7 @@ $httpBackend.flush(); $state.ensureAllTransitionsHappened(); - }); + })); it('$scope.update() should send a PUT request with the id of form', function() { var controller = createAdminFormController(); diff --git a/public/modules/forms/tests/unit/controllers/list-forms.client.controller.test.js b/public/modules/forms/tests/unit/controllers/list-forms.client.controller.test.js index 6f591280..2190264b 100644 --- a/public/modules/forms/tests/unit/controllers/list-forms.client.controller.test.js +++ b/public/modules/forms/tests/unit/controllers/list-forms.client.controller.test.js @@ -86,7 +86,6 @@ }); })); - // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_). // This allows us to inject a service but then attach it to a variable // with the same name as the service. @@ -106,25 +105,13 @@ // Initialize the Forms controller. createListFormsController = function(){ - return $controller('ListFormsController', { $scope: scope }); + return $controller('ListFormsController', { + $scope: scope, + myForms: sampleFormList + }); }; })); - it('$scope.findAll() should query all User\'s Forms', inject(function() { - - var controller = createListFormsController(); - - // Set GET response - $httpBackend.expectGET(/^(\/forms)$/).respond(200, sampleFormList); - - // Run controller functionality - scope.findAll(); - $httpBackend.flush(); - - // Test scope value - expect( scope.myforms ).toEqualData(sampleFormList); - })); - it('$scope.duplicateForm() should duplicate a Form', inject(function() { var dupSampleForm = sampleFormList[2], @@ -135,12 +122,6 @@ var controller = createListFormsController(); - // Set GET response - $httpBackend.expectGET(/^(\/forms)$/).respond(200, sampleFormList); - // Run controller functionality - scope.findAll(); - $httpBackend.flush(); - // Set GET response $httpBackend.expect('POST', '/forms').respond(200, dupSampleForm); // Run controller functionality @@ -164,13 +145,6 @@ var controller = createListFormsController(); - // Set GET response - $httpBackend.expectGET(/^(\/forms)$/).respond(200, sampleFormList); - - // Run controller functionality - scope.findAll(); - $httpBackend.flush(); - // Set GET response $httpBackend.expect('DELETE', /^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, delSampleForm); diff --git a/public/modules/forms/tests/unit/directives/edit-form-submissions.client.directive.test.js b/public/modules/forms/tests/unit/directives/edit-form-submissions.client.directive.test.js index d1418c2e..75ac6b0d 100644 --- a/public/modules/forms/tests/unit/directives/edit-form-submissions.client.directive.test.js +++ b/public/modules/forms/tests/unit/directives/edit-form-submissions.client.directive.test.js @@ -2,7 +2,7 @@ (function() { // Forms Controller Spec - describe('EditSubmissions Directive-Controller Tests', function() { + describe('EditFormSubmissions Directive-Controller Tests', function() { // Initialize global variables var el, scope, controller, $httpBackend; @@ -10,13 +10,25 @@ firstName: 'Full', lastName: 'Name', email: 'test@test.com', - username: 'test@test.com', + username: 'test1234', password: 'password', provider: 'local', roles: ['user'], _id: 'ed873933b1f1dea0ce12fab9' }; + var sampleVisitors = [{ + socketId: '33b1f1dea0ce12fab9ed8739', + referrer: 'https://tellform.com/examples', + lastActiveField: 'ed873933b0ce121f1deafab9', + timeElapsed: 100000, + isSubmitted: true, + language: 'en', + ipAddr: '192.168.1.1', + deviceType: 'desktop', + userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4' + }] + var sampleForm = { title: 'Form Title', admin: 'ed873933b1f1dea0ce12fab9', @@ -27,7 +39,18 @@ {fieldType:'checkbox', title:'hockey', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed8317393deab0ce121ffab9'} ], analytics: { - visitors: [] + visitors: sampleVisitors, + conversionRate: 80.5, + fields: [ + { + dropoffViews: 0, + responses: 1, + totalViews: 1, + continueRate: 100, + dropoffRate: 0, + field: {fieldType:'textfield', title:'First Name', fieldOptions: [], fieldValue: '', required: true, disabled: false, deletePreserved: false, _id: 'ed873933b0ce121f1deafab9'} + } + ] }, submissions: [], startPage: { @@ -61,7 +84,8 @@ ], admin: sampleUser, form: sampleForm, - timeElapsed: 10.33 + timeElapsed: 10.33, + selected: false }, { form_fields: [ @@ -71,7 +95,8 @@ ], admin: sampleUser, form: sampleForm, - timeElapsed: 2.33 + timeElapsed: 2.33, + selected: false }, { form_fields: [ @@ -81,7 +106,8 @@ ], admin: sampleUser, form: sampleForm, - timeElapsed: 11.11 + timeElapsed: 11.11, + selected: false }]; // The $resource service augments the response object with methods for updating and deleting the resource. @@ -118,10 +144,12 @@ $httpBackend.whenGET(/^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm); $httpBackend.whenGET('/forms').respond(200, sampleForm); $httpBackend.whenGET(/^(\/forms\/)([0-9a-fA-F]{24})$/).respond(200, sampleForm); - //Instantiate directive. + $httpBackend.whenGET(/^(\/forms\/)([0-9a-fA-F]{24})\/submissions$/).respond(200, sampleSubmissions); + $httpBackend.whenGET(/^(\/forms\/)([0-9a-fA-F]{24})\/visitors$/).respond(200, sampleVisitors); + + //Instantiate directive. var tmp_scope = $rootScope.$new(); tmp_scope.myform = sampleForm; - tmp_scope.myform.submissions = sampleSubmissions; tmp_scope.user = sampleUser; //gotacha: Controller and link functions will execute. @@ -141,6 +169,7 @@ it('$scope.toggleAllCheckers should toggle all checkboxes in table', function(){ //Run Controller Logic to Test + scope.table.rows = sampleSubmissions; scope.table.masterChecker = true; scope.toggleAllCheckers(); @@ -151,6 +180,7 @@ }); it('$scope.isAtLeastOneChecked should return true when at least one checkbox is selected', function(){ + scope.table.rows = sampleSubmissions; scope.table.masterChecker = true; scope.toggleAllCheckers(); @@ -161,16 +191,22 @@ }); it('$scope.deleteSelectedSubmissions should delete all submissions that are selected', function(){ + $httpBackend.expect('GET', /^(\/forms\/)([0-9a-fA-F]{24})(\/submissions)$/).respond(200, sampleSubmissions); scope.table.masterChecker = true; - scope.toggleAllCheckers(); + scope.getSubmissions(function(err){ + scope.toggleAllCheckers(); - $httpBackend.expect('DELETE', /^(\/forms\/)([0-9a-fA-F]{24})(\/submissions)$/).respond(200); + $httpBackend.expect('DELETE', /^(\/forms\/)([0-9a-fA-F]{24})(\/submissions)$/).respond(200); - //Run Controller Logic to Test - scope.deleteSelectedSubmissions(); + //Run Controller Logic to Test + scope.deleteSelectedSubmissions().then(function(){ + expect(scope.table.rows.length).toEqual(0); + }); + expect(err).not.toBeDefined(); + }); $httpBackend.flush(); - expect(scope.table.rows.length).toEqual(0); + }); }); diff --git a/public/modules/forms/tests/unit/directives/edit-form.client.directive.test.js b/public/modules/forms/tests/unit/directives/edit-form.client.directive.test.js index fe7e2452..aa1710ca 100644 --- a/public/modules/forms/tests/unit/directives/edit-form.client.directive.test.js +++ b/public/modules/forms/tests/unit/directives/edit-form.client.directive.test.js @@ -62,6 +62,24 @@ beforeEach(module('module-templates')); beforeEach(module('stateMock')); + //Mock FormFields Service + beforeEach(module(function($provide) { + $provide.service('FormFields', function() { + return { + types: [ + { + name : 'textfield', + value : 'Short Text' + }, + { + name : 'email', + value : 'Email' + } + ] + }; + }); + })); + beforeEach(inject(function($compile, $controller, $rootScope, _$httpBackend_) { //Instantiate directive. var tmp_scope = $rootScope.$new(); diff --git a/tests/client/mockData.js b/tests/client/mockData.js new file mode 100644 index 00000000..4b37219b --- /dev/null +++ b/tests/client/mockData.js @@ -0,0 +1,588 @@ +module.exports = { + sampleUser: { + "_id": "598cb79e43859500277bc804", + "lastModified": "2017-10-06T05:36:28.394Z", + "email": "test@test.com", + "username": "test1234", + "salt": null, + "__v": 0, + "resetPasswordExpires": "2017-10-06T06:36:28.391Z", + "resetPasswordToken": "2d95c01d79fb06c73691577cd82e5cce2ff616f1", + "created": "2017-08-10T19:44:30.601Z", + "language": "en", + "roles": ["user"], + "provider": "local", + "passwordHash": null, + "lastName": "Full", + "firstName": "Name" + }, + + sampleForm1: { + "_id": "59d25a9d413a7a3106878556", + "lastModified": "2017-10-19T00:46:24.056Z", + "title": "Form Title", + "created": "2017-10-02T15:26:21.221Z", + "admin": this.sampleUser, + "design": { + "colors": { + "buttonTextColor": "#333", + "buttonColor": "#fff", + "answerColor": "#333", + "questionColor": "#333", + "backgroundColor": "#fff" + } + }, + "isLive": true, + "hideFooter": false, + "endPage": { + "buttons": [], + "buttonText": "Go back to Form", + "title": "Thank you for filling out the form", + "showEnd": false + }, + "startPage": { + "buttons": [], + "introButtonText": "Start", + "introTitle": "Welcome to Form", + "showStart": false + }, + "submissions": [], + "form_fields": [{ + "globalId": "hSsZT02ICgcdvLTrbwCyYjl19qG9gQdAzO7ZDF2Esj4", + "lastModified": "2017-10-19T00:46:24.053Z", + "title": "First Name", + "fieldType": "textfield", + "fieldValue": "", + "logicJump": { + "expressionString": "field == static", + "jumpTo": "59e7f5d242a56fca5bf79365", + "valueB": "hello", + "_id": "59e7f5c442a56fca5bf7935e", + "enabled": true, + "id": "59e7f5c442a56fca5bf7935e" + }, + "_id": "59e7f5c442a56fca5bf7935d", + "created": "2017-10-19T00:45:56.855Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, { + "globalId": "N2DthDVEJfXvNU4JsYyax6PrCbHzump8QTnyc1hnAVR", + "lastModified": "2017-10-19T00:46:24.054Z", + "title": "nascar", + "fieldType": "checkbox", + "fieldValue": "", + "logicJump": { + "_id": "59e7f5c842a56fca5bf79361", + "enabled": false, + "id": "59e7f5c842a56fca5bf79361" + }, + "_id": "59e7f5c842a56fca5bf79360", + "created": "2017-10-19T00:46:00.484Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, { + "globalId": "7vnFgEhKCZWwb6rR29Lat7mePmBK05fDTashc3modje", + "lastModified": "2017-10-19T00:46:24.055Z", + "title": "hockey", + "fieldType": "checkbox", + "fieldValue": "", + "logicJump": { + "_id": "59e7f5d242a56fca5bf79366", + "enabled": false, + "id": "59e7f5d242a56fca5bf79366" + }, + "_id": "59e7f5d242a56fca5bf79365", + "created": "2017-10-19T00:46:10.619Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }], + "analytics": { + "visitors": [], + "fields": [{ + "field": { + "globalId": "hSsZT02ICgcdvLTrbwCyYjl19qG9gQdAzO7ZDF2Esj4", + "lastModified": "2017-10-19T00:46:24.053Z", + "title": "Short Text3", + "fieldType": "textfield", + "fieldValue": "", + "logicJump": { + "expressionString": "field == static", + "jumpTo": "59e7f5d242a56fca5bf79365", + "valueB": "hello", + "_id": "59e7f5c442a56fca5bf7935e", + "enabled": true, + "id": "59e7f5c442a56fca5bf7935e" + }, + "_id": "59e7f5c442a56fca5bf7935d", + "created": "2017-10-19T00:45:56.855Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, + "dropoffRate": 0, + "continueRate": 0, + "totalViews": 0, + "responses": 0, + "dropoffViews": 0 + }, { + "field": { + "globalId": "N2DthDVEJfXvNU4JsYyax6PrCbHzump8QTnyc1hnAVR", + "lastModified": "2017-10-19T00:46:24.054Z", + "title": "Short Text4", + "fieldType": "textfield", + "fieldValue": "", + "logicJump": { + "_id": "59e7f5c842a56fca5bf79361", + "enabled": false, + "id": "59e7f5c842a56fca5bf79361" + }, + "_id": "59e7f5c842a56fca5bf79360", + "created": "2017-10-19T00:46:00.484Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, + "dropoffRate": 0, + "continueRate": 0, + "totalViews": 0, + "responses": 0, + "dropoffViews": 0 + }, { + "field": { + "globalId": "7vnFgEhKCZWwb6rR29Lat7mePmBK05fDTashc3modje", + "lastModified": "2017-10-19T00:46:24.055Z", + "title": "Short Text5", + "fieldType": "textfield", + "fieldValue": "", + "logicJump": { + "_id": "59e7f5d242a56fca5bf79366", + "enabled": false, + "id": "59e7f5d242a56fca5bf79366" + }, + "_id": "59e7f5d242a56fca5bf79365", + "created": "2017-10-19T00:46:10.619Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, + "dropoffRate": 0, + "continueRate": 0, + "totalViews": 0, + "responses": 0, + "dropoffViews": 0 + }], + "conversionRate": 0, + "submissions": 0, + "views": 0 + }, + "language": "en", + "id": "59d25a9d413a7a3106878556" + }, + + sampleForm2: { + "_id": "52f6d0f87f5a407a384220e3", + "lastModified": "2017-10-19T00:46:24.056Z", + "title": "Form Title2", + "created": "2017-10-02T15:26:21.221Z", + "admin": this.sampleUser, + "design": { + "colors": { + "buttonTextColor": "#333", + "buttonColor": "#fff", + "answerColor": "#333", + "questionColor": "#333", + "backgroundColor": "#fff" + } + }, + "isLive": true, + "hideFooter": false, + "endPage": { + "buttons": [], + "buttonText": "Go back to Form", + "title": "Thank you for filling out the form", + "showEnd": false + }, + "startPage": { + "buttons": [], + "introButtonText": "Start", + "introTitle": "Welcome to Form", + "showStart": false + }, + "submissions": [], + "form_fields": [{ + "globalId": "hSsZT02ICgcdvLTrbwCyYjl19qG9gQdAzO7ZDF2Esj4", + "lastModified": "2017-10-19T00:46:24.053Z", + "title": "First Name", + "fieldType": "textfield", + "fieldValue": "", + "logicJump": { + "expressionString": "field == static", + "jumpTo": "59e7f5d242a56fca5bf79365", + "valueB": "hello", + "_id": "59e7f5c442a56fca5bf7935e", + "enabled": true, + "id": "59e7f5c442a56fca5bf7935e" + }, + "_id": "59e7f5c442a56fca5bf7935d", + "created": "2017-10-19T00:45:56.855Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, { + "globalId": "N2DthDVEJfXvNU4JsYyax6PrCbHzump8QTnyc1hnAVR", + "lastModified": "2017-10-19T00:46:24.054Z", + "title": "nascar", + "fieldType": "checkbox", + "fieldValue": "", + "logicJump": { + "_id": "59e7f5c842a56fca5bf79361", + "enabled": false, + "id": "59e7f5c842a56fca5bf79361" + }, + "_id": "59e7f5c842a56fca5bf79360", + "created": "2017-10-19T00:46:00.484Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, { + "globalId": "7vnFgEhKCZWwb6rR29Lat7mePmBK05fDTashc3modje", + "lastModified": "2017-10-19T00:46:24.055Z", + "title": "hockey", + "fieldType": "checkbox", + "fieldValue": "", + "logicJump": { + "_id": "59e7f5d242a56fca5bf79366", + "enabled": false, + "id": "59e7f5d242a56fca5bf79366" + }, + "_id": "59e7f5d242a56fca5bf79365", + "created": "2017-10-19T00:46:10.619Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }], + "analytics": { + "visitors": [], + "fields": [{ + "field": { + "globalId": "hSsZT02ICgcdvLTrbwCyYjl19qG9gQdAzO7ZDF2Esj4", + "lastModified": "2017-10-19T00:46:24.053Z", + "title": "Short Text3", + "fieldType": "textfield", + "fieldValue": "", + "logicJump": { + "expressionString": "field == static", + "jumpTo": "59e7f5d242a56fca5bf79365", + "valueB": "hello", + "_id": "59e7f5c442a56fca5bf7935e", + "enabled": true, + "id": "59e7f5c442a56fca5bf7935e" + }, + "_id": "59e7f5c442a56fca5bf7935d", + "created": "2017-10-19T00:45:56.855Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, + "dropoffRate": 0, + "continueRate": 0, + "totalViews": 0, + "responses": 0, + "dropoffViews": 0 + }, { + "field": { + "globalId": "N2DthDVEJfXvNU4JsYyax6PrCbHzump8QTnyc1hnAVR", + "lastModified": "2017-10-19T00:46:24.054Z", + "title": "Short Text4", + "fieldType": "textfield", + "fieldValue": "", + "logicJump": { + "_id": "59e7f5c842a56fca5bf79361", + "enabled": false, + "id": "59e7f5c842a56fca5bf79361" + }, + "_id": "59e7f5c842a56fca5bf79360", + "created": "2017-10-19T00:46:00.484Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, + "dropoffRate": 0, + "continueRate": 0, + "totalViews": 0, + "responses": 0, + "dropoffViews": 0 + }, { + "field": { + "globalId": "7vnFgEhKCZWwb6rR29Lat7mePmBK05fDTashc3modje", + "lastModified": "2017-10-19T00:46:24.055Z", + "title": "Short Text5", + "fieldType": "textfield", + "fieldValue": "", + "logicJump": { + "_id": "59e7f5d242a56fca5bf79366", + "enabled": false, + "id": "59e7f5d242a56fca5bf79366" + }, + "_id": "59e7f5d242a56fca5bf79365", + "created": "2017-10-19T00:46:10.619Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, + "dropoffRate": 0, + "continueRate": 0, + "totalViews": 0, + "responses": 0, + "dropoffViews": 0 + }], + "conversionRate": 0, + "submissions": 0, + "views": 0 + }, + "language": "en", + "id": "59d25a9d413a7a3106878556" + }, + + sampleForm3: { + "_id": "2fab9ed873937f0e1dea0ce1", + "lastModified": "2017-10-19T00:46:24.056Z", + "title": "Form Title3", + "created": "2017-10-02T15:26:21.221Z", + "admin": this.sampleUser, + "design": { + "colors": { + "buttonTextColor": "#333", + "buttonColor": "#fff", + "answerColor": "#333", + "questionColor": "#333", + "backgroundColor": "#fff" + } + }, + "isLive": true, + "hideFooter": false, + "endPage": { + "buttons": [], + "buttonText": "Go back to Form", + "title": "Thank you for filling out the form", + "showEnd": false + }, + "startPage": { + "buttons": [], + "introButtonText": "Start", + "introTitle": "Welcome to Form", + "showStart": false + }, + "submissions": [], + "form_fields": [{ + "globalId": "hSsZT02ICgcdvLTrbwCyYjl19qG9gQdAzO7ZDF2Esj4", + "lastModified": "2017-10-19T00:46:24.053Z", + "title": "First Name", + "fieldType": "textfield", + "fieldValue": "", + "logicJump": { + "expressionString": "field == static", + "jumpTo": "59e7f5d242a56fca5bf79365", + "valueB": "hello", + "_id": "59e7f5c442a56fca5bf7935e", + "enabled": true, + "id": "59e7f5c442a56fca5bf7935e" + }, + "_id": "59e7f5c442a56fca5bf7935d", + "created": "2017-10-19T00:45:56.855Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, { + "globalId": "N2DthDVEJfXvNU4JsYyax6PrCbHzump8QTnyc1hnAVR", + "lastModified": "2017-10-19T00:46:24.054Z", + "title": "nascar", + "fieldType": "checkbox", + "fieldValue": "", + "logicJump": { + "_id": "59e7f5c842a56fca5bf79361", + "enabled": false, + "id": "59e7f5c842a56fca5bf79361" + }, + "_id": "59e7f5c842a56fca5bf79360", + "created": "2017-10-19T00:46:00.484Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, { + "globalId": "7vnFgEhKCZWwb6rR29Lat7mePmBK05fDTashc3modje", + "lastModified": "2017-10-19T00:46:24.055Z", + "title": "hockey", + "fieldType": "checkbox", + "fieldValue": "", + "logicJump": { + "_id": "59e7f5d242a56fca5bf79366", + "enabled": false, + "id": "59e7f5d242a56fca5bf79366" + }, + "_id": "59e7f5d242a56fca5bf79365", + "created": "2017-10-19T00:46:10.619Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }], + "analytics": { + "visitors": [], + "fields": [{ + "field": { + "globalId": "hSsZT02ICgcdvLTrbwCyYjl19qG9gQdAzO7ZDF2Esj4", + "lastModified": "2017-10-19T00:46:24.053Z", + "title": "Short Text3", + "fieldType": "textfield", + "fieldValue": "", + "logicJump": { + "expressionString": "field == static", + "jumpTo": "59e7f5d242a56fca5bf79365", + "valueB": "hello", + "_id": "59e7f5c442a56fca5bf7935e", + "enabled": true, + "id": "59e7f5c442a56fca5bf7935e" + }, + "_id": "59e7f5c442a56fca5bf7935d", + "created": "2017-10-19T00:45:56.855Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, + "dropoffRate": 0, + "continueRate": 0, + "totalViews": 0, + "responses": 0, + "dropoffViews": 0 + }, { + "field": { + "globalId": "N2DthDVEJfXvNU4JsYyax6PrCbHzump8QTnyc1hnAVR", + "lastModified": "2017-10-19T00:46:24.054Z", + "title": "Short Text4", + "fieldType": "textfield", + "fieldValue": "", + "logicJump": { + "_id": "59e7f5c842a56fca5bf79361", + "enabled": false, + "id": "59e7f5c842a56fca5bf79361" + }, + "_id": "59e7f5c842a56fca5bf79360", + "created": "2017-10-19T00:46:00.484Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, + "dropoffRate": 0, + "continueRate": 0, + "totalViews": 0, + "responses": 0, + "dropoffViews": 0 + }, { + "field": { + "globalId": "7vnFgEhKCZWwb6rR29Lat7mePmBK05fDTashc3modje", + "lastModified": "2017-10-19T00:46:24.055Z", + "title": "Short Text5", + "fieldType": "textfield", + "fieldValue": "", + "logicJump": { + "_id": "59e7f5d242a56fca5bf79366", + "enabled": false, + "id": "59e7f5d242a56fca5bf79366" + }, + "_id": "59e7f5d242a56fca5bf79365", + "created": "2017-10-19T00:46:10.619Z", + "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], + "deletePreserved": false, + "disabled": false, + "required": true, + "fieldOptions": [], + "description": "", + "isSubmission": false + }, + "dropoffRate": 0, + "continueRate": 0, + "totalViews": 0, + "responses": 0, + "dropoffViews": 0 + }], + "conversionRate": 0, + "submissions": 0, + "views": 0 + }, + "language": "en", + "id": "59d25a9d413a7a3106878556" + }, + + sampleFormList: [this.sampleForm1, this.sampleForm2, this.sampleForm3], +} \ No newline at end of file From 538030c5519ded0340786e04e637f817901524b4 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 12:01:30 -0700 Subject: [PATCH 02/29] got edit-form-directive tests to pass --- .../admin-form.client.controller.test.js | 44 ++++++++--------- .../edit-form.client.directive.test.js | 48 ++++++++++++------- 2 files changed, 53 insertions(+), 39 deletions(-) diff --git a/public/modules/forms/tests/unit/controllers/admin-form.client.controller.test.js b/public/modules/forms/tests/unit/controllers/admin-form.client.controller.test.js index b94d75b7..d49d8914 100644 --- a/public/modules/forms/tests/unit/controllers/admin-form.client.controller.test.js +++ b/public/modules/forms/tests/unit/controllers/admin-form.client.controller.test.js @@ -57,28 +57,6 @@ _id: '525a8422f6d0f87f0e407a33' }; - var newFakeModal = function(){ - var modal = { - opened: true, - close: function( item ) { - //The user clicked OK on the modal dialog, call the stored confirm callback with the selected item - this.opened = false; - }, - dismiss: function( type ) { - //The user clicked cancel on the modal dialog, call the stored cancel callback - this.opened = false; - }, - result: { - then: function (cb) { - if(cb && typeof cb === 'function'){ - cb(); - } - } - } - }; - return modal; - }; - //Mock myForm Service beforeEach(module(function($provide) { $provide.service('myForm', function($q) { @@ -166,6 +144,28 @@ }); })); + var newFakeModal = function(){ + var modal = { + opened: true, + close: function( item ) { + //The user clicked OK on the modal dialog, call the stored confirm callback with the selected item + this.opened = false; + }, + dismiss: function( type ) { + //The user clicked cancel on the modal dialog, call the stored cancel callback + this.opened = false; + }, + result: { + then: function (cb) { + if(cb && typeof cb === 'function'){ + cb(); + } + } + } + }; + return modal; + }; + //Mock $uibModal beforeEach(inject(function($uibModal) { var modal = newFakeModal(); diff --git a/public/modules/forms/tests/unit/directives/edit-form.client.directive.test.js b/public/modules/forms/tests/unit/directives/edit-form.client.directive.test.js index aa1710ca..5ad0047b 100644 --- a/public/modules/forms/tests/unit/directives/edit-form.client.directive.test.js +++ b/public/modules/forms/tests/unit/directives/edit-form.client.directive.test.js @@ -80,6 +80,34 @@ }); })); + var newFakeModal = function(){ + var modal = { + opened: true, + close: function( item ) { + //The user clicked OK on the modal dialog, call the stored confirm callback with the selected item + this.opened = false; + }, + dismiss: function( type ) { + //The user clicked cancel on the modal dialog, call the stored cancel callback + this.opened = false; + }, + result: { + then: function (cb) { + if(cb && typeof cb === 'function'){ + cb(); + } + } + } + }; + return modal; + }; + + //Mock $uibModal + beforeEach(inject(function($uibModal) { + var modal = newFakeModal(); + spyOn($uibModal, 'open').and.returnValue(modal); + })); + beforeEach(inject(function($compile, $controller, $rootScope, _$httpBackend_) { //Instantiate directive. var tmp_scope = $rootScope.$new(); @@ -115,26 +143,12 @@ scope.myform = _.cloneDeep(sampleForm); }); - it('$scope.addNewField() should ADD a new field to $scope.myform.form_fields', function() { + it('$scope.addNewField() should open the new field modal', function() { //Run controller methods - scope.addNewField(true, 'textfield'); + scope.addNewField('textfield'); - var expectedFormField = { - title: 'Short Text2', - fieldType: 'textfield', - fieldValue: '', - required: true, - disabled: false, - deletePreserved: false, - logicJump: Object({ }) - }; - - var actualFormField = _.cloneDeep(_.last(scope.myform.form_fields)); - delete actualFormField._id; - - expect(scope.myform.form_fields.length).toEqual(sampleForm.form_fields.length+1); - expect(actualFormField).toEqualData(expectedFormField); + expect(scope.editFieldModal.opened).toBeTruthy(); }); it('$scope.deleteField() should DELETE a field to $scope.myform.form_fields', function() { From 7d65f0161b5f56a91e3f49487486a0d1adc8b571 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 12:07:42 -0700 Subject: [PATCH 03/29] removed duplicate translation keyword for form admin panel --- .../forms/admin/config/i18n/english.js | 2 +- .../modules/forms/admin/config/i18n/french.js | 2 +- .../modules/forms/admin/config/i18n/german.js | 2 +- .../forms/admin/config/i18n/italian.js | 2 +- .../forms/admin/config/i18n/spanish.js | 2 +- .../services/form-fields.client.service.js | 2 +- .../field-icon.client.directive.test.js | 58 +++++++++++++++++++ 7 files changed, 64 insertions(+), 6 deletions(-) diff --git a/public/modules/forms/admin/config/i18n/english.js b/public/modules/forms/admin/config/i18n/english.js index 84e5a848..3759d236 100644 --- a/public/modules/forms/admin/config/i18n/english.js +++ b/public/modules/forms/admin/config/i18n/english.js @@ -153,7 +153,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid MULTIPLE_CHOICE: 'Multiple Choice', DROPDOWN: 'Dropdown', DATE: 'Date', - PARAGRAPH_T: 'Paragraph', + PARAGRAPH_FIELD: 'Paragraph', YES_NO: 'Yes/No', LEGAL: 'Legal', RATING: 'Rating', diff --git a/public/modules/forms/admin/config/i18n/french.js b/public/modules/forms/admin/config/i18n/french.js index cc2187e8..d9675934 100644 --- a/public/modules/forms/admin/config/i18n/french.js +++ b/public/modules/forms/admin/config/i18n/french.js @@ -152,7 +152,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid MULTIPLE_CHOICE: 'Choix multiple', DROPDOWN: 'Menu Déroulant', DATE: 'Date', - PARAGRAPH_T: "Paragraphe", + PARAGRAPH_FIELD: "Paragraphe", OUI_NON: 'Oui / Non', LEGAL: 'Légal', RATING: "Évaluation", diff --git a/public/modules/forms/admin/config/i18n/german.js b/public/modules/forms/admin/config/i18n/german.js index 77d40107..fa3dd2b3 100644 --- a/public/modules/forms/admin/config/i18n/german.js +++ b/public/modules/forms/admin/config/i18n/german.js @@ -151,7 +151,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid MULTIPLE_CHOICE: 'Mehrfachauswahl', DROPDOWN: 'Dropdown-Liste', DATE: 'Datum', - PARAGRAPH_T: "Absatz", + PARAGRAPH_FIELD: "Absatz", YES_NO: 'Ja / Nein', LEGAL: "Rechtliche", RATING: 'Bewertung', diff --git a/public/modules/forms/admin/config/i18n/italian.js b/public/modules/forms/admin/config/i18n/italian.js index 17665625..1414e891 100644 --- a/public/modules/forms/admin/config/i18n/italian.js +++ b/public/modules/forms/admin/config/i18n/italian.js @@ -152,7 +152,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid MULTIPLE_CHOICE: 'Scelta multipla', DROPDOWN: 'Dropdown', DATE: 'Data', - PARAGRAPH_T: 'Paragrafo', + PARAGRAPH_FIELD: 'Paragrafo', YES_NO: 'Sì / no', LEGAL: 'Legale', RATING: 'Valutazione', diff --git a/public/modules/forms/admin/config/i18n/spanish.js b/public/modules/forms/admin/config/i18n/spanish.js index 8e0985ed..26c7199d 100644 --- a/public/modules/forms/admin/config/i18n/spanish.js +++ b/public/modules/forms/admin/config/i18n/spanish.js @@ -153,7 +153,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid MULTIPLE_CHOICE: 'Opciones múltiples', DROPDOWN: 'Desplegable', DATE: 'Fecha', - PARAGRAPH_T: 'Párrafo', + PARAGRAPH_FIELD: 'Párrafo', YES_NO: 'Si/No', LEGAL: 'Legal', RATING: 'Puntaje', diff --git a/public/modules/forms/admin/services/form-fields.client.service.js b/public/modules/forms/admin/services/form-fields.client.service.js index dd1d7dec..6b7c050c 100644 --- a/public/modules/forms/admin/services/form-fields.client.service.js +++ b/public/modules/forms/admin/services/form-fields.client.service.js @@ -28,7 +28,7 @@ angular.module('forms').service('FormFields', [ '$rootScope', '$translate', '$wi }, { name : 'textarea', - value : $translate.instant('PARAGRAPH'), + value : $translate.instant('PARAGRAPH_FIELD'), }, { name : 'yes_no', diff --git a/public/modules/forms/tests/unit/directives/field-icon.client.directive.test.js b/public/modules/forms/tests/unit/directives/field-icon.client.directive.test.js index fbb89193..14ca515a 100644 --- a/public/modules/forms/tests/unit/directives/field-icon.client.directive.test.js +++ b/public/modules/forms/tests/unit/directives/field-icon.client.directive.test.js @@ -25,6 +25,64 @@ 'number': 'fa fa-slack' }; + //Mock FormFields Service + beforeEach(module(function($provide) { + $provide.service('FormFields', function() { + return { + types: [ + { + name : 'textfield', + value : 'Short Text' + }, + { + name : 'email', + value : 'Email' + }, + { + name : 'radio', + value : 'Muliple Choice' + }, + { + name : 'dropdown', + value : 'Dropdown' + }, + { + name : 'date', + value : 'Date' + }, + { + name : 'textarea', + value : 'Paragraph', + }, + { + 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' + } + ] + }; + }); + })); + // Load the main application module beforeEach(module(ApplicationConfiguration.applicationModuleName)); From ebcc0c63cd447d9b6aa5f02ec60ac8aeaa9b2b62 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 12:13:22 -0700 Subject: [PATCH 04/29] fixed field-icon tests --- .../field-icon.client.directive.test.js | 119 +++++++++--------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/public/modules/forms/tests/unit/directives/field-icon.client.directive.test.js b/public/modules/forms/tests/unit/directives/field-icon.client.directive.test.js index 14ca515a..8be987de 100644 --- a/public/modules/forms/tests/unit/directives/field-icon.client.directive.test.js +++ b/public/modules/forms/tests/unit/directives/field-icon.client.directive.test.js @@ -25,71 +25,72 @@ 'number': 'fa fa-slack' }; - //Mock FormFields Service - beforeEach(module(function($provide) { - $provide.service('FormFields', function() { - return { - types: [ - { - name : 'textfield', - value : 'Short Text' - }, - { - name : 'email', - value : 'Email' - }, - { - name : 'radio', - value : 'Muliple Choice' - }, - { - name : 'dropdown', - value : 'Dropdown' - }, - { - name : 'date', - value : 'Date' - }, - { - name : 'textarea', - value : 'Paragraph', - }, - { - 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' - } - ] - }; - }); - })); + var FormFields = { + types: [ + { + name : 'textfield', + value : 'Short Text' + }, + { + name : 'email', + value : 'Email' + }, + { + name : 'radio', + value : 'Muliple Choice' + }, + { + name : 'dropdown', + value : 'Dropdown' + }, + { + name : 'date', + value : 'Date' + }, + { + name : 'textarea', + value : 'Paragraph', + }, + { + 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' + } + ] + }; // Load the main application module beforeEach(module(ApplicationConfiguration.applicationModuleName)); + //Mock FormFields Service + beforeEach(module(function($provide) { + $provide.service('FormFields', function() { + return FormFields; + }); + })); + beforeEach(inject(function ($rootScope, _FormFields_) { scope = $rootScope.$new(); - FormFields = _FormFields_; - })); + })); it('should be able render all field-icon types', inject(function($compile) { var currType, currClass; From f42709214409c98f285c32c96935b9d20a49726d Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 12:16:34 -0700 Subject: [PATCH 05/29] fixed field directive tests --- .../field-icon.client.directive.test.js | 10 ++- .../directives/field.client.directive.test.js | 63 ++++++++++++++++++- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/public/modules/forms/tests/unit/directives/field-icon.client.directive.test.js b/public/modules/forms/tests/unit/directives/field-icon.client.directive.test.js index 8be987de..7dfc6823 100644 --- a/public/modules/forms/tests/unit/directives/field-icon.client.directive.test.js +++ b/public/modules/forms/tests/unit/directives/field-icon.client.directive.test.js @@ -5,7 +5,6 @@ describe('FieldIcon Directive Tests', function() { // Initialize global variables var scope, - FormFields, faClasses = { 'textfield': 'fa fa-pencil-square-o', 'dropdown': 'fa fa-th-list', @@ -25,6 +24,10 @@ 'number': 'fa fa-slack' }; + // Load the main application module + beforeEach(module(ApplicationConfiguration.applicationModuleName)); + + //Mock FormFields Service var FormFields = { types: [ { @@ -77,11 +80,6 @@ } ] }; - - // Load the main application module - beforeEach(module(ApplicationConfiguration.applicationModuleName)); - - //Mock FormFields Service beforeEach(module(function($provide) { $provide.service('FormFields', function() { return FormFields; diff --git a/public/modules/forms/tests/unit/directives/field.client.directive.test.js b/public/modules/forms/tests/unit/directives/field.client.directive.test.js index 462951ca..d5d3c89d 100644 --- a/public/modules/forms/tests/unit/directives/field.client.directive.test.js +++ b/public/modules/forms/tests/unit/directives/field.client.directive.test.js @@ -5,11 +5,63 @@ describe('Field Directive Tests', function() { // Initialize global variables var scope, - FormFields, $templateCache, $httpBackend, $compile; + var FormFields = { + types: [ + { + name : 'textfield', + value : 'Short Text' + }, + { + name : 'email', + value : 'Email' + }, + { + name : 'radio', + value : 'Muliple Choice' + }, + { + name : 'dropdown', + value : 'Dropdown' + }, + { + name : 'date', + value : 'Date' + }, + { + name : 'textarea', + value : 'Paragraph', + }, + { + 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' + } + ] + }; + var sampleUser = { firstName: 'Full', lastName: 'Name', @@ -65,9 +117,15 @@ beforeEach(module('ngSanitize', 'ui.select')); + //Mock FormFields Service + beforeEach(module(function($provide) { + $provide.service('FormFields', function() { + return FormFields; + }); + })); + beforeEach(inject(function($rootScope, _FormFields_, _$compile_, _$httpBackend_) { scope = $rootScope.$new(); - FormFields = _FormFields_; // Point global variables to injected services $httpBackend = _$httpBackend_; @@ -76,6 +134,7 @@ $compile = _$compile_; })); + it('should be able to render all field types in html', inject(function($rootScope) { scope.fields = sampleFields; From 6fbfa35473dac6acede6295e19197a0b8d5c5590 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 12:17:54 -0700 Subject: [PATCH 06/29] fixed on-finish-render directive tests --- .../on-finish-render.client.directive.test.js | 66 +++++++++++++++++-- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/public/modules/forms/tests/unit/directives/on-finish-render.client.directive.test.js b/public/modules/forms/tests/unit/directives/on-finish-render.client.directive.test.js index 188022c4..9f48ab6a 100644 --- a/public/modules/forms/tests/unit/directives/on-finish-render.client.directive.test.js +++ b/public/modules/forms/tests/unit/directives/on-finish-render.client.directive.test.js @@ -4,15 +4,73 @@ // Forms Controller Spec describe('onFinishRender Directive Tests', function() { // Initialize global variables - var scope, - FormFields; + var scope; + + var FormFields = { + types: [ + { + name : 'textfield', + value : 'Short Text' + }, + { + name : 'email', + value : 'Email' + }, + { + name : 'radio', + value : 'Muliple Choice' + }, + { + name : 'dropdown', + value : 'Dropdown' + }, + { + name : 'date', + value : 'Date' + }, + { + name : 'textarea', + value : 'Paragraph', + }, + { + 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' + } + ] + }; // Load the main application module beforeEach(module(ApplicationConfiguration.applicationModuleName)); - beforeEach(inject(function ($rootScope, _FormFields_) { + //Mock FormFields Service + beforeEach(module(function($provide) { + $provide.service('FormFields', function() { + return FormFields; + }); + })); + + beforeEach(inject(function ($rootScope) { scope = $rootScope.$new(); - FormFields = _FormFields_; spyOn($rootScope, '$broadcast'); })); From 88fbf9e51fadd0b46ac418c2c1dd0507546d2196 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 12:20:49 -0700 Subject: [PATCH 07/29] got user tests to pass --- .../users/controllers/authentication.client.controller.js | 2 +- .../unit/controllers/authentication.client.controller.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/modules/users/controllers/authentication.client.controller.js b/public/modules/users/controllers/authentication.client.controller.js index b2bb6c89..dc59f9f1 100755 --- a/public/modules/users/controllers/authentication.client.controller.js +++ b/public/modules/users/controllers/authentication.client.controller.js @@ -9,7 +9,7 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca $scope.forms = {}; $scope.signin = function() { - if(!$scope.forms.signinForm.$invalid){ + if($scope.forms && $scope.forms.hasOwnProperty('siginForm') && !$scope.forms.signinForm.$invalid){ User.login($scope.credentials).then( function(response) { Auth.login(response); diff --git a/public/modules/users/tests/unit/controllers/authentication.client.controller.test.js b/public/modules/users/tests/unit/controllers/authentication.client.controller.test.js index 363f1f37..604f90e6 100644 --- a/public/modules/users/tests/unit/controllers/authentication.client.controller.test.js +++ b/public/modules/users/tests/unit/controllers/authentication.client.controller.test.js @@ -80,7 +80,7 @@ // Load the main application module beforeEach(module(ApplicationConfiguration.applicationModuleName)); - + beforeEach(module('module-templates')); beforeEach(module('stateMock')); // Mock Users Service From 759a4efdd124770bf4c5f142553fa8ca947a6cfe Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 12:44:12 -0700 Subject: [PATCH 08/29] got all tests to pass --- app/controllers/forms.server.controller.js | 5 +---- .../users.authentication.server.controller.js | 2 +- app/tests/form.server.routes.test.js | 3 ++- app/tests/form_submission.model.test.js | 5 +++-- app/views/500.server.view.pug | 2 +- config/express.js | 22 +++++++++---------- config/strategies/local.js | 2 -- 7 files changed, 18 insertions(+), 23 deletions(-) diff --git a/app/controllers/forms.server.controller.js b/app/controllers/forms.server.controller.js index 005841bb..32721440 100644 --- a/app/controllers/forms.server.controller.js +++ b/app/controllers/forms.server.controller.js @@ -88,15 +88,13 @@ exports.listSubmissions = function(req, res) { } res.json(_submissions); }); - }; /** * Create a new form */ exports.create = function(req, res) { - debugger; - + if(!req.body.form){ return res.status(401).send({ message: 'Invalid Input' @@ -107,7 +105,6 @@ exports.create = function(req, res) { form.admin = req.user._id; form.save(function(err) { - debugger; if (err) { return res.status(500).send({ message: errorHandler.getErrorMessage(err) diff --git a/app/controllers/users/users.authentication.server.controller.js b/app/controllers/users/users.authentication.server.controller.js index 46213490..5be06c43 100755 --- a/app/controllers/users/users.authentication.server.controller.js +++ b/app/controllers/users/users.authentication.server.controller.js @@ -190,7 +190,7 @@ exports.signin = function(req, res, next) { */ exports.signout = function(req, res) { if(req.cookies.hasOwnProperty('userLang')){ - res.destroyCookie('userLang'); + res.clearCookie('userLang'); } req.logout(); return res.status(200).send('You have successfully logged out.'); diff --git a/app/tests/form.server.routes.test.js b/app/tests/form.server.routes.test.js index e1aa2654..31faaae7 100644 --- a/app/tests/form.server.routes.test.js +++ b/app/tests/form.server.routes.test.js @@ -68,7 +68,6 @@ describe('Form Routes Unit tests', function() { .send({form: myForm}) .expect(401) .end(function(FormSaveErr, FormSaveRes) { - // Call the assertion callback done(FormSaveErr); }); @@ -275,6 +274,8 @@ describe('Form Routes Unit tests', function() { authenticatedSession.get('/auth/signout') .expect(200) .end(function(signoutErr, signoutRes) { + console.log(signoutRes.error.text); + // Handle signout error if (signoutErr) return done(signoutErr); authenticatedSession.destroy(); diff --git a/app/tests/form_submission.model.test.js b/app/tests/form_submission.model.test.js index f60e599e..09442c81 100644 --- a/app/tests/form_submission.model.test.js +++ b/app/tests/form_submission.model.test.js @@ -199,6 +199,7 @@ describe('FormSubmission Model Unit Tests:', function() { it('should preserve deleted form_fields that have submissions without any problems', function(done) { + var fieldPropertiesToOmit = ['deletePreserved', 'globalId', 'lastModified', 'created', '_id', 'submissionId', 'isSubmission', 'validFieldTypes', 'title']; var old_fields = myForm.toObject().form_fields; var new_form_fields = _.clone(myForm.toObject().form_fields); new_form_fields.splice(0, 1); @@ -210,8 +211,8 @@ describe('FormSubmission Model Unit Tests:', function() { should.not.exist(err); should.exist(_form.form_fields); - var actual_fields = _.deepOmit(_form.toObject().form_fields, ['deletePreserved', 'globalId', 'lastModified', 'created', '_id', 'submissionId']); - old_fields = _.deepOmit(old_fields, ['deletePreserved', 'globalId', 'lastModified', 'created', '_id', 'submissionId']); + var actual_fields = _.deepOmit(_form.toObject().form_fields, fieldPropertiesToOmit); + old_fields = _.deepOmit(old_fields, fieldPropertiesToOmit); should.deepEqual(actual_fields, old_fields, 'old form_fields not equal to newly saved form_fields'); done(); diff --git a/app/views/500.server.view.pug b/app/views/500.server.view.pug index 688a9af0..3c6fc1b1 100644 --- a/app/views/500.server.view.pug +++ b/app/views/500.server.view.pug @@ -5,7 +5,7 @@ block content div.row.valign h3.col-md-12.text-center=__('500_HEADER') div.col-md-4.col-md-offset-4 - if process.env.NODE_ENV == 'development' + if process.env.NODE_ENV == 'development' || process.env.NODE_ENV == 'test' div.col-md-12.text-center(style="padding-bottom: 50px;") | #{error} else diff --git a/config/express.js b/config/express.js index 1da3f4a1..7637bf4f 100755 --- a/config/express.js +++ b/config/express.js @@ -263,9 +263,13 @@ module.exports = function(db) { //Visitor Language Detection app.use(function(req, res, next) { var acceptLanguage = req.headers['accept-language']; - var languages = acceptLanguage.match(/[a-z]{2}(?!-)/g) || []; + var languages, supportedLanguage; + + if(acceptLanguage){ + languages = acceptLanguage.match(/[a-z]{2}(?!-)/g) || []; + supportedLanguage = containsAnySupportedLanguages(languages); + } - var supportedLanguage = containsAnySupportedLanguages(languages); if(!req.user && supportedLanguage !== null){ var currLanguage = res.cookie('userLang'); @@ -320,16 +324,10 @@ module.exports = function(db) { // Log it client.captureError(err); - if(process.env.NODE_ENV === 'production'){ - res.status(500).render('500', { - error: 'Internal Server Error' - }); - } else { - // Error page - res.status(500).render('500', { - error: err.stack - }); - } + // Error page + res.status(500).render('500', { + error: err.stack + }); }); // Assume 404 since no middleware responded diff --git a/config/strategies/local.js b/config/strategies/local.js index 319324a6..174a0007 100755 --- a/config/strategies/local.js +++ b/config/strategies/local.js @@ -14,8 +14,6 @@ module.exports = function () { passwordField: 'password' }, function (username, password, done) { - console.log('\n\n\n\n\nusername: '+username); - console.log('password: '+password) User.findOne({ $or: [ {'username': username.toLowerCase()}, From aa554c8210026f16bbe389db259ac54b7c007591 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 12:59:12 -0700 Subject: [PATCH 09/29] added coveralls support --- .travis.yml | 2 + gruntfile.js | 16 +- package.json | 1 + tests/client/mockData.js | 588 --------------------------------------- 4 files changed, 6 insertions(+), 601 deletions(-) delete mode 100644 tests/client/mockData.js diff --git a/.travis.yml b/.travis.yml index e092c961..f03b879b 100755 --- a/.travis.yml +++ b/.travis.yml @@ -11,5 +11,7 @@ services: addons: code_climate: repo_token: 6c3a1b81a09b2338d6f30913c1bcad115026689752cbb499a0a25061cda6fbcf +script: + - npm travis after_script: - grunt coverage diff --git a/gruntfile.js b/gruntfile.js index 1ed5f52b..98759acd 100755 --- a/gruntfile.js +++ b/gruntfile.js @@ -204,18 +204,6 @@ module.exports = function(grunt) { singleRun: true } }, - protractor: { - options: { - configFile: 'protractor.conf.js', - keepAlive: true, - noColor: false - }, - e2e: { - options: { - args: {} // Target-specific arguments - } - } - }, mocha_istanbul: { coverage: { src: watchFiles.allTests, // a folder works nicely @@ -349,9 +337,11 @@ module.exports = function(grunt) { grunt.registerTask('setup', ['execute']); // Test task(s). - grunt.registerTask('test', ['lint:tests', 'test:server', 'test:client']); + grunt.registerTask('test', ['test:server', 'test:client']); grunt.registerTask('test:server', ['lint:tests', 'env:test', 'mochaTest']); grunt.registerTask('test:client', ['lint:tests', 'html2js:main', 'html2js:forms', 'env:test', 'karma:unit']); + grunt.registerTask('test:travis', ['env:test', 'html2js:main', 'html2js:forms', 'env:test', 'karma:unit', 'mochaTest', 'coveralls']); + grunt.registerTask('testdebug', ['env:test', 'karma:debug']); }; diff --git a/package.json b/package.json index c1e2f083..608280ba 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "generate": "all-contributors generate", "start": "grunt", "test": "grunt test", + "travis": "grunt test:travis", "postinstall": "bower install --config.interactive=false; grunt build;", "init": "node scripts/setup.js" }, diff --git a/tests/client/mockData.js b/tests/client/mockData.js deleted file mode 100644 index 4b37219b..00000000 --- a/tests/client/mockData.js +++ /dev/null @@ -1,588 +0,0 @@ -module.exports = { - sampleUser: { - "_id": "598cb79e43859500277bc804", - "lastModified": "2017-10-06T05:36:28.394Z", - "email": "test@test.com", - "username": "test1234", - "salt": null, - "__v": 0, - "resetPasswordExpires": "2017-10-06T06:36:28.391Z", - "resetPasswordToken": "2d95c01d79fb06c73691577cd82e5cce2ff616f1", - "created": "2017-08-10T19:44:30.601Z", - "language": "en", - "roles": ["user"], - "provider": "local", - "passwordHash": null, - "lastName": "Full", - "firstName": "Name" - }, - - sampleForm1: { - "_id": "59d25a9d413a7a3106878556", - "lastModified": "2017-10-19T00:46:24.056Z", - "title": "Form Title", - "created": "2017-10-02T15:26:21.221Z", - "admin": this.sampleUser, - "design": { - "colors": { - "buttonTextColor": "#333", - "buttonColor": "#fff", - "answerColor": "#333", - "questionColor": "#333", - "backgroundColor": "#fff" - } - }, - "isLive": true, - "hideFooter": false, - "endPage": { - "buttons": [], - "buttonText": "Go back to Form", - "title": "Thank you for filling out the form", - "showEnd": false - }, - "startPage": { - "buttons": [], - "introButtonText": "Start", - "introTitle": "Welcome to Form", - "showStart": false - }, - "submissions": [], - "form_fields": [{ - "globalId": "hSsZT02ICgcdvLTrbwCyYjl19qG9gQdAzO7ZDF2Esj4", - "lastModified": "2017-10-19T00:46:24.053Z", - "title": "First Name", - "fieldType": "textfield", - "fieldValue": "", - "logicJump": { - "expressionString": "field == static", - "jumpTo": "59e7f5d242a56fca5bf79365", - "valueB": "hello", - "_id": "59e7f5c442a56fca5bf7935e", - "enabled": true, - "id": "59e7f5c442a56fca5bf7935e" - }, - "_id": "59e7f5c442a56fca5bf7935d", - "created": "2017-10-19T00:45:56.855Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, { - "globalId": "N2DthDVEJfXvNU4JsYyax6PrCbHzump8QTnyc1hnAVR", - "lastModified": "2017-10-19T00:46:24.054Z", - "title": "nascar", - "fieldType": "checkbox", - "fieldValue": "", - "logicJump": { - "_id": "59e7f5c842a56fca5bf79361", - "enabled": false, - "id": "59e7f5c842a56fca5bf79361" - }, - "_id": "59e7f5c842a56fca5bf79360", - "created": "2017-10-19T00:46:00.484Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, { - "globalId": "7vnFgEhKCZWwb6rR29Lat7mePmBK05fDTashc3modje", - "lastModified": "2017-10-19T00:46:24.055Z", - "title": "hockey", - "fieldType": "checkbox", - "fieldValue": "", - "logicJump": { - "_id": "59e7f5d242a56fca5bf79366", - "enabled": false, - "id": "59e7f5d242a56fca5bf79366" - }, - "_id": "59e7f5d242a56fca5bf79365", - "created": "2017-10-19T00:46:10.619Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }], - "analytics": { - "visitors": [], - "fields": [{ - "field": { - "globalId": "hSsZT02ICgcdvLTrbwCyYjl19qG9gQdAzO7ZDF2Esj4", - "lastModified": "2017-10-19T00:46:24.053Z", - "title": "Short Text3", - "fieldType": "textfield", - "fieldValue": "", - "logicJump": { - "expressionString": "field == static", - "jumpTo": "59e7f5d242a56fca5bf79365", - "valueB": "hello", - "_id": "59e7f5c442a56fca5bf7935e", - "enabled": true, - "id": "59e7f5c442a56fca5bf7935e" - }, - "_id": "59e7f5c442a56fca5bf7935d", - "created": "2017-10-19T00:45:56.855Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, - "dropoffRate": 0, - "continueRate": 0, - "totalViews": 0, - "responses": 0, - "dropoffViews": 0 - }, { - "field": { - "globalId": "N2DthDVEJfXvNU4JsYyax6PrCbHzump8QTnyc1hnAVR", - "lastModified": "2017-10-19T00:46:24.054Z", - "title": "Short Text4", - "fieldType": "textfield", - "fieldValue": "", - "logicJump": { - "_id": "59e7f5c842a56fca5bf79361", - "enabled": false, - "id": "59e7f5c842a56fca5bf79361" - }, - "_id": "59e7f5c842a56fca5bf79360", - "created": "2017-10-19T00:46:00.484Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, - "dropoffRate": 0, - "continueRate": 0, - "totalViews": 0, - "responses": 0, - "dropoffViews": 0 - }, { - "field": { - "globalId": "7vnFgEhKCZWwb6rR29Lat7mePmBK05fDTashc3modje", - "lastModified": "2017-10-19T00:46:24.055Z", - "title": "Short Text5", - "fieldType": "textfield", - "fieldValue": "", - "logicJump": { - "_id": "59e7f5d242a56fca5bf79366", - "enabled": false, - "id": "59e7f5d242a56fca5bf79366" - }, - "_id": "59e7f5d242a56fca5bf79365", - "created": "2017-10-19T00:46:10.619Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, - "dropoffRate": 0, - "continueRate": 0, - "totalViews": 0, - "responses": 0, - "dropoffViews": 0 - }], - "conversionRate": 0, - "submissions": 0, - "views": 0 - }, - "language": "en", - "id": "59d25a9d413a7a3106878556" - }, - - sampleForm2: { - "_id": "52f6d0f87f5a407a384220e3", - "lastModified": "2017-10-19T00:46:24.056Z", - "title": "Form Title2", - "created": "2017-10-02T15:26:21.221Z", - "admin": this.sampleUser, - "design": { - "colors": { - "buttonTextColor": "#333", - "buttonColor": "#fff", - "answerColor": "#333", - "questionColor": "#333", - "backgroundColor": "#fff" - } - }, - "isLive": true, - "hideFooter": false, - "endPage": { - "buttons": [], - "buttonText": "Go back to Form", - "title": "Thank you for filling out the form", - "showEnd": false - }, - "startPage": { - "buttons": [], - "introButtonText": "Start", - "introTitle": "Welcome to Form", - "showStart": false - }, - "submissions": [], - "form_fields": [{ - "globalId": "hSsZT02ICgcdvLTrbwCyYjl19qG9gQdAzO7ZDF2Esj4", - "lastModified": "2017-10-19T00:46:24.053Z", - "title": "First Name", - "fieldType": "textfield", - "fieldValue": "", - "logicJump": { - "expressionString": "field == static", - "jumpTo": "59e7f5d242a56fca5bf79365", - "valueB": "hello", - "_id": "59e7f5c442a56fca5bf7935e", - "enabled": true, - "id": "59e7f5c442a56fca5bf7935e" - }, - "_id": "59e7f5c442a56fca5bf7935d", - "created": "2017-10-19T00:45:56.855Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, { - "globalId": "N2DthDVEJfXvNU4JsYyax6PrCbHzump8QTnyc1hnAVR", - "lastModified": "2017-10-19T00:46:24.054Z", - "title": "nascar", - "fieldType": "checkbox", - "fieldValue": "", - "logicJump": { - "_id": "59e7f5c842a56fca5bf79361", - "enabled": false, - "id": "59e7f5c842a56fca5bf79361" - }, - "_id": "59e7f5c842a56fca5bf79360", - "created": "2017-10-19T00:46:00.484Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, { - "globalId": "7vnFgEhKCZWwb6rR29Lat7mePmBK05fDTashc3modje", - "lastModified": "2017-10-19T00:46:24.055Z", - "title": "hockey", - "fieldType": "checkbox", - "fieldValue": "", - "logicJump": { - "_id": "59e7f5d242a56fca5bf79366", - "enabled": false, - "id": "59e7f5d242a56fca5bf79366" - }, - "_id": "59e7f5d242a56fca5bf79365", - "created": "2017-10-19T00:46:10.619Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }], - "analytics": { - "visitors": [], - "fields": [{ - "field": { - "globalId": "hSsZT02ICgcdvLTrbwCyYjl19qG9gQdAzO7ZDF2Esj4", - "lastModified": "2017-10-19T00:46:24.053Z", - "title": "Short Text3", - "fieldType": "textfield", - "fieldValue": "", - "logicJump": { - "expressionString": "field == static", - "jumpTo": "59e7f5d242a56fca5bf79365", - "valueB": "hello", - "_id": "59e7f5c442a56fca5bf7935e", - "enabled": true, - "id": "59e7f5c442a56fca5bf7935e" - }, - "_id": "59e7f5c442a56fca5bf7935d", - "created": "2017-10-19T00:45:56.855Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, - "dropoffRate": 0, - "continueRate": 0, - "totalViews": 0, - "responses": 0, - "dropoffViews": 0 - }, { - "field": { - "globalId": "N2DthDVEJfXvNU4JsYyax6PrCbHzump8QTnyc1hnAVR", - "lastModified": "2017-10-19T00:46:24.054Z", - "title": "Short Text4", - "fieldType": "textfield", - "fieldValue": "", - "logicJump": { - "_id": "59e7f5c842a56fca5bf79361", - "enabled": false, - "id": "59e7f5c842a56fca5bf79361" - }, - "_id": "59e7f5c842a56fca5bf79360", - "created": "2017-10-19T00:46:00.484Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, - "dropoffRate": 0, - "continueRate": 0, - "totalViews": 0, - "responses": 0, - "dropoffViews": 0 - }, { - "field": { - "globalId": "7vnFgEhKCZWwb6rR29Lat7mePmBK05fDTashc3modje", - "lastModified": "2017-10-19T00:46:24.055Z", - "title": "Short Text5", - "fieldType": "textfield", - "fieldValue": "", - "logicJump": { - "_id": "59e7f5d242a56fca5bf79366", - "enabled": false, - "id": "59e7f5d242a56fca5bf79366" - }, - "_id": "59e7f5d242a56fca5bf79365", - "created": "2017-10-19T00:46:10.619Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, - "dropoffRate": 0, - "continueRate": 0, - "totalViews": 0, - "responses": 0, - "dropoffViews": 0 - }], - "conversionRate": 0, - "submissions": 0, - "views": 0 - }, - "language": "en", - "id": "59d25a9d413a7a3106878556" - }, - - sampleForm3: { - "_id": "2fab9ed873937f0e1dea0ce1", - "lastModified": "2017-10-19T00:46:24.056Z", - "title": "Form Title3", - "created": "2017-10-02T15:26:21.221Z", - "admin": this.sampleUser, - "design": { - "colors": { - "buttonTextColor": "#333", - "buttonColor": "#fff", - "answerColor": "#333", - "questionColor": "#333", - "backgroundColor": "#fff" - } - }, - "isLive": true, - "hideFooter": false, - "endPage": { - "buttons": [], - "buttonText": "Go back to Form", - "title": "Thank you for filling out the form", - "showEnd": false - }, - "startPage": { - "buttons": [], - "introButtonText": "Start", - "introTitle": "Welcome to Form", - "showStart": false - }, - "submissions": [], - "form_fields": [{ - "globalId": "hSsZT02ICgcdvLTrbwCyYjl19qG9gQdAzO7ZDF2Esj4", - "lastModified": "2017-10-19T00:46:24.053Z", - "title": "First Name", - "fieldType": "textfield", - "fieldValue": "", - "logicJump": { - "expressionString": "field == static", - "jumpTo": "59e7f5d242a56fca5bf79365", - "valueB": "hello", - "_id": "59e7f5c442a56fca5bf7935e", - "enabled": true, - "id": "59e7f5c442a56fca5bf7935e" - }, - "_id": "59e7f5c442a56fca5bf7935d", - "created": "2017-10-19T00:45:56.855Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, { - "globalId": "N2DthDVEJfXvNU4JsYyax6PrCbHzump8QTnyc1hnAVR", - "lastModified": "2017-10-19T00:46:24.054Z", - "title": "nascar", - "fieldType": "checkbox", - "fieldValue": "", - "logicJump": { - "_id": "59e7f5c842a56fca5bf79361", - "enabled": false, - "id": "59e7f5c842a56fca5bf79361" - }, - "_id": "59e7f5c842a56fca5bf79360", - "created": "2017-10-19T00:46:00.484Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, { - "globalId": "7vnFgEhKCZWwb6rR29Lat7mePmBK05fDTashc3modje", - "lastModified": "2017-10-19T00:46:24.055Z", - "title": "hockey", - "fieldType": "checkbox", - "fieldValue": "", - "logicJump": { - "_id": "59e7f5d242a56fca5bf79366", - "enabled": false, - "id": "59e7f5d242a56fca5bf79366" - }, - "_id": "59e7f5d242a56fca5bf79365", - "created": "2017-10-19T00:46:10.619Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }], - "analytics": { - "visitors": [], - "fields": [{ - "field": { - "globalId": "hSsZT02ICgcdvLTrbwCyYjl19qG9gQdAzO7ZDF2Esj4", - "lastModified": "2017-10-19T00:46:24.053Z", - "title": "Short Text3", - "fieldType": "textfield", - "fieldValue": "", - "logicJump": { - "expressionString": "field == static", - "jumpTo": "59e7f5d242a56fca5bf79365", - "valueB": "hello", - "_id": "59e7f5c442a56fca5bf7935e", - "enabled": true, - "id": "59e7f5c442a56fca5bf7935e" - }, - "_id": "59e7f5c442a56fca5bf7935d", - "created": "2017-10-19T00:45:56.855Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, - "dropoffRate": 0, - "continueRate": 0, - "totalViews": 0, - "responses": 0, - "dropoffViews": 0 - }, { - "field": { - "globalId": "N2DthDVEJfXvNU4JsYyax6PrCbHzump8QTnyc1hnAVR", - "lastModified": "2017-10-19T00:46:24.054Z", - "title": "Short Text4", - "fieldType": "textfield", - "fieldValue": "", - "logicJump": { - "_id": "59e7f5c842a56fca5bf79361", - "enabled": false, - "id": "59e7f5c842a56fca5bf79361" - }, - "_id": "59e7f5c842a56fca5bf79360", - "created": "2017-10-19T00:46:00.484Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, - "dropoffRate": 0, - "continueRate": 0, - "totalViews": 0, - "responses": 0, - "dropoffViews": 0 - }, { - "field": { - "globalId": "7vnFgEhKCZWwb6rR29Lat7mePmBK05fDTashc3modje", - "lastModified": "2017-10-19T00:46:24.055Z", - "title": "Short Text5", - "fieldType": "textfield", - "fieldValue": "", - "logicJump": { - "_id": "59e7f5d242a56fca5bf79366", - "enabled": false, - "id": "59e7f5d242a56fca5bf79366" - }, - "_id": "59e7f5d242a56fca5bf79365", - "created": "2017-10-19T00:46:10.619Z", - "validFieldTypes": ["textfield", "date", "email", "link", "legal", "url", "textarea", "statement", "welcome", "thankyou", "file", "dropdown", "scale", "rating", "radio", "checkbox", "hidden", "yes_no", "natural", "stripe", "number"], - "deletePreserved": false, - "disabled": false, - "required": true, - "fieldOptions": [], - "description": "", - "isSubmission": false - }, - "dropoffRate": 0, - "continueRate": 0, - "totalViews": 0, - "responses": 0, - "dropoffViews": 0 - }], - "conversionRate": 0, - "submissions": 0, - "views": 0 - }, - "language": "en", - "id": "59d25a9d413a7a3106878556" - }, - - sampleFormList: [this.sampleForm1, this.sampleForm2, this.sampleForm3], -} \ No newline at end of file From 3dbfe2f88d25d3df772ea2d86341e813e1dcc3f2 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 14:04:13 -0700 Subject: [PATCH 10/29] added helper function to remove sensitive data from forms/users --- app/controllers/forms.server.controller.js | 42 +++++++--------- app/controllers/helpers.server.controller.js | 44 +++++++++++++++++ .../users.authentication.server.controller.js | 12 ++--- .../users/users.profile.server.controller.js | 12 ++--- app/models/form.server.model.js | 20 +++++--- app/models/user.server.model.js | 2 - app/tests/form.server.routes.test.js | 48 +++++++++++++++++-- 7 files changed, 129 insertions(+), 51 deletions(-) create mode 100644 app/controllers/helpers.server.controller.js diff --git a/app/controllers/forms.server.controller.js b/app/controllers/forms.server.controller.js index 32721440..129be700 100644 --- a/app/controllers/forms.server.controller.js +++ b/app/controllers/forms.server.controller.js @@ -9,7 +9,8 @@ var mongoose = require('mongoose'), FormSubmission = mongoose.model('FormSubmission'), config = require('../../config/config'), diff = require('deep-diff'), - _ = require('lodash'); + _ = require('lodash'), + helpers = require('./helpers.server.controller'); /** * Delete a forms submissions @@ -96,7 +97,7 @@ exports.listSubmissions = function(req, res) { exports.create = function(req, res) { if(!req.body.form){ - return res.status(401).send({ + return res.status(400).send({ message: 'Invalid Input' }); } @@ -104,14 +105,15 @@ exports.create = function(req, res) { form.admin = req.user._id; - form.save(function(err) { + form.save(function(err, createdForm) { if (err) { return res.status(500).send({ message: errorHandler.getErrorMessage(err) }); } - return res.json(form); + createdForm = helpers.removeSensitiveModelData('private_form', createdForm); + return res.json(createdForm); }); }; @@ -132,6 +134,8 @@ exports.read = function(req, res) { message: 'Form Does Not Exist' }); } + + newForm = helpers.removeSensitiveModelData('private_form', newForm); return res.json(newForm); } }; @@ -147,9 +151,7 @@ var readForRender = exports.readForRender = function(req, res) { }); } - delete newForm.lastModified; - delete newForm.__v; - delete newForm.created; + newForm = helpers.removeSensitiveModelData('public_form', newForm); if(newForm.startPage && !newForm.startPage.showStart){ delete newForm.startPage; @@ -165,11 +167,8 @@ exports.update = function(req, res) { var form = req.form; var updatedForm = req.body.form; - if(form.form_fields === undefined){ - form.form_fields = []; - } - - if(form.analytics === undefined){ + + if(!form.analytics){ form.analytics = { visitors: [], gaCode: '' @@ -213,6 +212,7 @@ exports.update = function(req, res) { message: errorHandler.getErrorMessage(err) }); } else { + savedForm = helpers.removeSensitiveModelData('private_form', savedForm); res.json(savedForm); } }); @@ -254,6 +254,8 @@ exports.list = function(req, res) { }); } else { for(var i=0; i should be able to read/get a Form if not signed in', function(done) { + it(' > should be able to read/get a live Form if not signed in', function(done) { // Create new Form model instance var FormObj = new Form(myForm); @@ -104,6 +104,23 @@ describe('Form Routes Unit tests', function() { }); }); + it(' > should be able to read/get a non-live Form if not signed in', function(done) { + // Create new Form model instance + var FormObj = new Form(myForm); + FormObj.isLive = false; + + // Save the Form + FormObj.save(function(err, form) { + if(err) return done(err); + + userSession.get('/subdomain/' + credentials.username + '/forms/' + form._id + '/render') + .expect(401, {message: 'Form is Not Public'}) + .end(function(err, res) { + done(err); + }); + }); + }); + it(' > should not be able to delete an Form if not signed in', function(done) { // Set Form user myForm.admin = user; @@ -145,6 +162,16 @@ describe('Form Routes Unit tests', function() { }); }); + it(' > should not be able to create a Form if body is empty', function(done) { + loginSession.post('/forms') + .send({form: null}) + .expect(400, {"message":"Invalid Input"}) + .end(function(FormSaveErr, FormSaveRes) { + // Call the assertion callback + done(FormSaveErr); + }); + }); + it(' > should not be able to save a Form if no title is provided', function(done) { // Set Form with a invalid title field myForm.title = ''; @@ -167,7 +194,20 @@ describe('Form Routes Unit tests', function() { }); - it(' > should be able to update a Form if signed in', function(done) { + it(' > should be able to create a Form if form_fields are undefined', function(done) { + myForm.analytics = null; + myForm.form_fields = null; + + loginSession.post('/forms') + .send({form: myForm}) + .expect(200) + .end(function(FormSaveErr, FormSaveRes) { + // Call the assertion callback + done(FormSaveErr); + }); + }); + + it(' > should be able to update a Form if signed in and Form is valid', function(done) { // Save a new Form loginSession.post('/forms') @@ -181,7 +221,7 @@ describe('Form Routes Unit tests', function() { } // Update Form title - myForm.title = 'WHY YOU GOTTA BE SO MEAN?'; + myForm.title = 'WHY YOU GOTTA BE SO FORMULAIC?'; // Update an existing Form loginSession.put('/forms/' + FormSaveRes.body._id) @@ -196,7 +236,7 @@ describe('Form Routes Unit tests', function() { // Set assertions (FormUpdateRes.body._id).should.equal(FormSaveRes.body._id); - (FormUpdateRes.body.title).should.match('WHY YOU GOTTA BE SO MEAN?'); + (FormUpdateRes.body.title).should.match(myForm.title); // Call the assertion callback done(); From 9fffdf53284ac098fa5a5ec07a100601e6eca43e Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 15:47:01 -0700 Subject: [PATCH 11/29] added tests to cover reset password routes --- .../users/users.password.server.controller.js | 17 +- app/tests/form.server.routes.test.js | 68 +++++- app/tests/user.server.routes.test.js | 222 +++++++++++++----- 3 files changed, 235 insertions(+), 72 deletions(-) diff --git a/app/controllers/users/users.password.server.controller.js b/app/controllers/users/users.password.server.controller.js index bdeb0505..9d569bf1 100755 --- a/app/controllers/users/users.password.server.controller.js +++ b/app/controllers/users/users.password.server.controller.js @@ -84,7 +84,6 @@ exports.forgot = function(req, res) { const fn = pug.compileFile(__dirname + "/../../views/templates/reset-password-email.server.view.pug"); res.locals['url'] = 'http://' + req.headers.host + '/auth/reset/' + token; - console.log(res.locals); var renderedHtml = fn(res.locals); done(null, renderedHtml, user); }, @@ -142,9 +141,9 @@ exports.validateResetToken = function(req, res) { }); } if (!user) { - return res.redirect('/#!/password/reset/invalid'); + return res.redirect(400, '/#!/password/reset/invalid'); } - + res.redirect('/#!/password/reset/' + req.params.token); }); }; @@ -187,7 +186,7 @@ exports.reset = function(req, res, next) { done(null, savedUser); }); } else { - done('Password reset token is invalid or has expired.', null); + done('invalid_reset_token', null); } }); }, @@ -211,12 +210,18 @@ exports.reset = function(req, res, next) { } ], function(err) { if (err) { - res.status(500).send({ + if(err === 'invalid_reset_token'){ + return res.status(400).send({ + message: 'Password reset token is invalid or has expired.' + }); + } + + return res.status(500).send({ message: err.message || err }); } - return res.json({ + res.json({ message: 'Successfully changed your password!' }); }); diff --git a/app/tests/form.server.routes.test.js b/app/tests/form.server.routes.test.js index f7b740e9..3de6057d 100644 --- a/app/tests/form.server.routes.test.js +++ b/app/tests/form.server.routes.test.js @@ -9,7 +9,8 @@ var should = require('should'), User = mongoose.model('User'), Form = mongoose.model('Form'), Field = mongoose.model('Field'), - FormSubmission = mongoose.model('FormSubmission'); + FormSubmission = mongoose.model('FormSubmission'), + async = require('async'); /** * Globals @@ -191,7 +192,6 @@ describe('Form Routes Unit tests', function() { done(); }); - }); it(' > should be able to create a Form if form_fields are undefined', function(done) { @@ -242,7 +242,6 @@ describe('Form Routes Unit tests', function() { done(); }); }); - }); it(' > should be able to delete a Form if signed in', function(done) { @@ -277,7 +276,6 @@ describe('Form Routes Unit tests', function() { done(); }); }); - }); it('should be able to save new form while logged in', function(done){ @@ -310,14 +308,70 @@ describe('Form Routes Unit tests', function() { }); }); + it(' > should be able to get list of users\' forms sorted by date created while logged in', function(done) { + var myForm1 = { + title: 'First Form', + language: 'en', + admin: user.id, + form_fields: [ + new Field({'fieldType':'textfield', 'title':'First Name', 'fieldValue': ''}), + new Field({'fieldType':'checkbox', 'title':'nascar', 'fieldValue': ''}), + new Field({'fieldType':'checkbox', 'title':'hockey', 'fieldValue': ''}) + ], + isLive: true + }; + + var myForm2 = { + title: 'Second Form', + language: 'en', + admin: user.id, + form_fields: [ + new Field({'fieldType':'textfield', 'title':'Last Name', 'fieldValue': ''}), + new Field({'fieldType':'checkbox', 'title':'formula one', 'fieldValue': ''}), + new Field({'fieldType':'checkbox', 'title':'football', 'fieldValue': ''}) + ], + isLive: true + }; + + var FormObj1 = new Form(myForm1); + var FormObj2 = new Form(myForm2); + + async.waterfall([ + function(callback) { + FormObj1.save(function(err){ + callback(err); + }); + }, + function(callback) { + FormObj2.save(function(err){ + callback(err); + }); + }, + function(callback) { + loginSession.get('/forms') + .expect(200) + .end(function(err, res) { + res.body.length.should.equal(2); + res.body[0].title.should.equal('Second Form'); + res.body[1].title.should.equal('First Form'); + + // Call the assertion callback + callback(err); + }); + } + ], function (err) { + done(err); + }); + }); + afterEach('should be able to signout user', function(done){ authenticatedSession.get('/auth/signout') .expect(200) .end(function(signoutErr, signoutRes) { - console.log(signoutRes.error.text); - // Handle signout error - if (signoutErr) return done(signoutErr); + if (signoutErr) { + return done(signoutErr); + } authenticatedSession.destroy(); done(); }); diff --git a/app/tests/user.server.routes.test.js b/app/tests/user.server.routes.test.js index 89918285..c8e62ef4 100644 --- a/app/tests/user.server.routes.test.js +++ b/app/tests/user.server.routes.test.js @@ -6,20 +6,19 @@ var should = require('should'), mongoose = require('mongoose'), User = mongoose.model('User'), config = require('../../config/config'), - tmpUser = mongoose.model(config.tempUserCollection); + tmpUser = mongoose.model(config.tempUserCollection), + async = require('async'); /** * Globals */ -var credentials, _User, activateToken, userSession; +var credentials, _User, userSession; /** * Form routes tests */ describe('User CRUD tests', function() { - this.timeout(30000); - - beforeEach(function() { + before(function() { // Create user credentials credentials = { email: 'test732@test.com', @@ -31,77 +30,182 @@ describe('User CRUD tests', function() { _User = { email: credentials.email, username: credentials.username, - password: credentials.password + password: credentials.password, + firstName: 'John', + lastName: 'Smith' }; //Initialize Session userSession = Session(app); }); - it(' > Create, Verify and Activate a User > ', function() { + describe(' > Create, Verify and Activate a User > ', function() { + this.timeout(5000); - it('should be able to create a temporary (non-activated) User', function(done) { - userSession.post('/auth/signup') - .send(_User) - .expect(200) - .end(function(FormSaveErr) { - // Handle error - should.not.exist(FormSaveErr); - - tmpUser.findOne({username: _User.username}, function (err, user) { - should.not.exist(err); + it('should be able to create and activate a User', function(done) { + async.waterfall([ + function(callback) { + userSession.post('/auth/signup') + .send(_User) + .expect(200) + .end(function(err) { + callback(err) + }); + }, + function(callback) { + tmpUser.findOne({username: _User.username}) + .lean() + .exec(function (err, user) { should.exist(user); _User.username.should.equal(user.username); _User.firstName.should.equal(user.firstName); _User.lastName.should.equal(user.lastName); - activateToken = user.GENERATED_VERIFYING_URL; - - userSession.get('/auth/verify/'+activateToken) - .expect(200) - .end(function(VerifyErr, VerifyRes) { - // Handle error - if (VerifyErr) { - return done(VerifyErr); - } - - (VerifyRes.text).should.equal('User successfully verified'); - - userSession.post('/auth/signin') - .send(credentials) - .expect('Content-Type', /json/) - .expect(200) - .end(function(signinErr, signinRes) { - // Handle signin error - if (signinErr) { - return done(signinErr); - } - - var user = signinRes.body; - (user.username).should.equal(credentials.username); - - userSession.get('/auth/signout') - .expect(200) - .end(function(signoutErr, signoutRes) { - - // Handle signout error - if (signoutErr) { - return done(signoutErr); - } - - (signoutRes.text).should.equal('You have successfully logged out.'); - - done(); - }); - }); - }); + callback(err, user.GENERATED_VERIFYING_URL); }); - }); + }, + function(activateToken, callback) { + userSession.get('/auth/verify/' + activateToken) + .expect(200) + .end(function(err, res) { + (res.text).should.equal('User successfully verified'); + callback(err); + }); + }, + function(callback) { + userSession.post('/auth/signin') + .send(credentials) + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + (res.body.username).should.equal(credentials.username); + callback(err); + }); + }, + function(callback) { + userSession.get('/auth/signout') + .expect(200) + .end(function(err, res) { + (res.text).should.equal('You have successfully logged out.'); + callback(err); + }); + }, + function(callback) { + User.findOne({ username: _User.username }) + .lean() + .exec(function(err, user){ + should.exist(user); + callback(err); + }); + } + ], function (err) { + done(err); + }); + }); + + it('should be able to reset password of a created User with a valid passwordResetToken', function(done) { + var changedPassword = 'password1234'; + var resetPasswordToken; + + async.waterfall([ + function(callback) { + userSession.post('/auth/forgot') + .send({ username: _User.username }) + .expect(200) + .end(function(err) { + callback(err); + }); + }, + function(callback) { + User.findOne({ username: _User.username }) + .lean() + .exec(function(err, user){ + if(err){ + callback(err); + } + callback(null, user.resetPasswordToken) + }); + }, + function(resetPasswordToken, callback) { + userSession.get('/auth/reset/' + resetPasswordToken) + .expect(302) + .end(function(err) { + callback(err, resetPasswordToken); + }); + }, + function(resetPasswordToken, callback) { + userSession.post('/auth/reset/' + resetPasswordToken) + .send({ + newPassword: changedPassword, + verifyPassword: changedPassword + }) + .expect(200) + .end(function(err, res) { + callback(err, resetPasswordToken); + }); + }, + function(resetPasswordToken, callback) { + User.findOne({ username: _User.username }) + .exec(function(err, user){ + should.exist(user); + user.authenticate(changedPassword).should.be.true(); + should.not.exist(user.resetPasswordToken); + + callback(err); + }); + } + ], function (err, result) { + done(err); + }); + }); + + it('should be not able to reset password of a created User with a invalid passwordResetToken', function(done) { + var changedPassword = 'password4321'; + var resetPasswordToken = 'thisIsNotAValidToken'; + + async.waterfall([ + function(callback) { + userSession.post('/auth/forgot') + .send({ username: credentials.username }) + .expect(200) + .end(function(err, res) { + callback(err); + }); + }, + function(callback) { + userSession.get('/auth/reset/' + resetPasswordToken) + .expect(400) + .end(function(err) { + callback(err); + }); + }, + function(callback) { + userSession.post('/auth/reset/' + resetPasswordToken) + .send({ + newPassword: changedPassword, + verifyPassword: changedPassword + }) + .expect(400) + .end(function(err, res) { + callback(err); + }); + }, + function(callback) { + User.findOne({ username: _User.username }) + .exec(function(err, user){ + should.exist(user); + user.authenticate(changedPassword).should.be.false(); + callback(err); + }); + } + ], function (err, result) { + done(err); + }); }); }); - afterEach(function(done) { + after(function(done) { User.remove().exec(function () { tmpUser.remove().exec(function(){ userSession.destroy(); From aed7c6c43b5f51c741fc275ff00f464963a8694e Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 17:20:34 -0700 Subject: [PATCH 12/29] added test for changing password route --- app/routes/users.server.routes.js | 4 +- app/tests/user.server.routes.test.js | 83 ++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 6 deletions(-) diff --git a/app/routes/users.server.routes.js b/app/routes/users.server.routes.js index 967176ce..86306033 100755 --- a/app/routes/users.server.routes.js +++ b/app/routes/users.server.routes.js @@ -12,6 +12,7 @@ module.exports = function(app) { var users = require('../../app/controllers/users.server.controller'); // Setting up the users profile api + app.route('/users/password').post(users.requiresLogin, users.changePassword); app.route('/users/me').get(auth.isAuthenticatedOrApiKey, users.getUser); app.route('/users').put(auth.isAuthenticatedOrApiKey, users.update); @@ -19,8 +20,7 @@ module.exports = function(app) { app.route('/auth/verify/:token').get(users.validateVerificationToken); app.route('/auth/verify').post(users.resendVerificationEmail); - // Setting up the users password api - app.route('/users/password').post(users.requiresLogin, users.changePassword); + // Setting up the password reset api app.route('/auth/forgot').post(users.forgot); app.route('/auth/reset/:token').get(users.validateResetToken); app.route('/auth/reset/:token').post(users.reset); diff --git a/app/tests/user.server.routes.test.js b/app/tests/user.server.routes.test.js index c8e62ef4..ba7960ba 100644 --- a/app/tests/user.server.routes.test.js +++ b/app/tests/user.server.routes.test.js @@ -21,8 +21,8 @@ describe('User CRUD tests', function() { before(function() { // Create user credentials credentials = { - email: 'test732@test.com', - username: 'test732', + email: 'test099@test.com', + username: 'test099', password: 'password3223' }; @@ -40,8 +40,7 @@ describe('User CRUD tests', function() { }); describe(' > Create, Verify and Activate a User > ', function() { - this.timeout(5000); - + this.timeout(10000); it('should be able to create and activate a User', function(done) { async.waterfall([ function(callback) { @@ -103,6 +102,20 @@ describe('User CRUD tests', function() { }); }); + after(function(done){ + User.remove().exec(done); + }); + }); + + describe(' > Reset Password > ', function(){ + this.timeout(10000); + beforeEach(function(done){ + var UserObj = new User(_User); + UserObj.save(function(err){ + done(err); + }) + }); + it('should be able to reset password of a created User with a valid passwordResetToken', function(done) { var changedPassword = 'password1234'; var resetPasswordToken; @@ -155,6 +168,7 @@ describe('User CRUD tests', function() { }); } ], function (err, result) { + credentials.password = changedPassword; done(err); }); }); @@ -203,6 +217,67 @@ describe('User CRUD tests', function() { }); }); + afterEach(function(done){ + User.remove({ username: credentials.username }).exec(done); + }); + }); + + describe(' > User Profile Changes > ', function(){ + var profileSession = new Session(app); + + this.timeout(10000); + beforeEach(function(done){ + var UserObj = new User(_User); + UserObj.save(function(err, user){ + done(err); + }) + }) + + it('should be able to change password when logged in', function(done) { + var changedPassword = 'aVeryBadPassword'; + + async.waterfall([ + function(callback) { + userSession.post('/auth/signin') + .send({ + username: _User.username, + password: _User.password + }) + .expect(200) + .end(function(err, res) { + callback(err); + }); + }, + function(callback) { + userSession.post('/users/password') + .send({ + currentPassword: _User.password, + newPassword: changedPassword, + verifyPassword: changedPassword + }) + .expect(200) + .end(function(err, res) { + callback(err); + }); + }, + function(callback) { + User.findOne({ username: _User.username }) + .exec(function(err, user){ + user.authenticate(changedPassword).should.be.true(); + callback(err); + }); + } + ], function (err) { + done(err); + }); + }); + + afterEach(function(done){ + userSession.get('/auth/signout') + .end(function(err, res) { + User.remove().exec(done); + }); + }) }); after(function(done) { From 15eb66e4558c22a727ad31056446e1f5d44b55a3 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 17:34:27 -0700 Subject: [PATCH 13/29] added test for /users/me routes --- .../users/users.profile.server.controller.js | 48 +++++------- app/tests/user.server.routes.test.js | 73 +++++++++++++++++++ 2 files changed, 93 insertions(+), 28 deletions(-) diff --git a/app/controllers/users/users.profile.server.controller.js b/app/controllers/users/users.profile.server.controller.js index 8f4ea7cb..d6176f30 100755 --- a/app/controllers/users/users.profile.server.controller.js +++ b/app/controllers/users/users.profile.server.controller.js @@ -15,44 +15,36 @@ exports.update = function(req, res) { // Init Variables var user = req.user; - // For security measurement we remove the roles from the req.body object + // To improve security we remove the roles from the req.body object delete req.body.roles; - if (user) { - // Merge existing user - user = _.extend(user, req.body); - user.updated = Date.now(); + // Merge existing user + user = _.extend(user, req.body); + user.updated = Date.now(); - user.save(function(err) { - if (err) { - return res.status(500).send({ - message: errorHandler.getErrorMessage(err) - }); - } - req.login(user, function(loginErr) { - if (err) { - res.status(500).send(loginErr); - } else { - user = helpers.removeSensitiveModelData('private_user', user); - res.json(user); - } + user.save(function(err) { + if (err) { + return res.status(500).send({ + message: errorHandler.getErrorMessage(err) }); - + } + req.login(user, function(loginErr) { + if (err) { + res.status(500).send(loginErr); + } else { + user = helpers.removeSensitiveModelData('private_user', user); + res.json(user); + } }); - } else { - res.status(401).send({ - message: 'User is not signed in' - }); - } + + }); }; /** * Send User */ exports.getUser = function(req, res) { - var _user = helpers.removeSensitiveModelData('private_user', req.user); + var user = helpers.removeSensitiveModelData('private_user', req.user); - res.json(_user); - - res.end(); + return res.json(user); }; diff --git a/app/tests/user.server.routes.test.js b/app/tests/user.server.routes.test.js index ba7960ba..765e70aa 100644 --- a/app/tests/user.server.routes.test.js +++ b/app/tests/user.server.routes.test.js @@ -272,6 +272,79 @@ describe('User CRUD tests', function() { }); }); + it('should be able to update user when logged in', function(done) { + var newUser = {}; + newUser.firstName = 'goodnight'; + newUser.lastName = 'everyone'; + + newUser.email = 'grcg@gcrc.com'; + newUser.username = 'grcg'; + + async.waterfall([ + function(callback) { + userSession.post('/auth/signin') + .send({ + username: _User.username, + password: _User.password + }) + .expect(200) + .end(function(err, res) { + callback(err); + }); + }, + function(callback) { + userSession.put('/users') + .send(newUser) + .expect(200) + .end(function(err, res) { + callback(err); + }); + }, + function(callback) { + User.findOne({ username: newUser.username }) + .exec(function(err, user){ + user.firstName.should.equal(newUser.firstName); + user.lastName.should.equal(newUser.lastName); + user.email.should.equal(newUser.email); + user.username.should.equal(newUser.username); + callback(err); + }); + } + ], function (err) { + done(err); + }); + }); + + it('should be able to fetch user when logged in', function(done) { + async.waterfall([ + function(callback) { + userSession.post('/auth/signin') + .send({ + username: _User.username, + password: _User.password + }) + .expect(200) + .end(function(err, res) { + callback(err); + }); + }, + function(callback) { + userSession.get('/users/me') + .expect(200) + .end(function(err, res) { + var user = res.body; + user.firstName.should.equal(_User.firstName); + user.lastName.should.equal(_User.lastName); + user.email.should.equal(_User.email); + user.username.should.equal(_User.username); + callback(err); + }); + } + ], function (err) { + done(err); + }); + }); + afterEach(function(done){ userSession.get('/auth/signout') .end(function(err, res) { From 99a6cb50093e00775904deff8f8876303ca58a01 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 17:46:08 -0700 Subject: [PATCH 14/29] fixed hasAuthorization bug for API --- .../users/users.authorization.server.controller.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/controllers/users/users.authorization.server.controller.js b/app/controllers/users/users.authorization.server.controller.js index 8225cfa1..5dcfa623 100755 --- a/app/controllers/users/users.authorization.server.controller.js +++ b/app/controllers/users/users.authorization.server.controller.js @@ -5,7 +5,8 @@ */ var _ = require('lodash'), mongoose = require('mongoose'), - User = mongoose.model('User'); + User = mongoose.model('User'), + auth = require('../../config/passport_helpers'); /** * User middleware @@ -53,7 +54,7 @@ exports.hasAuthorization = function(roles) { var _this = this; return function(req, res, next) { - _this.requiresLogin(req, res, function() { + auth.isAuthenticatedOrApiKey(req, res, function() { if (_.intersection(req.user.roles, roles).length) { return next(); } else { From e1db98ec955048320eeba868620b949467a4a4a1 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 18:17:20 -0700 Subject: [PATCH 15/29] added tests for api routes --- .../users.authentication.server.controller.js | 13 +-- .../users.authorization.server.controller.js | 2 +- app/models/form.server.model.js | 20 ---- app/models/plugins/languagePlugin.js | 26 ----- app/tests/user.server.routes.test.js | 94 +++++++++++++++++++ config/passport_helpers.js | 1 + 6 files changed, 100 insertions(+), 56 deletions(-) delete mode 100644 app/models/plugins/languagePlugin.js diff --git a/app/controllers/users/users.authentication.server.controller.js b/app/controllers/users/users.authentication.server.controller.js index 98af93a8..e6844a74 100755 --- a/app/controllers/users/users.authentication.server.controller.js +++ b/app/controllers/users/users.authentication.server.controller.js @@ -201,16 +201,12 @@ exports.signout = function(req, res) { /* Generate API Key for User */ exports.generateAPIKey = function(req, res) { - if (!req.isAuthenticated()){ - return res.status(401).send({ - message: 'User is not Authorized' - }); - } - User.findById(req.user.id) .exec( function(err, user) { if (err) { - return res.status(400).send(err); + return res.status(400).send({ + message: errorHandler.getErrorMessage(err) + }); } if (!user) { @@ -230,8 +226,7 @@ exports.generateAPIKey = function(req, res) { var newUser = _user.toObject(); - newUser = helpers.removeSensitiveModelData('private_user', newUser); - return res.json(newUser); + return res.json({ id: newUser._id, apiKey: newUser.apiKey }); }); }); diff --git a/app/controllers/users/users.authorization.server.controller.js b/app/controllers/users/users.authorization.server.controller.js index 5dcfa623..1efbac64 100755 --- a/app/controllers/users/users.authorization.server.controller.js +++ b/app/controllers/users/users.authorization.server.controller.js @@ -6,7 +6,7 @@ var _ = require('lodash'), mongoose = require('mongoose'), User = mongoose.model('User'), - auth = require('../../config/passport_helpers'); + auth = require('../../../config/passport_helpers'); /** * User middleware diff --git a/app/models/form.server.model.js b/app/models/form.server.model.js index 1d00bf45..5f8321a0 100644 --- a/app/models/form.server.model.js +++ b/app/models/form.server.model.js @@ -294,26 +294,6 @@ FormSchema.plugin(timeStampPlugin, { useVirtual: false }); -FormSchema.pre('save', function (next) { - switch(this.language){ - case 'spanish': - this.language = 'es'; - break; - case 'french': - this.language = 'fr'; - break; - case 'italian': - this.language = 'it'; - break; - case 'german': - this.language = 'de'; - break; - default: - break; - } - next(); -}); - function getDeletedIndexes(needle, haystack){ var deletedIndexes = []; diff --git a/app/models/plugins/languagePlugin.js b/app/models/plugins/languagePlugin.js deleted file mode 100644 index a7b9b6e6..00000000 --- a/app/models/plugins/languagePlugin.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -const constants = require('../../libs/constants'), - config = require('../../../config/config'); - -module.exports = exports = function lastModifiedPlugin (schema, options) { - schema.add({ - language: { - type: String, - enum: constants.languageTypes, - default: config.defaultLanguage, - required: options.required || 'Must be a valid language' - } - }); - - schema.pre('save', function (next) { - var currWord = this.language; - - //English is the default backup language - this.language = 'en'; - if(constants.wordToLangCode.has(currWord)){ - this.language = constants.wordToLangCode[currWord]; - } - next(); - }); -}; \ No newline at end of file diff --git a/app/tests/user.server.routes.test.js b/app/tests/user.server.routes.test.js index 765e70aa..33c8987b 100644 --- a/app/tests/user.server.routes.test.js +++ b/app/tests/user.server.routes.test.js @@ -353,6 +353,100 @@ describe('User CRUD tests', function() { }) }); + describe(' > User API > ', function(){ + var apiKey; + + this.timeout(10000); + before(function(done){ + var UserObj = new User(_User); + UserObj.save(function(err, user){ + done(err); + }) + }) + + it('should be able to request API Key', function(done) { + async.waterfall([ + function(callback) { + userSession.post('/auth/signin') + .send({ + username: _User.username, + password: _User.password + }) + .expect(200) + .end(function(err, res) { + callback(err); + }); + }, + function(callback) { + userSession.get('/auth/genkey') + .expect(200) + .end(function(err, res) { + apiKey = res.body.apiKey; + callback(err); + }); + }, + function(callback) { + userSession.get('/auth/signout') + .expect(200) + .end(function(err, res) { + callback(err); + }); + }, + function(callback) { + userSession.get('/users/me?apikey=' + apiKey) + .expect(200) + .end(function(err, res) { + console.log(res.body); + var user = res.body; + user.firstName.should.equal(_User.firstName); + user.lastName.should.equal(_User.lastName); + user.email.should.equal(_User.email); + user.username.should.equal(_User.username); + callback(err); + }); + }, + ], function (err) { + done(err); + }); + }); + + it('should be able to update user with API key', function(done) { + var newUser = {}; + newUser.firstName = 'goodnight'; + newUser.lastName = 'everyone'; + + newUser.email = 'grcg@gcrc.com'; + newUser.username = 'grcg'; + + async.waterfall([ + function(callback) { + userSession.put('/users?apikey=' + apiKey) + .send(newUser) + .expect(200) + .end(function(err, res) { + callback(err); + }); + }, + function(callback) { + User.findOne({ username: newUser.username }) + .exec(function(err, user){ + user.firstName.should.equal(newUser.firstName); + user.lastName.should.equal(newUser.lastName); + user.email.should.equal(newUser.email); + user.username.should.equal(newUser.username); + callback(err); + }); + } + ], function (err) { + done(err); + }); + }); + + afterEach(function(done){ + User.remove().exec(done); + }) + }); + after(function(done) { User.remove().exec(function () { tmpUser.remove().exec(function(){ diff --git a/config/passport_helpers.js b/config/passport_helpers.js index cb861289..07da1396 100644 --- a/config/passport_helpers.js +++ b/config/passport_helpers.js @@ -6,6 +6,7 @@ module.exports.isAuthenticatedOrApiKey = function isAuthenticated(req, res, next if (req.isAuthenticated()) { return next(); } + // Try authenticate with API KEY if (req.headers.apikey || req.query.apikey || req.body.apikey) { passport.authenticate('localapikey', function (err, user, info) { From 3e3e7ccfe63543672d06be4e428234c6744b532f Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 19:02:01 -0700 Subject: [PATCH 16/29] removed hasRole and hasAdminRole from passport_helpers --- config/passport_helpers.js | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/config/passport_helpers.js b/config/passport_helpers.js index 07da1396..13ea356e 100644 --- a/config/passport_helpers.js +++ b/config/passport_helpers.js @@ -6,7 +6,7 @@ module.exports.isAuthenticatedOrApiKey = function isAuthenticated(req, res, next if (req.isAuthenticated()) { return next(); } - + // Try authenticate with API KEY if (req.headers.apikey || req.query.apikey || req.body.apikey) { passport.authenticate('localapikey', function (err, user, info) { @@ -29,23 +29,3 @@ module.exports.isAuthenticatedOrApiKey = function isAuthenticated(req, res, next } }; - -module.exports.hasRole = function hasRole(roleRequired) { - if (!roleRequired) { - throw new Error('Required role needs to be set'); - } - - return function(req, res, next) { - return module.exports.isAuthenticated(req, res, function() { - if (req.user && req.user.roles && req.user.roles.indexOf(roleRequired) !== -1){ - return next(); - } - return res.sendStatus(403); - }); - }; -}; - -module.exports.hasAdminRole = function hasAdminRole() { - return module.exports.hasRole('admin'); -}; - From 9a0a301c3dcf1b42e69da1a8e1288ede13f6a00c Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 20:05:52 -0700 Subject: [PATCH 17/29] got rid of unnessecary user middleware --- app/controllers/forms.server.controller.js | 13 ++--- .../users.authorization.server.controller.js | 51 +------------------ app/routes/users.server.routes.js | 3 -- app/tests/form.server.routes.test.js | 2 +- config/express.js | 2 - 5 files changed, 9 insertions(+), 62 deletions(-) diff --git a/app/controllers/forms.server.controller.js b/app/controllers/forms.server.controller.js index 129be700..17272194 100644 --- a/app/controllers/forms.server.controller.js +++ b/app/controllers/forms.server.controller.js @@ -124,17 +124,18 @@ exports.read = function(req, res) { if(!req.user || (req.form.admin.id !== req.user.id) ){ readForRender(req, res); } else { - var newForm = req.form.toJSON(); - - if (req.userId) { - if(req.form.admin._id+'' === req.userId+''){ - return res.json(newForm); - } + if(!req.form){ return res.status(404).send({ message: 'Form Does Not Exist' }); } + var newForm = req.form.toJSON(); + + if(newForm.admin._id === req.user._id){ + return res.json(newForm); + } + newForm = helpers.removeSensitiveModelData('private_form', newForm); return res.json(newForm); } diff --git a/app/controllers/users/users.authorization.server.controller.js b/app/controllers/users/users.authorization.server.controller.js index 1efbac64..ad7a78df 100755 --- a/app/controllers/users/users.authorization.server.controller.js +++ b/app/controllers/users/users.authorization.server.controller.js @@ -3,37 +3,7 @@ /** * Module dependencies. */ -var _ = require('lodash'), - mongoose = require('mongoose'), - User = mongoose.model('User'), - auth = require('../../../config/passport_helpers'); - -/** - * User middleware - */ -exports.userByID = function (req, res, next, id) { - if (!mongoose.Types.ObjectId.isValid(id)) { - return res.status(400).send({ - message: 'User is invalid' - }); - } - - User.findOne({ - _id: id - }).exec(function (err, user) { - if (err) { - return next(err); - } else if (!user) { - return res.status(404).send({ - message: 'User does not exist' - }); - } - - req.profile = user; - next(); - }); -}; - +var auth = require('../../../config/passport_helpers'); /** * Require login routing middleware */ @@ -46,22 +16,3 @@ exports.requiresLogin = function(req, res, next) { return next(); } }; - -/** - * User authorizations routing middleware - */ -exports.hasAuthorization = function(roles) { - var _this = this; - - return function(req, res, next) { - auth.isAuthenticatedOrApiKey(req, res, function() { - if (_.intersection(req.user.roles, roles).length) { - return next(); - } else { - return res.status(403).send({ - message: 'User is not authorized' - }); - } - }); - }; -}; diff --git a/app/routes/users.server.routes.js b/app/routes/users.server.routes.js index 86306033..89fbcd0e 100755 --- a/app/routes/users.server.routes.js +++ b/app/routes/users.server.routes.js @@ -33,7 +33,4 @@ module.exports = function(app) { app.route('/auth/signout').get(users.signout); app.route('/auth/genkey').get(users.requiresLogin, users.generateAPIKey); - - // Finish by binding the user middleware - app.param('userId', users.userByID); }; diff --git a/app/tests/form.server.routes.test.js b/app/tests/form.server.routes.test.js index 3de6057d..1ed05b06 100644 --- a/app/tests/form.server.routes.test.js +++ b/app/tests/form.server.routes.test.js @@ -278,7 +278,7 @@ describe('Form Routes Unit tests', function() { }); }); - it('should be able to save new form while logged in', function(done){ + it(' > should be able to save new form while logged in', function(done){ // Save a new Form authenticatedSession.post('/forms') .send({form: myForm}) diff --git a/config/express.js b/config/express.js index 7637bf4f..767e0bec 100755 --- a/config/express.js +++ b/config/express.js @@ -148,8 +148,6 @@ module.exports = function(db) { // reassign url req.url = subdomainPath; - req.userId = user._id; - // Q.E.D. return next(); }); From 774d2565075b07be89cd3a9a76532803f74dff50 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 20:13:35 -0700 Subject: [PATCH 18/29] removed unused code from user.server.model.js --- app/models/user.server.model.js | 26 ------------------------- app/tests/form_submission.model.test.js | 2 -- 2 files changed, 28 deletions(-) diff --git a/app/models/user.server.model.js b/app/models/user.server.model.js index 0d31ce4c..ab1d35b0 100755 --- a/app/models/user.server.model.js +++ b/app/models/user.server.model.js @@ -23,28 +23,6 @@ smtpTransport.verify(function(error, success) { } }); -/** - * A Validation function for local strategy properties - */ -var validateLocalStrategyProperty = function(property) { - var propHasLength; - if (property) { - propHasLength = !!property.length; - } else { - propHasLength = false; - } - - return ((this.provider !== 'local' && !this.updated) || propHasLength); -}; - -/** - * A Validation function for username - */ -var validateUsername = function(username) { - return (username.match(/^[a-zA-Z0-9.-_]+$/) !== null); -}; - - /** * User Schema */ @@ -121,10 +99,6 @@ var UserSchema = new Schema({ } }); -UserSchema.virtual('displayName').get(function () { - return this.firstName + ' ' + this.lastName; -}); - UserSchema.plugin(timeStampPlugin, { createdPath: 'created', modifiedPath: 'lastModified', diff --git a/app/tests/form_submission.model.test.js b/app/tests/form_submission.model.test.js index 09442c81..d7874e5c 100644 --- a/app/tests/form_submission.model.test.js +++ b/app/tests/form_submission.model.test.js @@ -17,7 +17,6 @@ var exampleDemo = { address: '880-9650 Velit. St.', city: '', dateOfBirth: '10', - displayName: 'Test User', email: 'polydaic@gmail.com', firstName: 'Test User', hin: '', @@ -82,7 +81,6 @@ describe('FormSubmission Model Unit Tests:', function() { user = new User({ firstName: 'Full', lastName: 'Name', - displayName: 'Full Name', email: 'test1@test.com'+Date.now(), username: 'test1'+Date.now(), password: 'password', From d0d273a718fde6f5d4595ce3916b26e5cf383516 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 20:23:36 -0700 Subject: [PATCH 19/29] removed secure configuration --- config/env/secure.js | 60 -------------------------------------------- config/express.js | 20 ++------------- config/logger.js | 2 -- 3 files changed, 2 insertions(+), 80 deletions(-) delete mode 100755 config/env/secure.js diff --git a/config/env/secure.js b/config/env/secure.js deleted file mode 100755 index db1c2bdb..00000000 --- a/config/env/secure.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -module.exports = { - baseUrl: 'https://forms.polydaic.com', - port: 8443, - db: { - uri: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || process.env.MONGODB_URI || 'mongodb://127.0.0.1/mean', - options: { - user: '', - pass: '' - } - }, - log: { - // Can specify one of 'combined', 'common', 'dev', 'short', 'tiny' - format: 'combined', - // Stream defaults to process.stdout - // Uncomment to enable logging to a log on the file system - options: { - stream: 'access.log' - } - }, - - sessionCookie: { - path: '/', - httpOnly: false, - // If secure is set to true then it will cause the cookie to be set - // only when SSL-enabled (HTTPS) is used, and otherwise it won't - // set a cookie. 'true' is recommended yet it requires the above - // mentioned pre-requisite. - secure: true, - // Only set the maxAge to null if the cookie shouldn't be expired - // at all. The cookie will expunge when the browser is closed. - maxAge: 7200, - // To set the cookie in a specific domain uncomment the following - // setting: - domain: process.env.BASE_URL || 'localhost:3000' - }, - assets: { - css: 'public/dist/application.min.css', - js: 'public/dist/application.min.js' - }, - mailer: { - from: process.env.MAILER_FROM || '', - options: process.env.MAILER_SMTP_HOST ? { //Uses custom SMTP if MAILER_SMTP_HOST is set - host: process.env.MAILER_SMTP_HOST || '', - port: process.env.MAILER_SMTP_PORT || 587, - secure: process.env.MAILER_SMTP_SECURE || true, - auth: { - user: process.env.MAILER_EMAIL_ID || '', - pass: process.env.MAILER_PASSWORD || '' - } - } : { - service: process.env.MAILER_SERVICE_PROVIDER || '', - auth: { - user: process.env.MAILER_EMAIL_ID || '', - pass: process.env.MAILER_PASSWORD || '' - } - } - } -}; diff --git a/config/express.js b/config/express.js index 767e0bec..ae73bf16 100755 --- a/config/express.js +++ b/config/express.js @@ -198,7 +198,7 @@ module.exports = function(db) { app.use(morgan(logger.getLogFormat(), logger.getMorganOptions())); // Environment dependent middleware - if (process.env.NODE_ENV === 'development') { + if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') { // Disable views cache app.set('view cache', false); } else if (process.env.NODE_ENV === 'production') { @@ -290,7 +290,7 @@ module.exports = function(db) { app.use(function (req, res, next) { // Website you wish to allow to connect - res.setHeader('Access-Control-Allow-Origin', 'https://sentry.polydaic.com'); + res.setHeader('Access-Control-Allow-Origin', 'https://sentry.io'); // Request methods you wish to allow res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); @@ -337,22 +337,6 @@ module.exports = function(db) { }); }); - if (process.env.NODE_ENV === 'secure') { - // Load SSL key and certificate - var privateKey = fs.readFileSync('./config/sslcerts/key.pem', 'utf8'); - var certificate = fs.readFileSync('./config/sslcerts/cert.pem', 'utf8'); - - // Create HTTPS Server - var httpsServer = https.createServer({ - key: privateKey, - cert: certificate - }, app); - - // Return HTTPS server instance - return httpsServer; - } - - app = configureSocketIO(app, db); // Return Express server instance diff --git a/config/logger.js b/config/logger.js index 33842f41..0682c49b 100755 --- a/config/logger.js +++ b/config/logger.js @@ -63,7 +63,6 @@ logger.setupFileLogger = function setupFileLogger() { return false; } - }; /** @@ -97,7 +96,6 @@ logger.getLogOptions = function getLogOptions() { handleExceptions: true, humanReadableUnhandledException: true }; - }; /** From b2b09171f3d410f28a2787ddd120d8ebf260d79a Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 21:22:43 -0700 Subject: [PATCH 20/29] fixed api tests --- gruntfile.js | 48 +++++++++--------------------------------------- karma.conf.js | 15 ++++++++++++--- package.json | 1 + 3 files changed, 22 insertions(+), 42 deletions(-) diff --git a/gruntfile.js b/gruntfile.js index 98759acd..f5630667 100755 --- a/gruntfile.js +++ b/gruntfile.js @@ -1,4 +1,4 @@ -'use strict'; + var bowerArray = ['public/lib/angular/angular.min.js', 'public/lib/angular-scroll/angular-scroll.min.js', @@ -205,50 +205,22 @@ module.exports = function(grunt) { } }, mocha_istanbul: { - coverage: { - src: watchFiles.allTests, // a folder works nicely - options: { - mask: '*.test.js', - require: ['server.js'] - } - }, - coverageClient: { - src: watchFiles.clientTests, // specifying file patterns works as well - options: { - coverageFolder: 'coverageClient', - mask: '*.test.js', - require: ['server.js'] - } - }, coverageServer: { src: watchFiles.serverTests, options: { coverageFolder: 'coverageServer', mask: '*.test.js', - require: ['server.js'] - } - }, - coveralls: { - src: watchFiles.allTests, // multiple folders also works - options: { - require: ['server.js'], - coverage: true, // this will make the grunt.event.on('coverage') event listener to be triggered - root: './lib', // define where the cover task should consider the root of libraries that are covered by tests + require: ['server.js'], reportFormats: ['cobertura','lcovonly'] } } }, - istanbul_check_coverage: { - default: { - options: { - coverageFolder: 'coverage*', // will check both coverage folders and merge the coverage results - check: { - lines: 80, - statements: 80 - } - } - } - }, + lcovMerge: { + options: { + emitters: ['event'], + }, + src: ['./coverageServer/*.info', './clientCoverage/lcov-report/*.info'] + }, html2js: { options: { base: 'public', @@ -311,9 +283,7 @@ module.exports = function(grunt) { }); // Code coverage tasks. - grunt.registerTask('coveralls', ['env:test','mocha_istanbul:coveralls']); - grunt.registerTask('coverage', ['env:test', 'mocha_istanbul:coverage']); - grunt.registerTask('coverage:client', ['env:test', 'mocha_istanbul:coverageClient']); + grunt.registerTask('coveralls', ['env:test','lcovMerge']); grunt.registerTask('coverage:server', ['env:test', 'mocha_istanbul:coverageServer']); // Default task(s). diff --git a/karma.conf.js b/karma.conf.js index d80e9196..c3c2661a 100755 --- a/karma.conf.js +++ b/karma.conf.js @@ -29,11 +29,20 @@ module.exports = function(config) { 'public/modules/**/views/**/*.html': ['ng-html2js'], 'public/modules/**/views/*.html': ['ng-html2js'], 'public/form_modules/forms/base/views/**/*.html': ['ng-html2js'], - 'public/form_modules/forms/base/views/*.html': ['ng-html2js'] - //'public/modules/*/*.js': ['coverage'], - //'public/modules/*/*[!tests]*/*.js': ['coverage'], + 'public/form_modules/forms/base/views/*.html': ['ng-html2js'], + 'public/modules/*/*.js': ['coverage'], + 'public/modules/*/*[!tests]*/*.js': ['coverage'] }, + // configure coverage reporter + coverageReporter: { + reporters: [ + { type: 'html', subdir: 'report-html' }, + { type: 'lcov', subdir: 'report-lcov' }, + ], + dir : 'coverageClient/' + }, + ngHtml2JsPreprocessor: { stripPrefix: 'public/', prependPrefix: 'static/', diff --git a/package.json b/package.json index 608280ba..feb9243b 100644 --- a/package.json +++ b/package.json @@ -94,6 +94,7 @@ "grunt-execute": "^0.2.2", "grunt-i18nlint": "github:jwarby/grunt-i18nlint", "grunt-karma": "~0.12.1", + "grunt-lcov-merge": "^1.2.3", "grunt-mocha-istanbul": "^3.0.1", "grunt-mocha-test": "~0.12.1", "grunt-newer": "~1.1.1", From 8ea1f63c9671c1a7de08c8a24deeb5617e1b20fe Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 21:32:02 -0700 Subject: [PATCH 21/29] fixed travis settings --- .travis.yml | 2 +- app/controllers/forms.server.controller.js | 5 ----- app/tests/user.server.routes.test.js | 18 +++++++++--------- config/logger.js | 2 +- config/passport_helpers.js | 17 +++++++++++++---- config/strategies/apikey.js | 6 ++++-- gruntfile.js | 8 ++++---- package.json | 2 +- server.js | 3 --- 9 files changed, 33 insertions(+), 30 deletions(-) diff --git a/.travis.yml b/.travis.yml index f03b879b..86c1e08c 100755 --- a/.travis.yml +++ b/.travis.yml @@ -14,4 +14,4 @@ addons: script: - npm travis after_script: - - grunt coverage + - grunt coveralls diff --git a/app/controllers/forms.server.controller.js b/app/controllers/forms.server.controller.js index 17272194..dc28ed73 100644 --- a/app/controllers/forms.server.controller.js +++ b/app/controllers/forms.server.controller.js @@ -191,11 +191,6 @@ exports.update = function(req, res) { delete updatedForm.admin; } - if(form.analytics === null){ - form.analytics.visitors = []; - form.analytics.gaCode = ''; - } - //Do this so we can create duplicate fields var checkForValidId = new RegExp('^[0-9a-fA-F]{24}$'); for(var i=0; i < req.body.form.form_fields.length; i++){ diff --git a/app/tests/user.server.routes.test.js b/app/tests/user.server.routes.test.js index 33c8987b..12b7af76 100644 --- a/app/tests/user.server.routes.test.js +++ b/app/tests/user.server.routes.test.js @@ -113,7 +113,7 @@ describe('User CRUD tests', function() { var UserObj = new User(_User); UserObj.save(function(err){ done(err); - }) + }); }); it('should be able to reset password of a created User with a valid passwordResetToken', function(done) { @@ -230,8 +230,8 @@ describe('User CRUD tests', function() { var UserObj = new User(_User); UserObj.save(function(err, user){ done(err); - }) - }) + }); + }); it('should be able to change password when logged in', function(done) { var changedPassword = 'aVeryBadPassword'; @@ -350,7 +350,7 @@ describe('User CRUD tests', function() { .end(function(err, res) { User.remove().exec(done); }); - }) + }); }); describe(' > User API > ', function(){ @@ -361,8 +361,8 @@ describe('User CRUD tests', function() { var UserObj = new User(_User); UserObj.save(function(err, user){ done(err); - }) - }) + }); + }); it('should be able to request API Key', function(done) { async.waterfall([ @@ -396,8 +396,8 @@ describe('User CRUD tests', function() { userSession.get('/users/me?apikey=' + apiKey) .expect(200) .end(function(err, res) { - console.log(res.body); var user = res.body; + user.firstName.should.equal(_User.firstName); user.lastName.should.equal(_User.lastName); user.email.should.equal(_User.email); @@ -442,9 +442,9 @@ describe('User CRUD tests', function() { }); }); - afterEach(function(done){ + after(function(done){ User.remove().exec(done); - }) + }); }); after(function(done) { diff --git a/config/logger.js b/config/logger.js index 0682c49b..d4fe9f40 100755 --- a/config/logger.js +++ b/config/logger.js @@ -75,7 +75,7 @@ logger.getLogOptions = function getLogOptions() { var _config = _.clone(config, true); var configFileLogger = _config.log.fileLogger; - if (!_.has(_config, 'log.fileLogger.directoryPath') || !_.has(_config, 'log.fileLogger.fileName')) { + if (process.env.NODE_ENV !== 'test' && !_.has(_config, 'log.fileLogger.directoryPath') || !_.has(_config, 'log.fileLogger.fileName')) { console.log('unable to find logging file configuration'); return false; } diff --git a/config/passport_helpers.js b/config/passport_helpers.js index 13ea356e..0543dff3 100644 --- a/config/passport_helpers.js +++ b/config/passport_helpers.js @@ -9,12 +9,21 @@ module.exports.isAuthenticatedOrApiKey = function isAuthenticated(req, res, next // Try authenticate with API KEY if (req.headers.apikey || req.query.apikey || req.body.apikey) { - passport.authenticate('localapikey', function (err, user, info) { - if (err) - return res.sendStatus(500); + if(!req.body.apikey && req.headers.apikey){ + req.body.apikey = req.headers.apikey; + } else if(!req.query.apikey && req.headers.apikey){ + req.query.apikey = req.headers.apikey; + } - if (!user) + passport.authenticate('localapikey', function (err, user, info) { + if (err) { + return res.status(500).send('Internal Server Error with API. Sorry about that!'); + } + + if (!user) { + console.log('no user for apikey'); return res.status(401).send(info.message || ''); + } req.login(user, function(loginErr) { if (loginErr) return res.sendStatus(500); diff --git a/config/strategies/apikey.js b/config/strategies/apikey.js index c4fdf389..5677b730 100644 --- a/config/strategies/apikey.js +++ b/config/strategies/apikey.js @@ -11,13 +11,15 @@ module.exports = function() { return User.findOne({ 'apiKey': apiKey }, function(err, user) { - if (err) + if (err) { return done(err); + } - if (!user) + if (!user){ return done(null, false, { message: 'Unknown API Key' }); + } return done(null, user); }); diff --git a/gruntfile.js b/gruntfile.js index f5630667..31e96e62 100755 --- a/gruntfile.js +++ b/gruntfile.js @@ -211,7 +211,7 @@ module.exports = function(grunt) { coverageFolder: 'coverageServer', mask: '*.test.js', require: ['server.js'], - reportFormats: ['cobertura','lcovonly'] + reportFormats: ['html','lcovonly'] } } }, @@ -219,7 +219,7 @@ module.exports = function(grunt) { options: { emitters: ['event'], }, - src: ['./coverageServer/*.info', './clientCoverage/lcov-report/*.info'] + src: ['./coverageServerg/*.info', './clientCoverage/lcov-report/*.info'] }, html2js: { options: { @@ -283,7 +283,7 @@ module.exports = function(grunt) { }); // Code coverage tasks. - grunt.registerTask('coveralls', ['env:test','lcovMerge']); + grunt.registerTask('coveralls', ['test:client', 'karma:unit', 'mocha_istanbul:coverageServer', 'lcovMerge']); grunt.registerTask('coverage:server', ['env:test', 'mocha_istanbul:coverageServer']); // Default task(s). @@ -310,7 +310,7 @@ module.exports = function(grunt) { grunt.registerTask('test', ['test:server', 'test:client']); grunt.registerTask('test:server', ['lint:tests', 'env:test', 'mochaTest']); grunt.registerTask('test:client', ['lint:tests', 'html2js:main', 'html2js:forms', 'env:test', 'karma:unit']); - grunt.registerTask('test:travis', ['env:test', 'html2js:main', 'html2js:forms', 'env:test', 'karma:unit', 'mochaTest', 'coveralls']); + grunt.registerTask('test:travis', ['env:test', 'html2js:main', 'html2js:forms', 'env:test', 'karma:unit', 'mochaTest']); grunt.registerTask('testdebug', ['env:test', 'karma:debug']); diff --git a/package.json b/package.json index feb9243b..7b8b7ef4 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "generate": "all-contributors generate", "start": "grunt", "test": "grunt test", - "travis": "grunt test:travis", + "travis": "grunt travis", "postinstall": "bower install --config.interactive=false; grunt build;", "init": "node scripts/setup.js" }, diff --git a/server.js b/server.js index 4f516183..b5b26931 100755 --- a/server.js +++ b/server.js @@ -62,9 +62,6 @@ console.log('--'); console.log(chalk.green('Environment:\t\t\t' + process.env.NODE_ENV)); console.log(chalk.green('Port:\t\t\t\t' + config.port)); console.log(chalk.green('Database:\t\t\t' + config.db.uri)); -if (process.env.NODE_ENV === 'secure') { - console.log(chalk.green('HTTPs:\t\t\t\ton')); -} console.log('--'); process.on('uncaughtException', function (err) { From 8d9e66548b4a5daac1f324b417191c4a3b39e14a Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 21:37:22 -0700 Subject: [PATCH 22/29] remove references to i18n-lint --- gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gruntfile.js b/gruntfile.js index 31e96e62..5f53b28a 100755 --- a/gruntfile.js +++ b/gruntfile.js @@ -297,7 +297,7 @@ module.exports = function(grunt) { grunt.registerTask('secure', ['env:secure', 'lint', 'html2js:main', 'html2js:forms', 'concurrent:default']); // Lint task(s). - grunt.registerTask('lint', ['jshint', 'csslint', 'i18nlint:client', 'i18nlint:server']); + grunt.registerTask('lint', ['jshint', 'csslint']); grunt.registerTask('lint:tests', ['jshint:allTests']); // Build task(s). From 26716e256dd5b87fbef8b85d8af2f8bfb0da90a2 Mon Sep 17 00:00:00 2001 From: David Baldwynn Date: Sun, 29 Oct 2017 21:54:30 -0700 Subject: [PATCH 23/29] migrating to yarn --- package.json | 3 +- public/dist/application.js | 4454 +------------------ public/dist/application.min.js | 7 +- public/dist/vendor.min.js | 30 +- yarn.lock | 7301 ++++++++++++++++++++++++++++++++ 5 files changed, 7525 insertions(+), 4270 deletions(-) create mode 100644 yarn.lock diff --git a/package.json b/package.json index 7b8b7ef4..1848192f 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ }, "dependencies": { "async": "^1.4.2", - "bcrypt": "^0.8.7", + "bcrypt": "~1.0.3", "body-parser": "~1.14.1", "bower": "~1.6.5", "chalk": "^1.1.3", @@ -92,7 +92,6 @@ "grunt-contrib-uglify": "^0.11.1", "grunt-contrib-watch": "~0.6.1", "grunt-execute": "^0.2.2", - "grunt-i18nlint": "github:jwarby/grunt-i18nlint", "grunt-karma": "~0.12.1", "grunt-lcov-merge": "^1.2.3", "grunt-mocha-istanbul": "^3.0.1", diff --git a/public/dist/application.js b/public/dist/application.js index 0833220a..92f6ce4e 100644 --- a/public/dist/application.js +++ b/public/dist/application.js @@ -1,35 +1,10 @@ 'use strict'; -// Init the application configuration module for AngularJS application -var ApplicationConfiguration = (function() { - // Init module configuration options - var applicationModuleName = 'TellForm'; - var applicationModuleVendorDependencies = ['duScroll', 'ui.select', 'ngSanitize', 'vButton', 'ngResource', 'TellForm.templates', 'ui.router', 'ui.bootstrap', 'ui.utils', 'pascalprecht.translate', 'view-form']; - - // Add a new vertical module - var registerModule = function(moduleName, dependencies) { - // Create angular module - angular.module(moduleName, dependencies || []); - - // Add the module to the AngularJS configuration file - angular.module(applicationModuleName).requires.push(moduleName); - }; - - return { - applicationModuleName: applicationModuleName, - applicationModuleVendorDependencies: applicationModuleVendorDependencies, - registerModule: registerModule - }; -})(); - -'use strict'; - //Start by defining the main module and adding the module dependencies angular.module(ApplicationConfiguration.applicationModuleName, ApplicationConfiguration.applicationModuleVendorDependencies); // Setting HTML5 Location Mode -angular.module(ApplicationConfiguration.applicationModuleName).config(['$locationProvider', - function($locationProvider) { +angular.module(ApplicationConfiguration.applicationModuleName).config(["$locationProvider", function($locationProvider) { $locationProvider.hashPrefix('!'); } ]); @@ -61,4213 +36,29 @@ angular.element(document).ready(function() { angular.bootstrap(document, [ApplicationConfiguration.applicationModuleName]); }); -angular.module('TellForm.templates', []).run(['$templateCache', function($templateCache) { - "use strict"; - $templateCache.put("modules/core/views/header.client.view.html", - "
"); - $templateCache.put("modules/forms/admin/views/admin-form.client.view.html", - "

{{ 'TELLFORM_URL' | translate }}
{{ 'COPY_AND_PASTE' | translate }}
{{ 'BACKGROUND_COLOR' | translate }}
{{ 'QUESTION_TEXT_COLOR' | translate }}
{{ 'ANSWER_TEXT_COLOR' | translate }}
{{ 'BTN_BACKGROUND_COLOR' | translate }}
{{ 'BTN_TEXT_COLOR' | translate }}
"); - $templateCache.put("modules/forms/admin/views/list-forms.client.view.html", - "

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

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

{{ 'FORM_PAUSED' | translate }}
"); - $templateCache.put("modules/forms/admin/views/adminTabs/analyze.html", - ""); - $templateCache.put("modules/forms/admin/views/adminTabs/configure.html", - ""); - $templateCache.put("modules/forms/admin/views/adminTabs/create.html", - ""); - $templateCache.put("modules/forms/admin/views/directiveViews/form/configure-form.client.view.html", - "
{{ 'FORM_NAME' | translate }}
{{ 'FORM_STATUS' | translate }}
{{ 'LANGUAGE' | translate }}
* {{ 'REQUIRED_FIELD' | translate }}
{{ 'GA_TRACKING_CODE' | translate }}
{{ 'DISPLAY_FOOTER' | translate }}
{{ 'DISPLAY_START_PAGE' | translate }}
{{ 'DISPLAY_END_PAGE' | translate }}
"); - $templateCache.put("modules/forms/admin/views/directiveViews/form/edit-form.client.view.html", - "

{{ 'ADD_FIELD_LG' | translate }}

{{ 'ADD_FIELD_MD' | translate }}

{{ 'ADD_FIELD_SM' | translate }}

{{ 'WELCOME_SCREEN' | translate }}


{{field.title}} *

{{ 'CLICK_FIELDS_FOOTER' | translate }}


{{ 'END_SCREEN' | translate }}

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

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

{{ 'ACCESS_DENIED_TEXT' | translate }}

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

{{ 'SUCCESS_HEADER' | translate }}

{{ 'SUCCESS_TEXT' | translate }}

{{ 'NOT_ACTIVATED_YET' | translate }}



{{ 'BEFORE_YOU_CONTINUE' | translate }} team@tellform.com

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

{{ 'PASSWORD_RESET_INVALID' | translate }}

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

{{ 'PASSWORD_RESET_SUCCESS' | translate }}

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

{{ 'RESET_PASSWORD' | translate }}

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

{{ 'CHANGE_PASSWORD' | translate }}


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

{{ 'EDIT_PROFILE' | translate }}

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

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

{{ 'CONNECTED_SOCIAL_ACCOUNTS' | translate }}:

{{ 'CONNECT_OTHER_SOCIAL_ACCOUNTS' | translate }}

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

{{ 'VERIFICATION_EMAIL_SENT' | translate }}

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

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

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

{{ 'VERIFY_SUCCESS' | translate }}

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

{{pageData.introTitle}}

{{pageData.introParagraph}}

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

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

{{field.description}}

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

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

{{field.description}}


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

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


{{field.description}}


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

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

{{field.description}}


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

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

{{field.description}}

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

{{field.title}}

{{field.description}}

{{field.description}}


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

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

{{ 'NEWLINE' | translate }}

{{field.description}}

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

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

{{field.description}}

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

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

{{field.description}}


"); - $templateCache.put("form_modules/forms/base/views/directiveViews/form/submit-form.client.view.html", - "
{{ 'COMPLETING_NEEDED' | translate:translateAdvancementData }}
{{ 'ENTER' | translate }}

{{ 'ADVANCEMENT' | translate:translateAdvancementData }}

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

404 - Form Does not Exist

The form you are trying to access does not exist. Sorry about that!
"); - $templateCache.put("form_modules/forms/base/views/form-unauthorized.client.view.html", - "

Not Authorized to Access Form

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

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

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

{{ \'FORM_PAUSED\' | translate }}
'),a.put("modules/forms/admin/views/adminTabs/analyze.html",""),a.put("modules/forms/admin/views/adminTabs/configure.html",""),a.put("modules/forms/admin/views/adminTabs/create.html",""),a.put("modules/forms/admin/views/directiveViews/form/configure-form.client.view.html",'
{{ \'FORM_NAME\' | translate }}
{{ \'FORM_STATUS\' | translate }}
{{ \'LANGUAGE\' | translate }}
* {{ \'REQUIRED_FIELD\' | translate }}
{{ \'GA_TRACKING_CODE\' | translate }}
{{ \'DISPLAY_FOOTER\' | translate }}
{{ \'DISPLAY_START_PAGE\' | translate }}
{{ \'DISPLAY_END_PAGE\' | translate }}
'),a.put("modules/forms/admin/views/directiveViews/form/edit-form.client.view.html",'

{{ \'WELCOME_SCREEN\' | translate }}


{{field.title}} *

{{ \'CLICK_FIELDS_FOOTER\' | translate }}


{{ \'END_SCREEN\' | translate }}

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

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

{{ 'ACCESS_DENIED_TEXT' | translate }}

{{ 'SIGNIN_BTN' | translate }}
"),a.put("modules/users/views/authentication/signin.client.view.html",'
'),a.put("modules/users/views/authentication/signup-success.client.view.html",''),a.put("modules/users/views/authentication/signup.client.view.html",''),a.put("modules/users/views/password/forgot-password.client.view.html",'
Error: {{error}}
{{success}}
'),a.put("modules/users/views/password/reset-password-invalid.client.view.html","

{{ 'PASSWORD_RESET_INVALID' | translate }}

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

{{ 'PASSWORD_RESET_SUCCESS' | translate }}

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

{{ \'RESET_PASSWORD\' | translate }}

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

{{ \'CHANGE_PASSWORD\' | translate }}

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

{{ \'EDIT_PROFILE\' | translate }}

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

{{ \'CONNECTED_SOCIAL_ACCOUNTS\' | translate }}:

{{ \'CONNECT_OTHER_SOCIAL_ACCOUNTS\' | translate }}

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

{{ \'VERIFICATION_EMAIL_SENT\' | translate }}

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

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

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

{{ \'VERIFY_SUCCESS\' | translate }}

'),a.put("form_modules/forms/base/views/directiveViews/entryPage/startPage.html",'

{{pageData.introTitle}}

{{pageData.introParagraph}}

'),a.put("form_modules/forms/base/views/directiveViews/field/date.html",'

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

{{field.description}}

'),a.put("form_modules/forms/base/views/directiveViews/field/dropdown.html",'
'),a.put("form_modules/forms/base/views/directiveViews/field/hidden.html",""),a.put("form_modules/forms/base/views/directiveViews/field/legal.html",'
'),a.put("form_modules/forms/base/views/directiveViews/field/radio.html",'

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

{{field.description}}


'),a.put("form_modules/forms/base/views/directiveViews/field/rating.html",'

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

{{field.description}}

'),a.put("form_modules/forms/base/views/directiveViews/field/statement.html",'

{{field.title}}

{{field.description}}

{{field.description}}


'),a.put("form_modules/forms/base/views/directiveViews/field/textarea.html",'

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

{{ \'NEWLINE\' | translate }}

{{field.description}}

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

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

{{field.description}}

{{ \'ENTER\' | translate }}
'), -a.put("form_modules/forms/base/views/directiveViews/field/yes_no.html",'

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

{{field.description}}


'),a.put("form_modules/forms/base/views/directiveViews/form/submit-form.client.view.html",'
{{ \'COMPLETING_NEEDED\' | translate:translateAdvancementData }}
'),a.put("form_modules/forms/base/views/form-not-found.client.view.html",'

404 - Form Does not Exist

The form you are trying to access does not exist. Sorry about that!
'),a.put("form_modules/forms/base/views/form-unauthorized.client.view.html",'

Not Authorized to Access Form

The form you are trying to access is currently private and not accesible publically.
If you are the owner of the form, you can set it to "Public" in the "Configuration" panel in the form admin.
'),a.put("form_modules/forms/base/views/submit-form.client.view.html","
")}]),ApplicationConfiguration.registerModule("core",["users"]),ApplicationConfiguration.registerModule("forms",["ngFileUpload","ui.router.tabs","ui.date","ui.sortable","angular-input-stars","users","ngclipboard"]),ApplicationConfiguration.registerModule("users"),angular.module("core").config(["$stateProvider","$urlRouterProvider",function(a,b,c){b.otherwise("/forms")}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","$state","$stateParams",function(a,b,c,d){a.$state=c,a.$stateParams=d,a.$on("$stateChangeSuccess",function(a,d,e,f){c.previous=f;var g=["home","signin","resendVerifyEmail","verify","signup","signup-success","forgot","reset-invalid","reset","reset-success"];g.indexOf(d.name)>0?b.isAuthenticated()&&(a.preventDefault(),c.go("listForms")):"access_denied"===d.name||b.isAuthenticated()||"submitForm"===d.name||(a.preventDefault(),c.go("listForms"))})}]),angular.module(ApplicationConfiguration.applicationModuleName).run(["$rootScope","Auth","User","Authorizer","$state","$stateParams",function(a,b,c,d,e,f){a.$on("$stateChangeStart",function(a,f){var g,h,i;h=f&&f.data&&f.data.permissions?f.data.permissions:null,b.ensureHasCurrentUser(c),i=b.currentUser,i&&(g=new d(i),null!==h&&(g.canAccess(h)||(a.preventDefault(),e.go("access_denied"))))})}]),angular.module("core").controller("HeaderController",["$rootScope","$scope","Menus","$state","Auth","User","$window","$translate",function(a,b,c,d,e,f,g,h){a.signupDisabled=g.signupDisabled,b.user=a.user=e.ensureHasCurrentUser(f),b.authentication=a.authentication=e,a.languages=b.languages=["en","fr","es","it","de"],a.language=b.user.language,h.use(b.user.language),b.isCollapsed=!1,a.hideNav=!1,b.menu=c.getMenu("topbar"),b.signout=function(){var c=f.logout();c.then(function(){e.logout(),e.ensureHasCurrentUser(f),b.user=a.user=null,d.go("listForms"),d.reload()},function(a){console.error("Logout Failed: "+a)})},b.toggleCollapsibleMenu=function(){b.isCollapsed=!b.isCollapsed},b.$on("$stateChangeSuccess",function(c,d,e,f,g){b.isCollapsed=!1,a.hideNav=!1,angular.isDefined(d.data)&&angular.isDefined(d.data.hideNav)&&(a.hideNav=d.data.hideNav)})}]),angular.module("core").service("Menus",[function(){this.defaultRoles=["*"],this.menus={};var a=function(a){if(a){if(~this.roles.indexOf("*"))return!0;for(var b in a.roles)for(var c in this.roles)if(this.roles[c]===a.roles[b])return!0;return!1}return this.isPublic};this.validateMenuExistance=function(a){if(a&&a.length){if(this.menus[a])return!0;throw new Error("Menu does not exists")}throw new Error("MenuId was not provided")},this.getMenu=function(a){return this.validateMenuExistance(a),this.menus[a]},this.addMenu=function(b,c,d){return this.menus[b]={isPublic:c||!1,roles:d||this.defaultRoles,items:[],shouldRender:a},this.menus[b]},this.removeMenu=function(a){this.validateMenuExistance(a),delete this.menus[a]},this.addMenuItem=function(b,c,d,e,f,g,h,i){return this.validateMenuExistance(b),this.menus[b].items.push({title:c,link:d,menuItemType:e||"item",menuItemClass:e,uiRoute:f||"/"+d,isPublic:null===g||"undefined"==typeof g?this.menus[b].isPublic:g,roles:null===h||"undefined"==typeof h?this.menus[b].roles:h,position:i||0,items:[],shouldRender:a}),this.menus[b]},this.addSubMenuItem=function(b,c,d,e,f,g,h,i){this.validateMenuExistance(b);for(var j in this.menus[b].items)this.menus[b].items[j].link===c&&this.menus[b].items[j].items.push({title:d,link:e,uiRoute:f||"/"+e,isPublic:null===g||"undefined"==typeof g?this.menus[b].items[j].isPublic:g,roles:null===h||"undefined"==typeof h?this.menus[b].items[j].roles:h,position:i||0,shouldRender:a});return this.menus[b]},this.removeMenuItem=function(a,b){this.validateMenuExistance(a);for(var c in this.menus[a].items)this.menus[a].items[c].link===b&&this.menus[a].items.splice(c,1);return this.menus[a]},this.removeSubMenuItem=function(a,b){this.validateMenuExistance(a);for(var c in this.menus[a].items)for(var d in this.menus[a].items[c].items)this.menus[a].items[c].items[d].link===b&&this.menus[a].items[c].items.splice(d,1);return this.menus[a]},this.addMenu("topbar",!1,["*"]),this.addMenu("bottombar",!1,["*"])}]),angular.module("core").factory("subdomain",["$location",function(a){var b=a.host();return b.indexOf(".")<0?null:b.split(".")[0]}]),angular.module("forms").run(["Menus",function(a){a.addMenuItem("topbar","My Forms","forms","","/forms",!1)}]).filter("secondsToDateTime",[function(){return function(a){return new Date(1970,0,1).setSeconds(a)}}]).filter("formValidity",[function(){return function(a){if(a&&a.form_fields&&a.visible_form_fields){var b=Object.keys(a),c=(b.filter(function(a){return"$"!==a[0]}),a.form_fields),d=c.filter(function(a){return"object"==typeof a&&"statement"!==a.fieldType&&"rating"!==a.fieldType?!!a.fieldValue:"rating"===a.fieldType||void 0}).length;return d-(a.form_fields.length-a.visible_form_fields.length)}return 0}}]).filter("trustSrc",["$sce",function(a){return function(b){return a.trustAsResourceUrl(b)}}]).config(["$provide",function(a){a.decorator("accordionDirective",["$delegate",function(a){var b=a[0];return b.replace=!0,a}])}]),angular.module("forms").config(["$stateProvider",function(a){a.state("listForms",{url:"/forms",templateUrl:"modules/forms/admin/views/list-forms.client.view.html",resolve:{Forms:"GetForms",myForms:["GetForms","$q",function(a,b){var c=b.defer();return a.query(function(a){c.resolve(a)}),c.promise}]},controller:"ListFormsController",controllerAs:"ctrl"}).state("submitForm",{url:"/forms/:formId",templateUrl:"/static/form_modules/forms/base/views/submit-form.client.view.html",data:{hideNav:!0},resolve:{Forms:"GetForms",myForm:["GetForms","$stateParams","$q",function(a,b,c){var d=c.defer();return a.get({formId:b.formId},function(a){d.resolve(a)}),d.promise}]},controller:"SubmitFormController",controllerAs:"ctrl"}).state("viewForm",{url:"/forms/:formId/admin",templateUrl:"modules/forms/admin/views/admin-form.client.view.html",data:{permissions:["editForm"]},resolve:{GetForms:"GetForms",myForm:["GetForms","$stateParams","$q",function(a,b,c){var d=c.defer();return a.get({formId:b.formId},function(a){d.resolve(a)}),d.promise}]},controller:"AdminFormController"}).state("viewForm.configure",{url:"/configure",templateUrl:"modules/forms/admin/views/adminTabs/configure.html"}).state("viewForm.design",{url:"/design",templateUrl:"modules/forms/admin/views/adminTabs/design.html"}).state("viewForm.analyze",{url:"/analyze",templateUrl:"modules/forms/admin/views/adminTabs/analyze.html"}).state("viewForm.create",{url:"/create",templateUrl:"modules/forms/admin/views/adminTabs/create.html"})}]),angular.module("forms").factory("GetForms",["$resource","FORM_URL",function(a,b){return a(b,{formId:"@_id"},{query:{method:"GET",isArray:!0},get:{method:"GET",transformResponse:function(a,b){var c=angular.fromJson(a);return c.visible_form_fields=_.filter(c.form_fields,function(a){return a.deletePreserved===!1}),c}},update:{method:"PUT"},save:{method:"POST"}})}]),angular.module("users").config(["$httpProvider",function(a){a.interceptors.push(["$q","$location",function(a,b){return{responseError:function(c){return"/users/me"!==b.path()&&c.config&&"/users/me"!==c.config.url&&(401===c.status?(b.nextAfterLogin=b.path(),b.path("/signin")):403===c.status&&b.path("/access_denied")),a.reject(c)}}}])}]),angular.module("users").config(["$stateProvider",function(a){var b=function(a,b,c,d,e){var f=a.defer();return e.currentUser&&e.currentUser.email?b(f.resolve):e.currentUser=d.getCurrent(function(){e.login(),b(f.resolve())},function(){e.logout(),b(f.reject()),c.go("signin",{reload:!0})}),f.promise};b.$inject=["$q","$timeout","$state","User","Auth"];var c=function(a,b,c){var d=c.defer();return b(a.signupDisabled?d.reject():d.resolve()),d.promise};c.$inject=["$window","$timeout","$q"],a.state("profile",{resolve:{loggedin:b},url:"/settings/profile",templateUrl:"modules/users/views/settings/edit-profile.client.view.html"}).state("password",{resolve:{loggedin:b},url:"/settings/password",templateUrl:"modules/users/views/settings/change-password.client.view.html"}).state("accounts",{resolve:{loggedin:b},url:"/settings/accounts",templateUrl:"modules/users/views/settings/social-accounts.client.view.html"}).state("signup",{resolve:{isDisabled:c},url:"/signup",templateUrl:"modules/users/views/authentication/signup.client.view.html"}).state("signup-success",{resolve:{isDisabled:c},url:"/signup-success",templateUrl:"modules/users/views/authentication/signup-success.client.view.html"}).state("signin",{url:"/signin",templateUrl:"modules/users/views/authentication/signin.client.view.html"}).state("access_denied",{url:"/access_denied",templateUrl:"modules/users/views/authentication/access-denied.client.view.html"}).state("verify",{resolve:{isDisabled:c},url:"/verify/:token",templateUrl:"modules/users/views/verify/verify-account.client.view.html"}).state("resendVerifyEmail",{resolve:{isDisabled:c},url:"/verify",templateUrl:"modules/users/views/verify/resend-verify-email.client.view.html"}).state("forgot",{url:"/password/forgot",templateUrl:"modules/users/views/password/forgot-password.client.view.html"}).state("reset-invalid",{url:"/password/reset/invalid",templateUrl:"modules/users/views/password/reset-password-invalid.client.view.html"}).state("reset-success",{url:"/password/reset/success",templateUrl:"modules/users/views/password/reset-password-success.client.view.html"}).state("reset",{url:"/password/reset/:token",templateUrl:"modules/users/views/password/reset-password.client.view.html"})}]),angular.module("users").controller("AuthenticationController",["$scope","$location","$state","$rootScope","User","Auth","$translate","$window",function(a,b,c,d,e,f,g,h){a=d,a.credentials={},a.error="",a.forms={},a.signin=function(){a.forms.signinForm.$invalid||e.login(a.credentials).then(function(b){f.login(b),a.user=d.user=f.ensureHasCurrentUser(e),"home"!==c.previous.name&&"verify"!==c.previous.name&&""!==c.previous.name?c.go(c.previous.name):c.go("listForms")},function(b){d.user=f.ensureHasCurrentUser(e),a.user=d.user,a.error=b,console.error("loginError: "+b)})},a.signup=function(){return"admin"===a.credentials?void(a.error="Username cannot be 'admin'. Please pick another username."):void(a.forms.signupForm.$invalid||e.signup(a.credentials).then(function(a){c.go("signup-success")},function(b){console.error(b),b?(a.error=b,console.error(b)):console.error("No response received")}))}}]),angular.module("users").controller("PasswordController",["$scope","$stateParams","$state","User","$translate","$window",function(a,b,c,d,e,f){e.use(f.locale),a.error="",a.forms={},a.askForPasswordReset=function(){d.askForPasswordReset(a.credentials).then(function(b){a.success=b.message,a.error=null,a.credentials=null},function(b){a.error=b,a.success=null,a.credentials=null})},a.resetUserPassword=function(){a.forms.resetPasswordForm.$invalid||(a.success=a.error=null,d.resetPassword(a.passwordDetails,b.token).then(function(b){a.success=b.message,a.error=null,a.passwordDetails=null,c.go("reset-success")},function(b){a.error=b.message||b,a.success=null,a.passwordDetails=null}))}}]),angular.module("users").controller("SettingsController",["$scope","$rootScope","$http","$state","Users","Auth",function(a,b,c,d,e,f){a.user=f.currentUser,a.hasConnectedAdditionalSocialAccounts=function(b){for(var c in a.user.additionalProvidersData)return!0;return!1},a.cancel=function(){a.user=f.currentUser},a.isConnectedSocialAccount=function(b){return a.user.provider===b||a.user.additionalProvidersData&&a.user.additionalProvidersData[b]},a.removeUserSocialAccount=function(b){a.success=a.error=null,c["delete"]("/users/accounts",{params:{provider:b}}).success(function(b){a.success=!0,a.error=null,a.user=b}).error(function(b){a.success=null,a.error=b.message})},a.updateUserProfile=function(b){if(b){a.success=a.error=null;var c=new e(a.user);c.$update(function(b){a.success=!0,a.error=null,a.user=b},function(b){a.success=null,a.error=b.data.message})}else a.submitted=!0},a.changeUserPassword=function(){a.success=a.error=null,c.post("/users/password",a.passwordDetails).success(function(b){a.success=!0,a.error=null,a.passwordDetails=null}).error(function(b){a.success=null,a.error=b.message})}}]),angular.module("users").controller("VerifyController",["$scope","$state","$rootScope","User","Auth","$stateParams","$translate","$window",function(a,b,c,d,e,f,g,h){g.use(h.locale),a.isResetSent=!1,a.credentials={},a.error="",a.resendVerifyEmail=function(){d.resendVerifyEmail(a.credentials.email).then(function(b){a.success=b.message,a.error=null,a.credentials=null,a.isResetSent=!0},function(b){a.error=b,a.success=null,a.credentials.email=null,a.isResetSent=!1})},a.validateVerifyToken=function(){f.token&&(console.log(f.token),d.validateVerifyToken(f.token).then(function(b){a.success=b.message,a.error=null,a.isResetSent=!0,a.credentials.email=null},function(b){a.isResetSent=!1,a.success=null,a.error=b,a.credentials.email=null}))}}]),angular.module("users").factory("Auth",["$window",function(a){var b={isLoggedIn:!1},c={_currentUser:null,get currentUser(){return this._currentUser},ensureHasCurrentUser:function(d){return c._currentUser&&c._currentUser.username?c._currentUser:a.user?(c._currentUser=a.user,c._currentUser):void d.getCurrent().then(function(d){return c._currentUser=d,b.isLoggedIn=!0,a.user=c._currentUser,c._currentUser},function(d){return b.isLoggedIn=!1,c._currentUser=null,a.user=null,null})},isAuthenticated:function(){return!!c._currentUser},getUserState:function(){return b},login:function(a){b.isLoggedIn=!0,c._currentUser=a},logout:function(){a.user=null,b.isLoggedIn=!1,c._currentUser=null}};return c}]),angular.module("users").service("Authorizer",["APP_PERMISSIONS","USER_ROLES",function(a,b){return function(c){return{canAccess:function(d){var e,f,g;for(angular.isArray(d)||(d=[d]),e=0,f=d.length;e-1;case a.viewPrivateForm:case a.editForm:return c.roles.indexOf(b.admin)>-1||c.roles.indexOf(b.normal)>-1}}return!1}}}}]),angular.module("users").factory("User",["$window","$q","$timeout","$http","$state",function(a,b,c,d,e){var f={getCurrent:function(){var a=b.defer();return d.get("/users/me").success(function(b){a.resolve(b)}).error(function(){a.reject("User's session has expired")}),a.promise},login:function(a){var c=b.defer();return d.post("/auth/signin",a).then(function(a){c.resolve(a.data)},function(a){c.reject(a.data.message||a.data)}),c.promise},logout:function(){var a=b.defer();return d.get("/auth/signout").then(function(b){a.resolve(null)},function(b){a.reject(b.data.message||b.data)}),a.promise},signup:function(a){var c=b.defer();return d.post("/auth/signup",a).then(function(a){c.resolve(a.data)},function(a){c.reject(a.data.message||a.data)}),c.promise},resendVerifyEmail:function(a){var c=b.defer();return d.post("/auth/verify",{email:a}).then(function(a){c.resolve(a.data)},function(a){c.reject(a.data.message||a.data)}),c.promise},validateVerifyToken:function(a){var c=/^([A-Za-z0-9]{48})$/g;if(!c.test(a))throw new Error("Error token: "+a+" is not a valid verification token");var e=b.defer();return d.get("/auth/verify/"+a).then(function(a){e.resolve(a.data)},function(a){e.reject(a.data)}),e.promise},resetPassword:function(a,c){var e=b.defer();return d.post("/auth/reset/"+c,a).then(function(a){e.resolve(a)},function(a){e.reject(a.data.message||a.data)}),e.promise},askForPasswordReset:function(a){var c=b.defer();return d.post("/auth/forgot",a).then(function(a){c.resolve(a.data)},function(a){c.reject(a.data.message||a.data)}),c.promise}};return f}]),angular.module("users").factory("Users",["$resource",function(a){return a("users",{},{update:{method:"PUT"}})}]),angular.module("core").config(["$translateProvider",function(a){a.translations("en",{MENU:"MENU",SIGNUP_TAB:"Sign Up",SIGNIN_TAB:"Sign In",SIGNOUT_TAB:"Signout",EDIT_PROFILE:"Edit Profile",MY_SETTINGS:"My Settings",CHANGE_PASSWORD:"Change Password",TOGGLE_NAVIGATION:"Toggle navigation"}),a.preferredLanguage("en").fallbackLanguage("en").useSanitizeValueStrategy("escape")}]),angular.module("core").config(["$translateProvider",function(a){a.translations("fr",{MENU:"MENU",SIGNUP_TAB:"Créer un Compte",SIGNIN_TAB:"Connexion",SIGNOUT_TAB:"Créer un compte",EDIT_PROFILE:"Modifier Mon Profil",MY_SETTINGS:"Mes Paramètres",CHANGE_PASSWORD:"Changer mon Mot de Pass",TOGGLE_NAVIGATION:"Basculer la navigation"})}]),angular.module("core").config(["$translateProvider",function(a){a.translations("de",{MENU:"MENÜ",SIGNUP_TAB:"Anmelden",SIGNIN_TAB:"Anmeldung",SIGNOUT_TAB:"Abmelden",EDIT_PROFILE:"Profil bearbeiten",MY_SETTINGS:"Meine Einstellungen",CHANGE_PASSWORD:"Passwort ändern",TOGGLE_NAVIGATION:"Navigation umschalten"})}]),angular.module("core").config(["$translateProvider",function(a){a.translations("it",{MENU:"MENÜ",SIGNUP_TAB:"Vi Phrasal",SIGNIN_TAB:"Accedi",SIGNOUT_TAB:"Esci",EDIT_PROFILE:"Modifica Profilo",MY_SETTINGS:"Mie Impostazioni",CHANGE_PASSWORD:"Cambia la password",TOGGLE_NAVIGATION:"Attiva la navigazione"})}]),angular.module("core").config(["$translateProvider",function(a){a.translations("es",{MENU:"MENU",SIGNUP_TAB:"Registrarse",SIGNIN_TAB:"Entrar",SIGNOUT_TAB:"Salir",EDIT_PROFILE:"Editar Perfil",MY_SETTINGS:"Mis configuraciones",CHANGE_PASSWORD:"Cambiar contraseña",TOGGLE_NAVIGATION:"Navegación de palanca"})}]),angular.module("forms").controller("AdminFormController",["$rootScope","$window","$scope","$stateParams","$state","Forms","CurrentForm","$http","$uibModal","myForm","$filter","$translate",function(a,b,c,d,e,f,g,h,i,j,k,l){c.activePill=0,c.copied=!1,c.onCopySuccess=function(a){c.copied=!0},c=a,c.animationsEnabled=!0,c.myform=j,a.saveInProgress=!1,c.oldForm=_.cloneDeep(c.myform),g.setForm(c.myform),c.formURL="/#!/forms/"+c.myform._id,c.myform.isLive?b.subdomainsDisabled===!0?c.actualFormURL=window.location.protocol+"//"+window.location.host+"/view"+c.formURL:window.location.host.split(".").length<3?c.actualFormURL=window.location.protocol+"//"+c.myform.admin.username+"."+window.location.host+c.formURL:c.actualFormURL=window.location.protocol+"//"+c.myform.admin.username+"."+window.location.host.split(".").slice(1,3).join(".")+c.formURL:c.actualFormURL=window.location.protocol+"//"+window.location.host+c.formURL;var m=c.refreshFrame=function(){document.getElementById("iframe")&&document.getElementById("iframe").contentWindow.location.reload()};c.tabData=[{heading:k("translate")("CONFIGURE_TAB"),templateName:"configure"}],c.designTabActive=!1,c.deactivateDesignTab=function(){c.designTabActive=!1},c.activateDesignTab=function(){c.designTabActive=!0},c.setForm=function(a){c.myform=a},a.resetForm=function(){c.myform=f.get({formId:d.formId})},c.openDeleteModal=function(){c.deleteModal=i.open({animation:c.animationsEnabled,templateUrl:"formDeleteModal.html",controller:"AdminFormController",resolve:{myForm:function(){return c.myform}}}),c.deleteModal.result.then(function(a){c.selected=a})},c.cancelDeleteModal=function(){c.deleteModal&&c.deleteModal.dismiss("cancel")},c.removeCurrentForm=function(){if(c.deleteModal&&c.deleteModal.opened){c.deleteModal.close();var a=c.myform._id;if(!a)throw new Error("Error - removeCurrentForm(): $scope.myform._id does not exist");h["delete"]("/forms/"+a).then(function(a){e.go("listForms",{},{reload:!0})},function(a){console.error(a)})}},c.updateDesign=function(a,b,d,e){c.update(a,b,d,e,function(){m()})},c.update=a.update=function(b,d,e,f,g){var i=!0;if(b||(i=!a.saveInProgress),i){var j=null;if(b||(a.saveInProgress=!0),e){for(var k=new RegExp("^[0-9a-fA-F]{24}$"),l=0;l]+/i,test:function(a){return!this.regExp.test(a)}},b.openDeleteModal=function(a){b.deleteModal=h.open({animation:b.animationsEnabled,templateUrl:"deleteModalListForms.html",controller:["$uibModalInstance","items","$scope",function(a,b,c){c.content=b,c.cancel=c.cancelDeleteModal,c.deleteForm=function(){c.$parent.removeForm(b.formIndex)}}],resolve:{items:function(){return{currFormTitle:b.myforms[a].title,formIndex:a}}}})},b.cancelDeleteModal=function(){ -b.deleteModal&&b.deleteModal.dismiss("cancel")},b.openCreateModal=function(){b.showCreateModal||(b.showCreateModal=!0)},b.closeCreateModal=function(){b.showCreateModal&&(b.showCreateModal=!1)},b.setForm=function(a){b.myform=a},b.goToWithId=function(a,b){d.go(a,{formId:b},{reload:!0})},b.duplicateForm=function(a){var c=_.cloneDeep(b.myforms[a]);delete c._id,g.post("/forms",{form:c}).success(function(c,d,e){b.myforms.splice(a+1,0,c)}).error(function(a){console.error(a),null===a&&(b.error=a.data.message)})},b.createNewForm=function(){var a={};a.title=b.forms.createForm.title.$modelValue,a.language=b.forms.createForm.language.$modelValue,b.forms.createForm.$valid&&b.forms.createForm.$dirty&&g.post("/forms",{form:a}).success(function(a,c,d){b.goToWithId("viewForm.create",a._id+"")}).error(function(a){console.error(a),b.error=a.data.message})},b.removeForm=function(a){if(a>=b.myforms.length||a<0)throw new Error("Error: form_index in removeForm() must be between 0 and "+b.myforms.length-1);g["delete"]("/forms/"+b.myforms[a]._id).success(function(c,d,e){b.myforms.splice(a,1),b.cancelDeleteModal()}).error(function(a){console.error(a)})}}]),angular.module("forms").directive("configureFormDirective",["$rootScope","$http","Upload","CurrentForm",function(a,b,c,d){return{templateUrl:"modules/forms/admin/views/directiveViews/form/configure-form.client.view.html",restrict:"E",scope:{myform:"=",user:"=",pdfFields:"@",formFields:"@"},controller:["$scope",function(b){b.log="",b.languages=a.languages,b.resetForm=a.resetForm,b.update=a.update}]}}]),angular.module("forms").directive("editFormDirective",["$rootScope","FormFields","$uibModal",function(a,b,c){return{templateUrl:"modules/forms/admin/views/directiveViews/form/edit-form.client.view.html",restrict:"E",transclude:!0,scope:{myform:"="},controller:["$scope",function(d){var e;d.sortableOptions={appendTo:".dropzone",forceHelperSize:!0,forcePlaceholderSize:!0,update:function(a,b){d.update(!1,d.myform,!0,!1,function(a){})}},d.openEditModal=function(a,b,e){d.editFieldModal=c.open({animation:!0,templateUrl:"editFieldModal.html",windowClass:"edit-modal-window",controller:["$uibModalInstance","$scope",function(c,d){d.field=a,d.showLogicJump=!1,d.isEdit=b,d.showAddOptions=function(a){return"dropdown"===d.field.fieldType||"checkbox"===d.field.fieldType||"radio"===d.field.fieldType},d.validShapes=["Heart","Star","thumbs-up","thumbs-down","Circle","Square","Check Circle","Smile Outlined","Hourglass","bell","Paper Plane","Comment","Trash"],d.addOption=function(){if("checkbox"===d.field.fieldType||"dropdown"===d.field.fieldType||"radio"===d.field.fieldType){d.field.fieldOptions||(d.field.fieldOptions=[]);var a=d.field.fieldOptions.length+1,b={option_id:Math.floor(1e5*Math.random()),option_title:"Option "+a,option_value:"Option "+a};d.field.fieldOptions.push(b)}},d.deleteOption=function(a){if("checkbox"===d.field.fieldType||"dropdown"===d.field.fieldType||"radio"===d.field.fieldType)for(var b=0;b',restrict:"E",scope:{typeName:"@"},controller:["$scope",function(a){var b={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"};a.typeIcon=b[a.typeName]}]}});var __indexOf=[].indexOf||function(a){for(var b=0,c=this.length;b=0&&(c=c+b+".html"),d.get(c)};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&",design:"=",index:"=",forms:"="},link:function(a,d){c.chooseDefaultOption=a.chooseDefaultOption=function(b){"yes_no"===b?a.field.fieldValue="true":"rating"===b?a.field.fieldValue=0:"radio"===a.field.fieldType?a.field.fieldValue=a.field.fieldOptions[0].option_value:"legal"===b&&(a.field.fieldValue="true",c.nextField())},a.nextField=c.nextField,a.setActiveField=c.setActiveField,"date"===a.field.fieldType&&(a.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0});var e=a.field.fieldType;if("number"===a.field.fieldType||"textfield"===a.field.fieldType||"email"===a.field.fieldType||"link"===a.field.fieldType){switch(a.field.fieldType){case"textfield":a.input_type="text";break;case"email":a.input_type="email",a.placeholder="joesmith@example.com";break;case"number":a.input_type="text",a.validateRegex=/^-?\d+$/;break;default:a.input_type="url",a.placeholder="http://example.com"}e="textfield"}var g=f(e);d.html(g).show();b(d.contents())(a)}}}]),angular.module("view-form").directive("onEnterKey",["$rootScope",function(a){return{restrict:"A",link:function(b,c,d){c.bind("keydown keypress",function(b){var c=b.which||b.keyCode,e=!1;null!==d.onEnterKeyDisabled&&(e=d.onEnterKeyDisabled),13!==c||b.shiftKey||e||(b.preventDefault(),a.$apply(function(){a.$eval(d.onEnterKey)}))})}}}]).directive("onTabKey",["$rootScope",function(a){return{restrict:"A",link:function(b,c,d){c.bind("keyup keypress",function(b){var c=b.which||b.keyCode;9!==c||b.shiftKey||(b.preventDefault(),a.$apply(function(){a.$eval(d.onTabKey)}))})}}}]).directive("onEnterOrTabKey",["$rootScope",function(a){return{restrict:"A",link:function(b,c,d){c.bind("keydown keypress",function(b){var c=b.which||b.keyCode;13!==c&&9!==c||b.shiftKey||(b.preventDefault(),a.$apply(function(){a.$eval(d.onEnterOrTabKey)}))})}}}]).directive("onTabAndShiftKey",["$rootScope",function(a){return{restrict:"A",link:function(b,c,d){c.bind("keydown keypress",function(b){var c=b.which||b.keyCode;9===c&&b.shiftKey&&(console.log("onTabAndShiftKey"),b.preventDefault(),a.$apply(function(){a.$eval(d.onTabAndShiftKey)}))})}}}]),angular.module("view-form").directive("onFinishRender",["$rootScope","$timeout",function(a,b){return{restrict:"A",link:function(b,c,d){if(c.attr("ng-repeat")||c.attr("data-ng-repeat")){var e=d.onFinishRender||"ngRepeat";b.$first&&!b.$last?b.$evalAsync(function(){a.$broadcast(e+" Started")}):b.$last&&b.$evalAsync(function(){a.$broadcast(e+" Finished")})}}}}]),jsep.addBinaryOp("contains",10),jsep.addBinaryOp("!contains",10),jsep.addBinaryOp("begins",10),jsep.addBinaryOp("!begins",10),jsep.addBinaryOp("ends",10),jsep.addBinaryOp("!ends",10),angular.module("view-form").directive("submitFormDirective",["$http","TimeCounter","$filter","$rootScope","SendVisitorData","$translate","$timeout",function(a,b,c,d,e,f,g){return{templateUrl:"form_modules/forms/base/views/directiveViews/form/submit-form.client.view.html",restrict:"E",scope:{myform:"=",ispreview:"="},controller:["$document","$window","$scope",function(f,g,h){var i=!1,j="submit_field";h.forms={},h.ispreview&&b.restartClock();var k=h.myform.visible_form_fields.filter(function(a){return"statement"!==a.fieldType}).length,l=c("formValidity")(h.myform);h.translateAdvancementData={done:l,total:k,answers_not_completed:k-l},h.reloadForm=function(){h.myform.submitted=!1,h.myform.form_fields=_.chain(h.myform.visible_form_fields).map(function(a){return a.fieldValue="",a}).value(),h.loading=!1,h.error="",h.selected={_id:"",index:0},h.setActiveField(h.myform.visible_form_fields[0]._id,0,!1),b.restartClock()};var m=function(a){var b=a.logicJump;if(b.enabled&&b.expressionString&&b.valueB&&a.fieldValue){var c,d,e=jsep(b.expressionString);if("field"===e.left.name?(c=a.fieldValue,d=b.valueB):(c=b.valueB,d=a.fieldValue),"number"===a.fieldType||"scale"===a.fieldType||"rating"===a.fieldType)switch(e.operator){case"==":return parseInt(c)===parseInt(d);case"!==":return parseInt(c)!==parseInt(d);case">":return parseInt(c)>parseInt(d);case">=":return parseInt(c)>parseInt(d);case"<":return parseInt(c)-1;case"!contains": -return!(c.indexOf(d)>-1);case"begins":return c.startsWith(d);case"!begins":return!c.startsWith(d);case"ends":return c.endsWith(d);case"!ends":return c.endsWith(d);default:return!1}}},n=function(){if(null===h.selected)throw console.error("current active field is null"),new Error("current active field is null");return h.selected._id===j?h.myform.form_fields.length-1:h.selected.index};h.isActiveField=function(a){return h.selected._id===a._id},h.setActiveField=d.setActiveField=function(a,b,d){if(null!==h.selected&&(a||null!==b)){if(a){if(null===b){b=h.myform.visible_form_fields.length;for(var e=0;e .field-directive:nth-of-type("+String(h.myform.visible_form_fields.length-1)+")"),m=$(l).height(),n=k-g-1.2*m,o=.9;h.selected.index===h.myform.visible_form_fields.length?bn?(a=h.selected.index+1,h.setActiveField(j,a,!1)):ef*o&&(a=h.selected.index-1,h.setActiveField(null,a,!1))}h.$apply()},d.nextField=h.nextField=function(){if(h.selected&&h.selected.index>-1)if(h.selected._id!==j){var a=h.myform.visible_form_fields[h.selected.index];a.logicJump&&a.logicJump.jumpTo&&m(a)?h.setActiveField(a.logicJump.jumpTo,null,!0):h.selected.index0&&h.setActiveField(null,a,!0)},d.goToInvalid=h.goToInvalid=function(){var a=$(".row.field-directive .ng-invalid.focusOn, .row.field-directive .ng-untouched.focusOn:not(.ng-valid)").first().parents(".row.field-directive").first().attr("data-id");h.setActiveField(a,null,!0)},h.exitStartPage=function(){h.myform.startPage.showStart=!1,h.myform.visible_form_fields.length>0&&(h.selected._id=h.myform.visible_form_fields[0]._id)};var o=function(){var a=new MobileDetect(window.navigator.userAgent),b="other";return a.tablet()?b="tablet":a.mobile()?b="mobile":a.is("bot")||(b="desktop"),{type:b,name:window.navigator.platform}},p=function(){$.ajaxSetup({async:!1});var a=$.getJSON("https://freegeoip.net/json/").responseJSON;return $.ajaxSetup({async:!0}),a&&a.ip||(a={ip:"Adblocker"}),{ipAddr:a.ip,geoLocation:{City:a.city,Country:a.country_name}}};d.submitForm=h.submitForm=function(){if(h.forms.myForm.$invalid)return void h.goToInvalid();var d=b.stopClock();h.loading=!0;var f=_.cloneDeep(h.myform),g=o();f.device=g;var i=p();f.ipAddr=i.ipAddr,f.geoLocation=i.geoLocation,f.timeElapsed=d,f.percentageComplete=c("formValidity")(h.myform)/h.myform.visible_form_fields.length*100,delete f.endPage,delete f.isLive,delete f.provider,delete f.startPage,delete f.visible_form_fields,delete f.analytics,delete f.design,delete f.submissions,delete f.submitted;for(var j=0;j',restrict:"E",scope:{typeName:"@"},controller:["$scope",function(a){var b={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"};a.typeIcon=b[a.typeName]}]}});var __indexOf=[].indexOf||function(a){for(var b=0,c=this.length;b=0&&(c=c+b+".html"),d.get(c)};return{template:"
{{field.title}}
",restrict:"E",scope:{field:"=",required:"&",design:"=",index:"=",forms:"="},link:function(a,d){c.chooseDefaultOption=a.chooseDefaultOption=function(b){"yes_no"===b?a.field.fieldValue="true":"rating"===b?a.field.fieldValue=0:"radio"===a.field.fieldType?a.field.fieldValue=a.field.fieldOptions[0].option_value:"legal"===b&&(a.field.fieldValue="true",c.nextField())},a.nextField=c.nextField,a.setActiveField=c.setActiveField,"date"===a.field.fieldType&&(a.dateOptions={changeYear:!0,changeMonth:!0,altFormat:"mm/dd/yyyy",yearRange:"1900:-0",defaultDate:0});var e=a.field.fieldType;if("number"===a.field.fieldType||"textfield"===a.field.fieldType||"email"===a.field.fieldType||"link"===a.field.fieldType){switch(a.field.fieldType){case"textfield":a.input_type="text";break;case"email":a.input_type="email",a.placeholder="joesmith@example.com";break;case"number":a.input_type="text",a.validateRegex=/^-?\d+$/;break;default:a.input_type="url",a.placeholder="http://example.com"}e="textfield"}var g=f(e);d.html(g).show();b(d.contents())(a)}}}]),angular.module("view-form").directive("onEnterKey",["$rootScope",function(a){return{restrict:"A",link:function(b,c,d){c.bind("keydown keypress",function(b){var c=b.which||b.keyCode,e=!1;null!==d.onEnterKeyDisabled&&(e=d.onEnterKeyDisabled),13!==c||b.shiftKey||e||(b.preventDefault(),a.$apply(function(){a.$eval(d.onEnterKey)}))})}}}]).directive("onTabKey",["$rootScope",function(a){return{restrict:"A",link:function(b,c,d){c.bind("keyup keypress",function(b){var c=b.which||b.keyCode;9!==c||b.shiftKey||(b.preventDefault(),a.$apply(function(){a.$eval(d.onTabKey)}))})}}}]).directive("onEnterOrTabKey",["$rootScope",function(a){return{restrict:"A",link:function(b,c,d){c.bind("keydown keypress",function(b){var c=b.which||b.keyCode;13!==c&&9!==c||b.shiftKey||(b.preventDefault(),a.$apply(function(){a.$eval(d.onEnterOrTabKey)}))})}}}]).directive("onTabAndShiftKey",["$rootScope",function(a){return{restrict:"A",link:function(b,c,d){c.bind("keydown keypress",function(b){var c=b.which||b.keyCode;9===c&&b.shiftKey&&(console.log("onTabAndShiftKey"),b.preventDefault(),a.$apply(function(){a.$eval(d.onTabAndShiftKey)}))})}}}]),angular.module("view-form").directive("onFinishRender",["$rootScope","$timeout",function(a,b){return{restrict:"A",link:function(b,c,d){if(c.attr("ng-repeat")||c.attr("data-ng-repeat")){var e=d.onFinishRender||"ngRepeat";b.$first&&!b.$last?b.$evalAsync(function(){a.$broadcast(e+" Started")}):b.$last&&b.$evalAsync(function(){a.$broadcast(e+" Finished")})}}}}]),jsep.addBinaryOp("contains",10),jsep.addBinaryOp("!contains",10),jsep.addBinaryOp("begins",10),jsep.addBinaryOp("!begins",10),jsep.addBinaryOp("ends",10),jsep.addBinaryOp("!ends",10),angular.module("view-form").directive("submitFormDirective",["$http","TimeCounter","$filter","$rootScope","SendVisitorData","$translate","$timeout",function(a,b,c,d,e,f,g){return{templateUrl:"form_modules/forms/base/views/directiveViews/form/submit-form.client.view.html",restrict:"E",scope:{myform:"=",ispreview:"="},controller:["$document","$window","$scope",function(f,g,h){var i=!1,j="submit_field";h.forms={},h.ispreview&&b.restartClock();var k=h.myform.visible_form_fields.filter(function(a){return"statement"!==a.fieldType}).length,l=c("formValidity")(h.myform);h.translateAdvancementData={done:l,total:k,answers_not_completed:k-l},h.reloadForm=function(){h.myform.submitted=!1,h.myform.form_fields=_.chain(h.myform.visible_form_fields).map(function(a){return a.fieldValue="",a}).value(),h.loading=!1,h.error="",h.selected={_id:"",index:0},h.setActiveField(h.myform.visible_form_fields[0]._id,0,!1),b.restartClock()};var m=function(a){var b=a.logicJump;if(b.enabled&&b.expressionString&&b.valueB&&a.fieldValue){var c,d,e=jsep(b.expressionString);if("field"===e.left.name?(c=a.fieldValue,d=b.valueB):(c=b.valueB,d=a.fieldValue),"number"===a.fieldType||"scale"===a.fieldType||"rating"===a.fieldType)switch(e.operator){case"==":return parseInt(c)===parseInt(d);case"!==":return parseInt(c)!==parseInt(d);case">":return parseInt(c)>parseInt(d);case">=":return parseInt(c)>parseInt(d);case"<":return parseInt(c)-1;case"!contains":return!(c.indexOf(d)>-1);case"begins":return c.startsWith(d);case"!begins":return!c.startsWith(d);case"ends":return c.endsWith(d);case"!ends":return c.endsWith(d);default:return!1}}},n=function(){if(null===h.selected)throw console.error("current active field is null"),new Error("current active field is null");return h.selected._id===j?h.myform.form_fields.length-1:h.selected.index};h.isActiveField=function(a){return h.selected._id===a._id},h.setActiveField=d.setActiveField=function(a,b,d){if(null!==h.selected&&(a||null!==b)){if(a){if(null===b){b=h.myform.visible_form_fields.length;for(var e=0;e .field-directive:nth-of-type("+String(h.myform.visible_form_fields.length-1)+")"),m=$(l).height(),n=k-g-1.2*m,o=.9;h.selected.index===h.myform.visible_form_fields.length?bn?(a=h.selected.index+1,h.setActiveField(j,a,!1)):ef*o&&(a=h.selected.index-1,h.setActiveField(null,a,!1))}h.$apply()},d.nextField=h.nextField=function(){if(h.selected&&h.selected.index>-1)if(h.selected._id!==j){var a=h.myform.visible_form_fields[h.selected.index];a.logicJump&&a.logicJump.jumpTo&&m(a)?h.setActiveField(a.logicJump.jumpTo,null,!0):h.selected.index0&&h.setActiveField(null,a,!0)},d.goToInvalid=h.goToInvalid=function(){var a=$(".row.field-directive .ng-invalid.focusOn, .row.field-directive .ng-untouched.focusOn:not(.ng-valid)").first().parents(".row.field-directive").first().attr("data-id");h.setActiveField(a,null,!0)},h.exitStartPage=function(){h.myform.startPage.showStart=!1,h.myform.visible_form_fields.length>0&&(h.selected._id=h.myform.visible_form_fields[0]._id)};var o=function(){var a=new MobileDetect(window.navigator.userAgent),b="other";return a.tablet()?b="tablet":a.mobile()?b="mobile":a.is("bot")||(b="desktop"),{type:b,name:window.navigator.platform}},p=function(){$.ajaxSetup({async:!1});var a=$.getJSON("https://freegeoip.net/json/").responseJSON;return $.ajaxSetup({async:!0}),a&&a.ip||(a={ip:"Adblocker"}),{ipAddr:a.ip,geoLocation:{City:a.city,Country:a.country_name}}};d.submitForm=h.submitForm=function(){if(h.forms.myForm.$invalid)return void h.goToInvalid();var d=b.stopClock();h.loading=!0;var f=_.cloneDeep(h.myform),g=o();f.device=g;var i=p();f.ipAddr=i.ipAddr,f.geoLocation=i.geoLocation,f.timeElapsed=d,f.percentageComplete=c("formValidity")(h.myform)/h.myform.visible_form_fields.length*100,delete f.endPage,delete f.isLive,delete f.provider,delete f.startPage,delete f.visible_form_fields,delete f.analytics,delete f.design,delete f.submissions,delete f.submitted;for(var j=0;j"+c+"",d.childNodes[0].childNodes;default:return c}}function _(a,b){if("srcdoc"==b)return B.HTML;var c=H(a);return"xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b||"ngSrc"==b)?B.RESOURCE_URL:void 0}function aa(a,b,c,e,f){var g=_(a,e);f=m[e]||f;var h=d(c,!0,g,f);if(h){if("multiple"===e&&"select"===H(a))throw Td("selmulti",T(a));b.push({priority:100,compile:function(){return{pre:function(a,b,i){if(b=i.$$observers||(i.$$observers=ja()),v.test(e))throw Td("nodomevents");var j=i[e];j!==c&&(h=j&&d(j,!0,g,f),c=j),h&&(i[e]=h(a),(b[e]||(b[e]=[])).$$inter=!0,(i.$$observers&&i.$$observers[e].$$scope||a).$watch(h,function(a,b){"class"===e&&a!=b?i.$updateClass(a,b):i.$set(e,a)}))}}}})}}function ba(a,c,d){var e,f,g=c[0],h=c.length,i=g.parentNode;if(a)for(e=0,f=a.length;e=b)return a;for(;b--;)8===a[b].nodeType&&Yc.call(a,b,1);return a}function _a(){var a={},b=!1;this.register=function(b,c){ga(b,"controller"),u(b)?k(a,b):a[b]=c},this.allowGlobals=function(){b=!0},this.$get=["$injector","$window",function(e,f){function g(a,b,c,e){if(!a||!u(a.$scope))throw d("$controller")("noscp",e,b);a.$scope[b]=c}return function(d,h,i,j){var l,m,n;if(i=!0===i,j&&w(j)&&(n=j),w(d)){if(j=d.match(Wd),!j)throw Vd("ctrlfmt",d);m=j[1],n=n||j[3],d=a.hasOwnProperty(m)?a[m]:ha(h.$scope,m,!0)||(b?ha(f,m,!0):c),fa(d,m,!0)}return i?(i=(ed(d)?d[d.length-1]:d).prototype,l=Object.create(i||null),n&&g(h,n,l,m||d.name),k(function(){var a=e.invoke(d,l,h,m);return a!==l&&(u(a)||z(a))&&(l=a,n&&g(h,n,l,m||d.name)),l},{instance:l,identifier:n})):(l=e.instantiate(d,h,m),n&&g(h,n,l,m||d.name),l)}}]}function ab(){this.$get=["$window",function(a){return Qc(a.document)}]}function bb(){this.$get=["$log",function(a){return function(b,c){a.error.apply(a,arguments)}}]}function cb(a){return u(a)?y(a)?a.toISOString():P(a):a}function db(){this.$get=function(){return function(a){if(!a)return"";var b=[];return g(a,function(a,c){null===a||s(a)||(ed(a)?f(a,function(a,d){b.push(Y(c)+"="+Y(cb(a)))}):b.push(Y(c)+"="+Y(cb(a))))}),b.join("&")}}}function eb(){this.$get=function(){return function(a){function b(a,d,e){null===a||s(a)||(ed(a)?f(a,function(a,c){b(a,d+"["+(u(a)?c:"")+"]")}):u(a)&&!y(a)?g(a,function(a,c){b(a,d+(e?"":"[")+c+(e?"":"]"))}):c.push(Y(d)+"="+Y(cb(a))))}if(!a)return"";var c=[];return b(a,"",!0),c.join("&")}}}function fb(a,b){if(w(a)){var c=a.replace(ae,"").trim();if(c){var d=b("Content-Type");(d=d&&0===d.indexOf(Yd))||(d=(d=c.match($d))&&_d[d[0]].test(c)),d&&(a=Q(c))}}return a}function gb(a){var b,c=ja();return w(a)?f(a.split("\n"),function(a){b=a.indexOf(":");var d=Uc(gd(a.substr(0,b)));a=gd(a.substr(b+1)),d&&(c[d]=c[d]?c[d]+", "+a:a)}):u(a)&&f(a,function(a,b){var d=Uc(b),e=gd(a);d&&(c[d]=c[d]?c[d]+", "+e:e)}),c}function hb(a){var b;return function(c){return b||(b=gb(a)),c?(c=b[Uc(c)],void 0===c&&(c=null),c):b}}function ib(a,b,c,d){return z(d)?d(a,b,c):(f(d,function(d){a=d(a,b,c)}),a)}function jb(){var a=this.defaults={transformResponse:[fb],transformRequest:[function(a){return u(a)&&"[object File]"!==$c.call(a)&&"[object Blob]"!==$c.call(a)&&"[object FormData]"!==$c.call(a)?P(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:K(Zd),put:K(Zd),patch:K(Zd)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},b=!1;this.useApplyAsync=function(a){return t(a)?(b=!!a,this):b};var e=!0;this.useLegacyPromiseExtensions=function(a){return t(a)?(e=!!a,this):e};var g=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",function(h,i,j,l,m,n){function o(b){function g(a){var b=k({},a);return b.data=ib(a.data,a.headers,a.status,i.transformResponse),a=a.status,200<=a&&300>a?b:m.reject(b)}function h(a,b){var c,d={};return f(a,function(a,e){z(a)?(c=a(b),null!=c&&(d[e]=c)):d[e]=a}),d}if(!bd.isObject(b))throw d("$http")("badreq",b);if(!w(b.url))throw d("$http")("badreq",b.url);var i=k({method:"get",transformRequest:a.transformRequest,transformResponse:a.transformResponse,paramSerializer:a.paramSerializer},b);i.headers=function(b){var c,d,e,f=a.headers,g=k({},b.headers),f=k({},f.common,f[Uc(b.method)]);a:for(c in f){d=Uc(c);for(e in g)if(Uc(e)===d)continue a;g[c]=f[c]}return h(g,K(b))}(b),i.method=Wc(i.method),i.paramSerializer=w(i.paramSerializer)?n.get(i.paramSerializer):i.paramSerializer;var j=[function(b){var d=b.headers,e=ib(b.data,hb(d),c,b.transformRequest);return s(e)&&f(d,function(a,b){"content-type"===Uc(b)&&delete d[b]}),s(b.withCredentials)&&!s(a.withCredentials)&&(b.withCredentials=a.withCredentials),p(b,e).then(g,g)},c],l=m.when(i);for(f(v,function(a){(a.request||a.requestError)&&j.unshift(a.request,a.requestError),(a.response||a.responseError)&&j.push(a.response,a.responseError)});j.length;){b=j.shift();var o=j.shift(),l=l.then(b,o)}return e?(l.success=function(a){return fa(a,"fn"),l.then(function(b){a(b.data,b.status,b.headers,i)}),l},l.error=function(a){return fa(a,"fn"),l.then(null,function(b){a(b.data,b.status,b.headers,i)}),l}):(l.success=ce("success"),l.error=ce("error")),l}function p(d,e){function f(a,c,d,e){function f(){g(c,a,d,e)}n&&(200<=a&&300>a?n.put(y,[a,c,gb(d),e]):n.remove(y)),b?l.$applyAsync(f):(f(),l.$$phase||l.$apply())}function g(a,b,c,e){b=-1<=b?b:0,(200<=b&&300>b?v.resolve:v.reject)({data:a,status:b,headers:hb(c),config:d,statusText:e})}function j(a){g(a.data,a.status,K(a.headers()),a.statusText)}function k(){var a=o.pendingRequests.indexOf(d);-1!==a&&o.pendingRequests.splice(a,1)}var n,p,v=m.defer(),w=v.promise,x=d.headers,y=q(d.url,d.paramSerializer(d.params));return o.pendingRequests.push(d),w.then(k,k),!d.cache&&!a.cache||!1===d.cache||"GET"!==d.method&&"JSONP"!==d.method||(n=u(d.cache)?d.cache:u(a.cache)?a.cache:r),n&&(p=n.get(y),t(p)?p&&z(p.then)?p.then(j,j):ed(p)?g(p[1],p[0],K(p[2]),p[3]):g(p,200,{},"OK"):n.put(y,w)),s(p)&&((p=gc(d.url)?i()[d.xsrfCookieName||a.xsrfCookieName]:c)&&(x[d.xsrfHeaderName||a.xsrfHeaderName]=p),h(d.method,y,e,f,x,d.timeout,d.withCredentials,d.responseType)),w}function q(a,b){return 0=h&&(p.resolve(n),m(q.$$intervalId),delete f[q.$$intervalId]),o||a.$apply()},g),f[q.$$intervalId]=p,q}var f={};return e.cancel=function(a){return!!(a&&a.$$intervalId in f)&&(f[a.$$intervalId].reject("canceled"),b.clearInterval(a.$$intervalId),delete f[a.$$intervalId],!0)},e}]}function pb(a){a=a.split("/");for(var b=a.length;b--;)a[b]=X(a[b]);return a.join("/")}function qb(a,b){var c=fc(a);b.$$protocol=c.protocol,b.$$host=c.hostname,b.$$port=m(c.port)||fe[c.protocol]||null}function rb(a,b){var c="/"!==a.charAt(0);c&&(a="/"+a);var d=fc(a);b.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname),b.$$search=V(d.search),b.$$hash=decodeURIComponent(d.hash),b.$$path&&"/"!=b.$$path.charAt(0)&&(b.$$path="/"+b.$$path)}function sb(a,b){if(0===b.indexOf(a))return b.substr(a.length)}function tb(a){var b=a.indexOf("#");return-1==b?a:a.substr(0,b)}function ub(a){return a.replace(/(#.+)|#$/,"$1")}function vb(a,b,c){this.$$html5=!0,c=c||"",qb(a,this),this.$$parse=function(a){var c=sb(b,a);if(!w(c))throw ge("ipthprfx",a,b);rb(c,this),this.$$path||(this.$$path="/"),this.$$compose()},this.$$compose=function(){var a=W(this.$$search),c=this.$$hash?"#"+X(this.$$hash):"";this.$$url=pb(this.$$path)+(a?"?"+a:"")+c,this.$$absUrl=b+this.$$url.substr(1)},this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;return t(f=sb(a,d))?(g=f,g=t(f=sb(c,f))?b+(sb("/",f)||f):a+g):t(f=sb(b,d))?g=b+f:b==d+"/"&&(g=b),g&&this.$$parse(g),!!g}}function wb(a,b,c){qb(a,this),this.$$parse=function(d){var e,f=sb(a,d)||sb(b,d);s(f)||"#"!==f.charAt(0)?this.$$html5?e=f:(e="",s(f)&&(a=d,this.replace())):(e=sb(c,f),s(e)&&(e=f)),rb(e,this),d=this.$$path;var f=a,g=/^\/[A-Z]:(\/.*)/;0===e.indexOf(f)&&(e=e.replace(f,"")),g.exec(e)||(d=(e=g.exec(d))?e[1]:d),this.$$path=d,this.$$compose()},this.$$compose=function(){var b=W(this.$$search),d=this.$$hash?"#"+X(this.$$hash):"";this.$$url=pb(this.$$path)+(b?"?"+b:"")+d,this.$$absUrl=a+(this.$$url?c+this.$$url:"")},this.$$parseLinkUrl=function(b,c){return tb(a)==tb(b)&&(this.$$parse(b),!0)}}function xb(a,b,c){this.$$html5=!0,wb.apply(this,arguments),this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;return a==tb(d)?f=d:(g=sb(b,d))?f=a+c+g:b===d+"/"&&(f=b),f&&this.$$parse(f),!!f},this.$$compose=function(){var b=W(this.$$search),d=this.$$hash?"#"+X(this.$$hash):"";this.$$url=pb(this.$$path)+(b?"?"+b:"")+d,this.$$absUrl=a+c+this.$$url}}function yb(a){return function(){return this[a]}}function zb(a,b){return function(c){return s(c)?this[a]:(this[a]=b(c),this.$$compose(),this)}}function Ab(){var a="",b={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(b){return t(b)?(a=b,this):a},this.html5Mode=function(a){return D(a)?(b.enabled=a,this):u(a)?(D(a.enabled)&&(b.enabled=a.enabled),D(a.requireBase)&&(b.requireBase=a.requireBase),D(a.rewriteLinks)&&(b.rewriteLinks=a.rewriteLinks),this):b},this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=j.url(),f=j.$$state;try{d.url(a,b,c),j.$$state=d.state()}catch(g){throw j.url(e),j.$$state=f,g}}function i(a,b){c.$broadcast("$locationChangeSuccess",j.absUrl(),a,j.$$state,b)}var j,k;k=d.baseHref();var l,m=d.url();if(b.enabled){if(!k&&b.requireBase)throw ge("nobase");l=m.substring(0,m.indexOf("/",m.indexOf("//")+2))+(k||"/"),k=e.history?vb:xb}else l=tb(m),k=wb;var n=l.substr(0,tb(l).lastIndexOf("/")+1);j=new k(l,n,"#"+a),j.$$parseLinkUrl(m,m),j.$$state=d.state();var o=/^\s*(javascript|mailto):/i;f.on("click",function(a){if(b.rewriteLinks&&!a.ctrlKey&&!a.metaKey&&!a.shiftKey&&2!=a.which&&2!=a.button){for(var e=Qc(a.target);"a"!==H(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),i=e.attr("href")||e.attr("xlink:href");u(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=fc(h.animVal).href),o.test(h)||!h||e.attr("target")||a.isDefaultPrevented()||!j.$$parseLinkUrl(h,i)||(a.preventDefault(),j.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}}),ub(j.absUrl())!=ub(m)&&d.url(j.absUrl(),!0);var p=!0;return d.onUrlChange(function(a,b){s(sb(n,a))?g.location.href=a:(c.$evalAsync(function(){var d,e=j.absUrl(),f=j.$$state;a=ub(a),j.$$parse(a),j.$$state=b,d=c.$broadcast("$locationChangeStart",a,e,b,f).defaultPrevented,j.absUrl()===a&&(d?(j.$$parse(e),j.$$state=f,h(e,!1,f)):(p=!1,i(e,f)))}),c.$$phase||c.$digest())}),c.$watch(function(){var a=ub(d.url()),b=ub(j.absUrl()),f=d.state(),g=j.$$replace,k=a!==b||j.$$html5&&e.history&&f!==j.$$state;(p||k)&&(p=!1,c.$evalAsync(function(){var b=j.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,j.$$state,f).defaultPrevented;j.absUrl()===b&&(d?(j.$$parse(a),j.$$state=f):(k&&h(b,g,f===j.$$state?null:j.$$state),i(a,f)))})),j.$$replace=!1}),j}]}function Bb(){var a=!0,b=this;this.debugEnabled=function(b){return t(b)?(a=b,this):a},this.$get=["$window",function(c){function d(a){return a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line)),a}function e(a){var b=c.console||{},e=b[a]||b.log||o;a=!1;try{a=!!e.apply}catch(g){}return a?function(){var a=[];return f(arguments,function(b){a.push(d(b))}),e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){a&&c.apply(b,arguments)}}()}}]}function Cb(a,b){if("__defineGetter__"===a||"__defineSetter__"===a||"__lookupGetter__"===a||"__lookupSetter__"===a||"__proto__"===a)throw ie("isecfld",b);return a}function Db(a,b){if(a+="",!w(a))throw ie("iseccst",b);return a}function Eb(a,b){if(a){if(a.constructor===a)throw ie("isecfn",b);if(a.window===a)throw ie("isecwindow",b);if(a.children&&(a.nodeName||a.prop&&a.attr&&a.find))throw ie("isecdom",b);if(a===Object)throw ie("isecobj",b)}return a}function Fb(a,b){if(a){if(a.constructor===a)throw ie("isecfn",b);if(a===je||a===ke||a===le)throw ie("isecff",b)}}function Gb(a,b){if(a&&(a===(0).constructor||a===(!1).constructor||a==="".constructor||a==={}.constructor||a===[].constructor||a===Function.constructor))throw ie("isecaf",b)}function Hb(a,b){return"undefined"!=typeof a?a:b}function Ib(a,b){return"undefined"==typeof a?b:"undefined"==typeof b?a:a+b}function Jb(a,b){var c,d;switch(a.type){case pe.Program:c=!0,f(a.body,function(a){Jb(a.expression,b),c=c&&a.expression.constant}),a.constant=c;break;case pe.Literal:a.constant=!0,a.toWatch=[];break;case pe.UnaryExpression:Jb(a.argument,b),a.constant=a.argument.constant,a.toWatch=a.argument.toWatch;break;case pe.BinaryExpression:Jb(a.left,b),Jb(a.right,b),a.constant=a.left.constant&&a.right.constant,a.toWatch=a.left.toWatch.concat(a.right.toWatch);break;case pe.LogicalExpression:Jb(a.left,b),Jb(a.right,b),a.constant=a.left.constant&&a.right.constant,a.toWatch=a.constant?[]:[a];break;case pe.ConditionalExpression:Jb(a.test,b),Jb(a.alternate,b),Jb(a.consequent,b),a.constant=a.test.constant&&a.alternate.constant&&a.consequent.constant,a.toWatch=a.constant?[]:[a];break;case pe.Identifier:a.constant=!1,a.toWatch=[a];break;case pe.MemberExpression:Jb(a.object,b),a.computed&&Jb(a.property,b),a.constant=a.object.constant&&(!a.computed||a.property.constant),a.toWatch=[a];break;case pe.CallExpression:c=!!a.filter&&!b(a.callee.name).$stateful,d=[],f(a.arguments,function(a){Jb(a,b),c=c&&a.constant,a.constant||d.push.apply(d,a.toWatch)}),a.constant=c,a.toWatch=a.filter&&!b(a.callee.name).$stateful?d:[a];break;case pe.AssignmentExpression:Jb(a.left,b),Jb(a.right,b),a.constant=a.left.constant&&a.right.constant,a.toWatch=[a];break;case pe.ArrayExpression:c=!0,d=[],f(a.elements,function(a){Jb(a,b),c=c&&a.constant,a.constant||d.push.apply(d,a.toWatch)}),a.constant=c,a.toWatch=d;break;case pe.ObjectExpression:c=!0,d=[],f(a.properties,function(a){Jb(a.value,b),c=c&&a.value.constant,a.value.constant||d.push.apply(d,a.value.toWatch)}),a.constant=c,a.toWatch=d;break;case pe.ThisExpression:a.constant=!1,a.toWatch=[]}}function Kb(a){if(1==a.length){a=a[0].expression;var b=a.toWatch;return 1!==b.length?b:b[0]!==a?b:c}}function Lb(a){return a.type===pe.Identifier||a.type===pe.MemberExpression}function Mb(a){if(1===a.body.length&&Lb(a.body[0].expression))return{type:pe.AssignmentExpression,left:a.body[0].expression,right:{type:pe.NGValueParameter},operator:"="}}function Nb(a){return 0===a.body.length||1===a.body.length&&(a.body[0].expression.type===pe.Literal||a.body[0].expression.type===pe.ArrayExpression||a.body[0].expression.type===pe.ObjectExpression)}function Ob(a,b){this.astBuilder=a,this.$filter=b}function Pb(a,b){this.astBuilder=a,this.$filter=b}function Qb(a){return"constructor"==a}function Rb(a){return z(a.valueOf)?a.valueOf():re.call(a)}function Sb(){var a=ja(),b=ja();this.$get=["$filter",function(d){function e(c,e,f){var h,n,s;switch(f=f||r,typeof c){case"string":s=c=c.trim();var t=f?b:a;if(h=t[s],!h){":"===c.charAt(0)&&":"===c.charAt(1)&&(n=!0,c=c.substring(2)),h=f?q:p;var u=new oe(h);h=new qe(u,d,h).parse(c),h.constant?h.$$watchDelegate=l:n?h.$$watchDelegate=h.literal?k:j:h.inputs&&(h.$$watchDelegate=i),f&&(h=g(h)),t[s]=h}return m(h,e);case"function":return m(c,e);default:return m(o,e)}}function g(a){function b(b,c,d,e){var f=r;r=!0;try{return a(b,c,d,e)}finally{r=f}}if(!a)return a;b.$$watchDelegate=a.$$watchDelegate,b.assign=g(a.assign),b.constant=a.constant,b.literal=a.literal;for(var c=0;a.inputs&&c=this.promise.$$state.status&&d&&d.length&&a(function(){for(var a,e,f=0,g=d.length;fa)for(b in k++,f)Vc.call(d,b)||(p--,delete f[b])}else f!==d&&(f=d,k++);return k}}c.$stateful=!0;var d,f,g,h=this,i=1s&&(q=4-s,u[q]||(u[q]=[]),u[q].push({msg:z(a.exp)?"fn: "+(a.exp.name||a.exp.toString()):a.exp,newVal:d,oldVal:e}))}catch(B){i(B)}if(!(l=o.$$watchersCount&&o.$$childHead||o!==this&&o.$$nextSibling))for(;o!==this&&!(l=o.$$nextSibling);)o=o.$parent}while(o=l);if((n||y.length)&&!s--)throw x.$$phase=null,c("infdig",b,u)}while(n||y.length);for(x.$$phase=null;A.length;)try{A.shift()()}catch(C){i(C)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy"),this.$$destroyed=!0,this===x&&k.$$applicationDestroyed(),q(this,-this.$$watchersCount);for(var b in this.$$listenerCount)r(this,this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling),a&&a.$$childTail==this&&(a.$$childTail=this.$$prevSibling),this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling),this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling),this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=o,this.$on=this.$watch=this.$watchGroup=function(){return o},this.$$listeners={},this.$$nextSibling=null,m(this)}},$eval:function(a,b){return j(a)(this,b)},$evalAsync:function(a,b){x.$$phase||y.length||k.defer(function(){y.length&&x.$digest()}),y.push({scope:this,expression:j(a),locals:b})},$$postDigest:function(a){A.push(a)},$apply:function(a){try{p("$apply");try{return this.$eval(a)}finally{x.$$phase=null}}catch(b){i(b)}finally{try{x.$digest()}catch(c){throw i(c),c}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&B.push(b),a=j(a),w()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]),c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,r(e,1,a))}},$emit:function(a,b){var c,d,e,f=[],g=this,h=!1,j={name:a,targetScope:g,stopPropagation:function(){h=!0},preventDefault:function(){j.defaultPrevented=!0},defaultPrevented:!1},k=M([j],arguments,1);do{for(c=g.$$listeners[a]||f,j.currentScope=g,d=0,e=c.length;dPc)throw se("iequirks");var d=K(te);d.isEnabled=function(){return a},d.trustAs=c.trustAs,d.getTrusted=c.getTrusted,d.valueOf=c.valueOf,a||(d.trustAs=d.getTrusted=function(a,b){return b},d.valueOf=p),d.parseAs=function(a,c){var e=b(c);return e.literal&&e.constant?e:b(c,function(b){return d.getTrusted(a,b)})};var e=d.parseAs,g=d.getTrusted,h=d.trustAs;return f(te,function(a,b){var c=Uc(b);d[ma("parse_as_"+c)]=function(b){return e(a,b)},d[ma("get_trusted_"+c)]=function(b){return g(a,b)},d[ma("trust_as_"+c)]=function(b){return h(a,b)}}),d}]}function bc(){this.$get=["$window","$document",function(a,b){var c,d={},e=m((/android (\d+)/.exec(Uc((a.navigator||{}).userAgent))||[])[1]),f=/Boxee/i.test((a.navigator||{}).userAgent),g=b[0]||{},h=/^(Moz|webkit|ms)(?=[A-Z])/,i=g.body&&g.body.style,j=!1,k=!1;if(i){for(var l in i)if(j=h.exec(l)){c=j[0],c=c.substr(0,1).toUpperCase()+c.substr(1);break}c||(c="WebkitOpacity"in i&&"webkit"),j=!!("transition"in i||c+"Transition"in i),k=!!("animation"in i||c+"Animation"in i),!e||j&&k||(j=w(i.webkitTransition),k=w(i.webkitAnimation))}return{history:!(!a.history||!a.history.pushState||4>e||f),hasEvent:function(a){if("input"===a&&11>=Pc)return!1;if(s(d[a])){var b=g.createElement("div");d[a]="on"+a in b}return d[a]},csp:id(),vendorPrefix:c,transitions:j,animations:k,android:e}}]}function cc(){this.$get=["$templateCache","$http","$q","$sce",function(a,b,c,d){function e(f,g){e.totalPendingRequests++,w(f)&&!s(a.get(f))||(f=d.getTrustedResourceUrl(f));var h=b.defaults&&b.defaults.transformResponse;return ed(h)?h=h.filter(function(a){return a!==fb}):h===fb&&(h=null),b.get(f,{cache:a,transformResponse:h})["finally"](function(){e.totalPendingRequests--}).then(function(b){return a.put(f,b.data),b.data},function(a){if(!g)throw Td("tpload",f,a.status,a.statusText);return c.reject(a)})}return e.totalPendingRequests=0,e}]}function dc(){this.$get=["$rootScope","$browser","$location",function(a,b,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var d=[];return f(a,function(a){var e=bd.element(a).data("$binding");e&&f(e,function(e){c?new RegExp("(^|\\s)"+hd(b)+"(\\s|\\||$)").test(e)&&d.push(a):-1!=e.indexOf(b)&&d.push(a)})}),d},findModels:function(a,b,c){for(var d=["ng-","data-ng-","ng\\:"],e=0;ec&&(c=d),c+=+a.slice(d+1),a=a.substring(0,d)):0>c&&(c=a.length),d=0;a.charAt(d)==ye;d++);if(d==(f=a.length))b=[0],c=1;else{for(f--;a.charAt(f)==ye;)f--;for(c-=d,b=[],e=0;d<=f;d++,e++)b[e]=+a.charAt(d)}return c>we&&(b=b.splice(0,we-1),g=c-1,c=1),{d:b,e:g,i:c}}function sc(a,b,c,d){var e=a.d,f=e.length-a.i;if(b=s(b)?Math.min(Math.max(c,f),d):+b,c=b+a.i,d=e[c],0h;)i.unshift(0),h++;for(0=b.lgSize&&h.unshift(i.splice(-b.lgSize,i.length).join(""));i.length>b.gSize;)h.unshift(i.splice(-b.gSize,i.length).join(""));i.length&&h.unshift(i.join("")),i=h.join(c),f.length&&(i+=d+f.join("")),e&&(i+="e+"+e)}return 0>a&&!g?b.negPre+i+b.negSuf:b.posPre+i+b.posSuf}function uc(a,b,c){var d="";for(0>a&&(d="-",a=-a),a=""+a;a.length-c)&&(e+=c),0===e&&-12==c&&(e=12),uc(e,b,d)}}function wc(a,b){return function(c,d){var e=c["get"+a](),f=Wc(b?"SHORT"+a:a);return d[f][e]}}function xc(a){var b=new Date(a,0,1).getDay();return new Date(a,0,(4>=b?5:12)-b)}function yc(a){return function(b){var c=xc(b.getFullYear());return b=+new Date(b.getFullYear(),b.getMonth(),b.getDate()+(4-b.getDay()))-+c,b=1+Math.round(b/6048e5),uc(b,a)}}function zc(a,b){return 0>=a.getFullYear()?b.ERAS[0]:b.ERAS[1]}function Ac(a){function b(a){var b;if(b=a.match(c)){a=new Date(0);var d=0,e=0,f=b[8]?a.setUTCFullYear:a.setFullYear,g=b[8]?a.setUTCHours:a.setHours;b[9]&&(d=m(b[9]+b[10]),e=m(b[9]+b[11])),f.call(a,m(b[1]),m(b[2])-1,m(b[3])),d=m(b[4]||0)-d,e=m(b[5]||0)-e,f=m(b[6]||0),b=Math.round(1e3*parseFloat("0."+(b[7]||0))),g.call(a,d,e,f,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,d,e){var g,h,i="",j=[];if(d=d||"mediumDate",d=a.DATETIME_FORMATS[d]||d,w(c)&&(c=Be.test(c)?m(c):b(c)),x(c)&&(c=new Date(c)),!y(c)||!isFinite(c.getTime()))return c;for(;d;)(h=Ae.exec(d))?(j=M(j,h,1),d=j.pop()):(j.push(d),d=null);var k=c.getTimezoneOffset();return e&&(k=R(e,k),c=S(c,e,!0)),f(j,function(b){g=ze[b],i+=g?g(c,a.DATETIME_FORMATS,k):"''"===b?"'":b.replace(/(^'|'$)/g,"").replace(/''/g,"'")}),i}}function Bc(){return function(a,b){return s(b)&&(b=2),P(a,b)}}function Cc(){return function(a,b,c){return b=1/0===Math.abs(Number(b))?Number(b):m(b),isNaN(b)?a:(x(a)&&(a=a.toString()),ed(a)||w(a)?(c=!c||isNaN(c)?0:m(c),c=0>c?Math.max(0,a.length+c):c,0<=b?a.slice(c,c+b):0===c?a.slice(b,a.length):a.slice(Math.max(0,c+b),c)):a)}}function Dc(a){function b(b,c){return c=c?-1:1,b.map(function(b){var d=1,e=p;if(z(b))e=b;else if(w(b)&&("+"!=b.charAt(0)&&"-"!=b.charAt(0)||(d="-"==b.charAt(0)?-1:1,b=b.substring(1)),""!==b&&(e=a(b),e.constant)))var f=e(),e=function(a){return a[f]};return{get:e,descending:d*c}})}function c(a){switch(typeof a){case"number":case"boolean":case"string":return!0;default:return!1}}return function(a,d,f){if(!e(a))return a;ed(d)||(d=[d]),0===d.length&&(d=["+"]);var g=b(d,f);return g.push({get:function(){return{}},descending:f?-1:1}),a=Array.prototype.map.call(a,function(a,b){return{value:a,predicateValues:g.map(function(d){var e=d.get(a);return d=typeof e,null===e?(d="string",e="null"):"string"===d?e=e.toLowerCase():"object"===d&&("function"==typeof e.valueOf&&(e=e.valueOf(),c(e))||r(e)&&(e=e.toString(),c(e))||(e=b)),{value:e,type:d}})}}),a.sort(function(a,b){for(var c=0,d=0,e=g.length;db||37<=b&&40>=b||k(a,this,this.value)}),e.hasEvent("paste")&&b.on("paste cut",k)}b.on("change",j),Te[g]&&d.$$hasNativeValidators&&g===c.type&&b.on("keydown wheel mousedown",function(a){if(!i){var b=this.validity,c=b.badInput,d=b.typeMismatch;i=f.defer(function(){i=null,b.badInput===c&&b.typeMismatch===d||j(a)})}}),d.$render=function(){var a=d.$isEmpty(d.$viewValue)?"":d.$viewValue;b.val()!==a&&b.val(a)}}function Ic(a,b){return function(c,d){var e,g;if(y(c))return c;if(w(c)){if('"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1)),Ke.test(c))return new Date(c);if(a.lastIndex=0,e=a.exec(c))return e.shift(),g=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1e3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},f(e,function(a,c){c=q},h.$observe("min",function(a){q=n(a),i.$validate()})}if(t(h.max)||h.ngMax){var r;i.$validators.max=function(a){return!m(a)||s(r)||d(a)<=r},h.$observe("max",function(a){r=n(a),i.$validate()})}}}function Kc(a,b,d,e){(e.$$hasNativeValidators=u(b[0].validity))&&e.$parsers.push(function(a){var d=b.prop("validity")||{};return d.badInput&&!d.typeMismatch?c:a})}function Lc(a,b,c,d,e){if(t(d)){if(a=a(d),!a.constant)throw sf("constexpr",c,d);return a(b)}return e}function Mc(a,b){return a="ngClass"+a,["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d(?:<\/\1>|)$/,xd=/<|&#?\w+;/,yd=/<([\w:-]+)/,zd=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,Ad={option:[1,'"],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};Ad.optgroup=Ad.option,Ad.tbody=Ad.tfoot=Ad.colgroup=Ad.caption=Ad.thead,Ad.th=Ad.td;var Bd=Node.prototype.contains||function(a){return!!(16&this.compareDocumentPosition(a))},Cd=qa.prototype={ready:function(c){function d(){e||(e=!0,c())}var e=!1;"complete"===b.readyState?setTimeout(d):(this.on("DOMContentLoaded",d),qa(a).on("load",d))},toString:function(){var a=[];return f(this,function(b){a.push(""+b)}),"["+a.join(", ")+"]"},eq:function(a){return Qc(0<=a?this[a]:this[this.length+a])},length:0,push:Zc,sort:[].sort,splice:[].splice},Dd={};f("multiple selected checked disabled readOnly required open".split(" "),function(a){Dd[Uc(a)]=a});var Ed={};f("input select option textarea button form details".split(" "),function(a){Ed[a]=!0});var Fd={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};f({data:wa,removeData:ua,hasData:function(a){for(var b in qd[a.ng339])return!0;return!1}},function(a,b){qa[b]=a}),f({data:wa,inheritedData:Ca,scope:function(a){return Qc.data(a,"$scope")||Ca(a.parentNode||a,["$isolateScope","$scope"])},isolateScope:function(a){return Qc.data(a,"$isolateScope")||Qc.data(a,"$isolateScopeNoTemplate")},controller:Ba,injector:function(a){return Ca(a,"$injector")},removeAttr:function(a,b){a.removeAttribute(b)},hasClass:xa,css:function(a,b,c){return b=ma(b),t(c)?void(a.style[b]=c):a.style[b]},attr:function(a,b,d){var e=a.nodeType;if(e!==od&&2!==e&&8!==e)if(e=Uc(b),Dd[e]){if(!t(d))return a[b]||(a.attributes.getNamedItem(b)||o).specified?e:c;d?(a[b]=!0,a.setAttribute(b,e)):(a[b]=!1,a.removeAttribute(e))}else if(t(d))a.setAttribute(b,d);else if(a.getAttribute)return a=a.getAttribute(b,2),null===a?c:a},prop:function(a,b,c){return t(c)?void(a[b]=c):a[b]},text:function(){function a(a,b){if(s(b)){var c=a.nodeType;return 1===c||c===od?a.textContent:""}a.textContent=b}return a.$dv="",a}(),val:function(a,b){if(s(b)){if(a.multiple&&"select"===H(a)){var c=[];return f(a.options,function(a){a.selected&&c.push(a.value||a.text)}),0===c.length?null:c}return a.value}a.value=b},html:function(a,b){return s(b)?a.innerHTML:(sa(a,!0),void(a.innerHTML=b))},empty:Da},function(a,b){qa.prototype[b]=function(b,c){var d,e,f=this.length;if(a!==Da&&s(2==a.length&&a!==xa&&a!==Ba?b:c)){if(u(b)){for(d=0;d <= >= && || ! = |".split(" "),function(a){me[a]=!0});var ne={n:"\n",f:"\f",r:"\r",t:"\t",v:"\x0B","'":"'",'"':'"'},oe=function(a){this.options=a};oe.prototype={constructor:oe,lex:function(a){for(this.text=a,this.index=0,this.tokens=[];this.index=a&&"string"==typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\x0B"===a||" "===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,b,c){throw c=c||this.index,b=t(b)?"s "+b+"-"+this.index+" ["+this.text.substring(b,c)+"]":" "+c,ie("lexerr",a,b,this.text)},readNumber:function(){for(var a="",b=this.index;this.index","<=",">=");)b={type:pe.BinaryExpression,operator:a.text,left:b,right:this.additive()};return b},additive:function(){for(var a,b=this.multiplicative();a=this.expect("+","-");)b={type:pe.BinaryExpression,operator:a.text,left:b,right:this.multiplicative()};return b},multiplicative:function(){for(var a,b=this.unary();a=this.expect("*","/","%");)b={type:pe.BinaryExpression,operator:a.text,left:b,right:this.unary()};return b},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:pe.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.constants.hasOwnProperty(this.peek().text)?a=J(this.constants[this.consume().text]):this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var b;b=this.expect("(","[",".");)"("===b.text?(a={type:pe.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")):"["===b.text?(a={type:pe.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===b.text?a={type:pe.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var b={type:pe.CallExpression,callee:this.identifier(),arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return b},parseArguments:function(){var a=[];if(")"!==this.peekToken().text)do a.push(this.expression());while(this.expect(","));return a},identifier:function(){var a=this.consume();return a.identifier||this.throwError("is not a valid identifier",a),{type:pe.Identifier,name:a.text}},constant:function(){return{type:pe.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text)do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","));return this.consume("]"),{type:pe.ArrayExpression,elements:a}},object:function(){var a,b=[];if("}"!==this.peekToken().text)do{if(this.peek("}"))break;a={type:pe.Property,kind:"init"},this.peek().constant?a.key=this.constant():this.peek().identifier?a.key=this.identifier():this.throwError("invalid key",this.peek()),this.consume(":"),a.value=this.expression(),b.push(a)}while(this.expect(","));return this.consume("}"),{type:pe.ObjectExpression,properties:b}},throwError:function(a,b){throw ie("syntax",b.text,a,b.index+1,this.text,this.text.substring(b.index))},consume:function(a){if(0===this.tokens.length)throw ie("ueoe",this.text);var b=this.expect(a);return b||this.throwError("is unexpected, expecting ["+a+"]",this.peek()),b},peekToken:function(){if(0===this.tokens.length)throw ie("ueoe",this.text);return this.tokens[0]},peek:function(a,b,c,d){return this.peekAhead(0,a,b,c,d)},peekAhead:function(a,b,c,d,e){if(this.tokens.length>a){a=this.tokens[a];var f=a.text;if(f===b||f===c||f===d||f===e||!(b||c||d||e))return a}return!1},expect:function(a,b,c,d){return!!(a=this.peek(a,b,c,d))&&(this.tokens.shift(),a)},constants:{"true":{type:pe.Literal,value:!0},"false":{type:pe.Literal,value:!1},"null":{type:pe.Literal,value:null},undefined:{type:pe.Literal,value:c},"this":{type:pe.ThisExpression}}},Ob.prototype={compile:function(a,b){var d=this,e=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:b,fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]},Jb(e,d.$filter);var g,h="";return this.stage="assign",(g=Mb(e))&&(this.state.computing="assign",h=this.nextId(),this.recurse(g,h),this.return_(h),h="fn.assign="+this.generateFunction("assign","s,v,l")),g=Kb(e.body),d.stage="inputs",f(g,function(a,b){var c="fn"+b;d.state[c]={vars:[],body:[],own:{}},d.state.computing=c;var e=d.nextId();d.recurse(a,e),d.return_(e),d.state.inputs.push(c),a.watchId=b}),this.state.computing="fn",this.stage="main",this.recurse(e),h='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+h+this.watchFns()+"return fn;",h=new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","getStringValue","ensureSafeAssignContext","ifDefined","plus","text",h)(this.$filter,Cb,Eb,Fb,Db,Gb,Hb,Ib,a),this.state=this.stage=c,h.literal=Nb(e),h.constant=e.constant,h},USE:"use",STRICT:"strict",watchFns:function(){var a=[],b=this.state.inputs,c=this;return f(b,function(b){a.push("var "+b+"="+c.generateFunction(b,"s"))}),b.length&&a.push("fn.inputs=["+b.join(",")+"];"),a.join("")},generateFunction:function(a,b){return"function("+b+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],b=this;return f(this.state.filters,function(c,d){a.push(c+"=$filter("+b.escape(d)+")")}),a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,b,d,e,g,h){var i,j,k,l,m=this;if(e=e||o,!h&&t(a.watchId))b=b||this.nextId(),this.if_("i",this.lazyAssign(b,this.computedMember("i",a.watchId)),this.lazyRecurse(a,b,d,e,g,!0));else switch(a.type){case pe.Program:f(a.body,function(b,d){m.recurse(b.expression,c,c,function(a){j=a}),d!==a.body.length-1?m.current().body.push(j,";"):m.return_(j)});break;case pe.Literal:l=this.escape(a.value),this.assign(b,l),e(l);break;case pe.UnaryExpression:this.recurse(a.argument,c,c,function(a){j=a}),l=a.operator+"("+this.ifDefined(j,0)+")",this.assign(b,l),e(l);break;case pe.BinaryExpression:this.recurse(a.left,c,c,function(a){i=a}),this.recurse(a.right,c,c,function(a){j=a}),l="+"===a.operator?this.plus(i,j):"-"===a.operator?this.ifDefined(i,0)+a.operator+this.ifDefined(j,0):"("+i+")"+a.operator+"("+j+")",this.assign(b,l),e(l);break;case pe.LogicalExpression:b=b||this.nextId(),m.recurse(a.left,b),m.if_("&&"===a.operator?b:m.not(b),m.lazyRecurse(a.right,b)),e(b);break;case pe.ConditionalExpression:b=b||this.nextId(),m.recurse(a.test,b),m.if_(b,m.lazyRecurse(a.alternate,b),m.lazyRecurse(a.consequent,b)),e(b);break;case pe.Identifier:b=b||this.nextId(),d&&(d.context="inputs"===m.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name),Cb(a.name),m.if_("inputs"===m.stage||m.not(m.getHasOwnProperty("l",a.name)),function(){m.if_("inputs"===m.stage||"s",function(){g&&1!==g&&m.if_(m.not(m.nonComputedMember("s",a.name)),m.lazyAssign(m.nonComputedMember("s",a.name),"{}")),m.assign(b,m.nonComputedMember("s",a.name))})},b&&m.lazyAssign(b,m.nonComputedMember("l",a.name))),(m.state.expensiveChecks||Qb(a.name))&&m.addEnsureSafeObject(b),e(b);break;case pe.MemberExpression:i=d&&(d.context=this.nextId())||this.nextId(),b=b||this.nextId(),m.recurse(a.object,i,c,function(){m.if_(m.notNull(i),function(){g&&1!==g&&m.addEnsureSafeAssignContext(i),a.computed?(j=m.nextId(),m.recurse(a.property,j),m.getStringValue(j),m.addEnsureSafeMemberName(j),g&&1!==g&&m.if_(m.not(m.computedMember(i,j)),m.lazyAssign(m.computedMember(i,j),"{}")),l=m.ensureSafeObject(m.computedMember(i,j)),m.assign(b,l),d&&(d.computed=!0,d.name=j)):(Cb(a.property.name),g&&1!==g&&m.if_(m.not(m.nonComputedMember(i,a.property.name)),m.lazyAssign(m.nonComputedMember(i,a.property.name),"{}")),l=m.nonComputedMember(i,a.property.name),(m.state.expensiveChecks||Qb(a.property.name))&&(l=m.ensureSafeObject(l)),m.assign(b,l),d&&(d.computed=!1,d.name=a.property.name))},function(){m.assign(b,"undefined")}),e(b)},!!g);break;case pe.CallExpression:b=b||this.nextId(),a.filter?(j=m.filter(a.callee.name),k=[],f(a.arguments,function(a){var b=m.nextId();m.recurse(a,b),k.push(b)}),l=j+"("+k.join(",")+")",m.assign(b,l),e(b)):(j=m.nextId(),i={},k=[],m.recurse(a.callee,j,i,function(){m.if_(m.notNull(j),function(){m.addEnsureSafeFunction(j),f(a.arguments,function(a){m.recurse(a,m.nextId(),c,function(a){k.push(m.ensureSafeObject(a))})}),i.name?(m.state.expensiveChecks||m.addEnsureSafeObject(i.context),l=m.member(i.context,i.name,i.computed)+"("+k.join(",")+")"):l=j+"("+k.join(",")+")",l=m.ensureSafeObject(l),m.assign(b,l)},function(){m.assign(b,"undefined")}),e(b)}));break;case pe.AssignmentExpression:if(j=this.nextId(),i={},!Lb(a.left))throw ie("lval");this.recurse(a.left,c,i,function(){m.if_(m.notNull(i.context),function(){m.recurse(a.right,j),m.addEnsureSafeObject(m.member(i.context,i.name,i.computed)),m.addEnsureSafeAssignContext(i.context),l=m.member(i.context,i.name,i.computed)+a.operator+j,m.assign(b,l),e(b||l)})},1);break;case pe.ArrayExpression:k=[],f(a.elements,function(a){m.recurse(a,m.nextId(),c,function(a){k.push(a)})}),l="["+k.join(",")+"]",this.assign(b,l),e(l);break;case pe.ObjectExpression:k=[],f(a.properties,function(a){m.recurse(a.value,m.nextId(),c,function(b){k.push(m.escape(a.key.type===pe.Identifier?a.key.name:""+a.key.value)+":"+b)})}),l="{"+k.join(",")+"}",this.assign(b,l),e(l);break;case pe.ThisExpression:this.assign(b,"s"),e("s");break;case pe.NGValueParameter:this.assign(b,"v"),e("v")}},getHasOwnProperty:function(a,b){var c=a+"."+b,d=this.current().own;return d.hasOwnProperty(c)||(d[c]=this.nextId(!1,a+"&&("+this.escape(b)+" in "+a+")")),d[c]},assign:function(a,b){if(a)return this.current().body.push(a,"=",b,";"),a},filter:function(a){return this.state.filters.hasOwnProperty(a)||(this.state.filters[a]=this.nextId(!0)),this.state.filters[a]},ifDefined:function(a,b){return"ifDefined("+a+","+this.escape(b)+")"},plus:function(a,b){return"plus("+a+","+b+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,b,c){if(!0===a)b();else{var d=this.current().body;d.push("if(",a,"){"),b(),d.push("}"),c&&(d.push("else{"),c(),d.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,b){return a+"."+b},computedMember:function(a,b){return a+"["+b+"]"},member:function(a,b,c){return c?this.computedMember(a,b):this.nonComputedMember(a,b)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a),";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},addEnsureSafeAssignContext:function(a){this.current().body.push(this.ensureSafeAssignContext(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},getStringValue:function(a){this.assign(a,"getStringValue("+a+",text)")},ensureSafeAssignContext:function(a){return"ensureSafeAssignContext("+a+",text)"},lazyRecurse:function(a,b,c,d,e,f){var g=this;return function(){g.recurse(a,b,c,d,e,f)}},lazyAssign:function(a,b){var c=this;return function(){c.assign(a,b)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(w(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(x(a))return a.toString();if(!0===a)return"true";if(!1===a)return"false";if(null===a)return"null";if("undefined"==typeof a)return"undefined";throw ie("esc")},nextId:function(a,b){var c="v"+this.state.nextId++;return a||this.current().vars.push(c+(b?"="+b:"")),c},current:function(){return this.state[this.state.computing]}},Pb.prototype={compile:function(a,b){var c=this,d=this.astBuilder.ast(a);this.expression=a,this.expensiveChecks=b,Jb(d,c.$filter);var e,g;(e=Mb(d))&&(g=this.recurse(e)),e=Kb(d.body);var h;e&&(h=[],f(e,function(a,b){var d=c.recurse(a);a.input=d,h.push(d),a.watchId=b}));var i=[];return f(d.body,function(a){i.push(c.recurse(a.expression))}),e=0===d.body.length?function(){}:1===d.body.length?i[0]:function(a,b){var c;return f(i,function(d){c=d(a,b)}),c},g&&(e.assign=function(a,b,c){return g(a,c,b)}),h&&(e.inputs=h),e.literal=Nb(d),e.constant=d.constant,e},recurse:function(a,b,d){var e,g,h,i=this;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case pe.Literal:return this.value(a.value,b);case pe.UnaryExpression:return g=this.recurse(a.argument),this["unary"+a.operator](g,b);case pe.BinaryExpression:return e=this.recurse(a.left),g=this.recurse(a.right),this["binary"+a.operator](e,g,b);case pe.LogicalExpression:return e=this.recurse(a.left),g=this.recurse(a.right),this["binary"+a.operator](e,g,b);case pe.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),b);case pe.Identifier:return Cb(a.name,i.expression),i.identifier(a.name,i.expensiveChecks||Qb(a.name),b,d,i.expression);case pe.MemberExpression:return e=this.recurse(a.object,!1,!!d),a.computed||(Cb(a.property.name,i.expression),g=a.property.name),a.computed&&(g=this.recurse(a.property)),a.computed?this.computedMember(e,g,b,d,i.expression):this.nonComputedMember(e,g,i.expensiveChecks,b,d,i.expression);case pe.CallExpression:return h=[],f(a.arguments,function(a){h.push(i.recurse(a))}),a.filter&&(g=this.$filter(a.callee.name)),a.filter||(g=this.recurse(a.callee,!0)),a.filter?function(a,d,e,f){for(var i=[],j=0;j":function(a,b,c){return function(d,e,f,g){return d=a(d,e,f,g)>b(d,e,f,g),c?{value:d}:d}},"binary<=":function(a,b,c){return function(d,e,f,g){return d=a(d,e,f,g)<=b(d,e,f,g),c?{value:d}:d}},"binary>=":function(a,b,c){return function(d,e,f,g){return d=a(d,e,f,g)>=b(d,e,f,g),c?{value:d}:d}},"binary&&":function(a,b,c){return function(d,e,f,g){return d=a(d,e,f,g)&&b(d,e,f,g),c?{value:d}:d}},"binary||":function(a,b,c){return function(d,e,f,g){return d=a(d,e,f,g)||b(d,e,f,g),c?{value:d}:d}},"ternary?:":function(a,b,c,d){return function(e,f,g,h){return e=a(e,f,g,h)?b(e,f,g,h):c(e,f,g,h),d?{value:e}:e}},value:function(a,b){return function(){return b?{context:c,name:c,value:a}:a}},identifier:function(a,b,d,e,f){return function(g,h,i,j){return g=h&&a in h?h:g,e&&1!==e&&g&&!g[a]&&(g[a]={}),h=g?g[a]:c,b&&Eb(h,f),d?{context:g,name:a,value:h}:h}},computedMember:function(a,b,c,d,e){return function(f,g,h,i){var j,k,l=a(f,g,h,i);return null!=l&&(j=b(f,g,h,i),j=Db(j),Cb(j,e),d&&1!==d&&(Gb(l),l&&!l[j]&&(l[j]={})),k=l[j],Eb(k,e)),c?{context:l,name:j,value:k}:k}},nonComputedMember:function(a,b,d,e,f,g){return function(h,i,j,k){return h=a(h,i,j,k),f&&1!==f&&(Gb(h),h&&!h[b]&&(h[b]={})),i=null!=h?h[b]:c,(d||Qb(b))&&Eb(i,g),e?{context:h,name:b,value:i}:i}},inputs:function(a,b){return function(c,d,e,f){return f?f[b]:a(c,d,e)}}};var qe=function(a,b,c){this.lexer=a,this.$filter=b,this.options=c,this.ast=new pe(this.lexer),this.astCompiler=c.csp?new Pb(this.ast,b):new Ob(this.ast,b)};qe.prototype={constructor:qe,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};var re=Object.prototype.valueOf,se=d("$sce"),te={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},Td=d("$compile"),ue=b.createElement("a"),ve=fc(a.location.href);ic.$inject=["$document"],kc.$inject=["$provide"];var we=22,xe=".",ye="0";pc.$inject=["$locale"],qc.$inject=["$locale"];var ze={yyyy:vc("FullYear",4),yy:vc("FullYear",2,0,!0),y:vc("FullYear",1),MMMM:wc("Month"),MMM:wc("Month",!0),MM:vc("Month",2,1),M:vc("Month",1,1),dd:vc("Date",2),d:vc("Date",1),HH:vc("Hours",2),H:vc("Hours",1),hh:vc("Hours",2,-12),h:vc("Hours",1,-12),mm:vc("Minutes",2),m:vc("Minutes",1),ss:vc("Seconds",2),s:vc("Seconds",1),sss:vc("Milliseconds",3),EEEE:wc("Day"),EEE:wc("Day",!0),a:function(a,b){return 12>a.getHours()?b.AMPMS[0]:b.AMPMS[1]},Z:function(a,b,c){return a=-1*c,a=(0<=a?"+":"")+(uc(Math[0=a.getFullYear()?b.ERANAMES[0]:b.ERANAMES[1]}},Ae=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,Be=/^\-?\d+$/;Ac.$inject=["$locale"];var Ce=q(Uc),De=q(Wc);Dc.$inject=["$parse"];var Ee=q({restrict:"E",compile:function(a,b){if(!b.href&&!b.xlinkHref)return function(a,b){if("a"===b[0].nodeName.toLowerCase()){var c="[object SVGAnimatedString]"===$c.call(b.prop("href"))?"xlink:href":"href";b.on("click",function(a){b.attr(c)||a.preventDefault()})}}}}),Fe={};f(Dd,function(a,b){function c(a,c,e){a.$watch(e[d],function(a){e.$set(b,!!a)})}if("multiple"!=a){var d=Ya("ng-"+b),e=c;"checked"===a&&(e=function(a,b,e){e.ngModel!==e[d]&&c(a,b,e)}),Fe[d]=function(){return{restrict:"A",priority:100,link:e}}}}),f(Fd,function(a,b){Fe[b]=function(){return{priority:100,link:function(a,c,d){return"ngPattern"===b&&"/"==d.ngPattern.charAt(0)&&(c=d.ngPattern.match(Tc))?void d.$set("ngPattern",new RegExp(c[1],c[2])):void a.$watch(d[b],function(a){d.$set(b,a)})}}}}),f(["src","srcset","href"],function(a){var b=Ya("ng-"+a);Fe[b]=function(){return{priority:99,link:function(c,d,e){var f=a,g=a;"href"===a&&"[object SVGAnimatedString]"===$c.call(d.prop("href"))&&(g="xlinkHref",e.$attr[g]="xlink:href",f=null),e.$observe(b,function(b){b?(e.$set(g,b),Pc&&f&&d.prop(f,e[g])):"href"===a&&e.$set(g,null)})}}}});var Ge={$addControl:o,$$renameControl:function(a,b){a.$name=b},$removeControl:o,$setValidity:o,$setDirty:o,$setPristine:o,$setSubmitted:o};Fc.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var He=function(a){return["$timeout","$parse",function(b,d){function e(a){return""===a?d('this[""]').assign:d(a).assign||o}return{name:"form",restrict:a?"EAC":"E",require:["form","^^?form"],controller:Fc,compile:function(d,f){d.addClass(pf).addClass(nf);var g=f.name?"name":!(!a||!f.ngForm)&&"ngForm";return{pre:function(a,d,f,h){var i=h[0];if(!("action"in f)){var j=function(b){a.$apply(function(){i.$commitViewValue(),i.$setSubmitted()}),b.preventDefault()};d[0].addEventListener("submit",j,!1),d.on("$destroy",function(){b(function(){d[0].removeEventListener("submit",j,!1)},0,!1)})}(h[1]||i.$$parentForm).$addControl(i);var l=g?e(i.$name):o;g&&(l(a,i),f.$observe(g,function(b){i.$name!==b&&(l(a,c),i.$$parentForm.$$renameControl(i,b),(l=e(i.$name))(a,i))})),d.on("$destroy",function(){i.$$parentForm.$removeControl(i),l(a,c),k(i,Ge)})}}}}}]},Ie=He(),Je=He(!0),Ke=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,Le=/^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:\/?#]+|\[[a-f\d:]+\])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i,Me=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,Ne=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Oe=/^(\d{4})-(\d{2})-(\d{2})$/,Pe=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Qe=/^(\d{4})-W(\d\d)$/,Re=/^(\d{4})-(\d\d)$/,Se=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Te=ja();f(["date","datetime-local","month","time","week"],function(a){Te[a]=!0});var Ue={text:function(a,b,c,d,e,f){Hc(a,b,c,d,e,f),Gc(d)},date:Jc("date",Oe,Ic(Oe,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":Jc("datetimelocal",Pe,Ic(Pe,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:Jc("time",Se,Ic(Se,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:Jc("week",Qe,function(a,b){if(y(a))return a;if(w(a)){Qe.lastIndex=0;var c=Qe.exec(a);if(c){var d=+c[1],e=+c[2],f=c=0,g=0,h=0,i=xc(d),e=7*(e-1);return b&&(c=b.getHours(),f=b.getMinutes(),g=b.getSeconds(),h=b.getMilliseconds()),new Date(d,0,i.getDate()+e,c,f,g,h)}}return NaN},"yyyy-Www"),month:Jc("month",Re,Ic(Re,["yyyy","MM"]),"yyyy-MM"),number:function(a,b,d,e,f,g){if(Kc(a,b,d,e),Hc(a,b,d,e,f,g),e.$$parserName="number",e.$parsers.push(function(a){return e.$isEmpty(a)?null:Ne.test(a)?parseFloat(a):c}),e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!x(a))throw sf("numfmt",a);a=a.toString()}return a}),t(d.min)||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)||s(h)||a>=h},d.$observe("min",function(a){t(a)&&!x(a)&&(a=parseFloat(a,10)),h=x(a)&&!isNaN(a)?a:c,e.$validate()})}if(t(d.max)||d.ngMax){var i;e.$validators.max=function(a){return e.$isEmpty(a)||s(i)||a<=i},d.$observe("max",function(a){t(a)&&!x(a)&&(a=parseFloat(a,10)),i=x(a)&&!isNaN(a)?a:c,e.$validate()})}},url:function(a,b,c,d,e,f){Hc(a,b,c,d,e,f),Gc(d),d.$$parserName="url",d.$validators.url=function(a,b){var c=a||b;return d.$isEmpty(c)||Le.test(c)}},email:function(a,b,c,d,e,f){Hc(a,b,c,d,e,f),Gc(d),d.$$parserName="email",d.$validators.email=function(a,b){var c=a||b;return d.$isEmpty(c)||Me.test(c)}},radio:function(a,b,c,d){s(c.name)&&b.attr("name",++cd),b.on("click",function(a){b[0].checked&&d.$setViewValue(c.value,a&&a.type)}),d.$render=function(){b[0].checked=c.value==d.$viewValue},c.$observe("value",d.$render)},checkbox:function(a,b,c,d,e,f,g,h){var i=Lc(h,a,"ngTrueValue",c.ngTrueValue,!0),j=Lc(h,a,"ngFalseValue",c.ngFalseValue,!1);b.on("click",function(a){d.$setViewValue(b[0].checked,a&&a.type)}),d.$render=function(){b[0].checked=d.$viewValue},d.$isEmpty=function(a){return!1===a},d.$formatters.push(function(a){return L(a,i)}),d.$parsers.push(function(a){return a?i:j})},hidden:o,button:o,submit:o,reset:o,file:o},Ve=["$browser","$sniffer","$filter","$parse",function(a,b,c,d){return{restrict:"E",require:["?ngModel"],link:{pre:function(e,f,g,h){h[0]&&(Ue[Uc(g.type)]||Ue.text)(e,f,g,h[0],b,a,c,d)}}}}],We=/^(true|false|\d+)$/,Xe=function(){return{restrict:"A",priority:100,compile:function(a,b){return We.test(b.ngValue)?function(a,b,c){c.$set("value",a.$eval(c.ngValue))}:function(a,b,c){a.$watch(c.ngValue,function(a){c.$set("value",a)})}}}},Ye=["$compile",function(a){return{restrict:"AC",compile:function(b){return a.$$addBindingClass(b),function(b,c,d){a.$$addBindingInfo(c,d.ngBind),c=c[0],b.$watch(d.ngBind,function(a){c.textContent=s(a)?"":a})}}}}],Ze=["$interpolate","$compile",function(a,b){ -return{compile:function(c){return b.$$addBindingClass(c),function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate)),b.$$addBindingInfo(d,c.expressions),d=d[0],e.$observe("ngBindTemplate",function(a){d.textContent=s(a)?"":a})}}}}],$e=["$sce","$parse","$compile",function(a,b,c){return{restrict:"A",compile:function(d,e){var f=b(e.ngBindHtml),g=b(e.ngBindHtml,function(b){return a.valueOf(b)});return c.$$addBindingClass(d),function(b,d,e){c.$$addBindingInfo(d,e.ngBindHtml),b.$watch(g,function(){var c=f(b);d.html(a.getTrustedHtml(c)||"")})}}}}],_e=q({restrict:"A",require:"ngModel",link:function(a,b,c,d){d.$viewChangeListeners.push(function(){a.$eval(c.ngChange)})}}),af=Mc("",!0),bf=Mc("Odd",0),cf=Mc("Even",1),df=Ec({compile:function(a,b){b.$set("ngCloak",c),a.removeClass("ng-cloak")}}),ef=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],ff={},gf={blur:!0,focus:!0};f("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var b=Ya("ng-"+a);ff[b]=["$parse","$rootScope",function(c,d){return{restrict:"A",compile:function(e,f){var g=c(f[b],null,!0);return function(b,c){c.on(a,function(c){var e=function(){g(b,{$event:c})};gf[a]&&d.$$phase?b.$evalAsync(e):b.$apply(e)})}}}}]});var hf=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,i,j;c.$watch(e.ngIf,function(c){c?i||g(function(c,f){i=f,c[c.length++]=b.createComment(" end ngIf: "+e.ngIf+" "),h={clone:c},a.enter(c,d.parent(),d)}):(j&&(j.remove(),j=null),i&&(i.$destroy(),i=null),h&&(j=ia(h.clone),a.leave(j).then(function(){j=null}),h=null))})}}}],jf=["$templateRequest","$anchorScroll","$animate",function(a,b,c){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:bd.noop,compile:function(d,e){var f=e.ngInclude||e.src,g=e.onload||"",h=e.autoscroll;return function(d,e,i,j,k){var l,m,n,o=0,p=function(){m&&(m.remove(),m=null),l&&(l.$destroy(),l=null),n&&(c.leave(n).then(function(){m=null}),m=n,n=null)};d.$watch(f,function(f){var i=function(){!t(h)||h&&!d.$eval(h)||b()},m=++o;f?(a(f,!0).then(function(a){if(!d.$$destroyed&&m===o){var b=d.$new();j.template=a,a=k(b,function(a){p(),c.enter(a,null,e).then(i)}),l=b,n=a,l.$emit("$includeContentLoaded",f),d.$eval(g)}},function(){d.$$destroyed||m!==o||(p(),d.$emit("$includeContentError",f))}),d.$emit("$includeContentRequested",f)):(p(),j.template=null)})}}}}],kf=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(oa(f.template,b).childNodes)(c,function(a){d.append(a)},{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],lf=Ec({priority:450,compile:function(){return{pre:function(a,b,c){a.$eval(c.ngInit)}}}}),mf=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,b,d,e){var g=b.attr(d.$attr.ngList)||", ",h="false"!==d.ngTrim,i=h?gd(g):g;e.$parsers.push(function(a){if(!s(a)){var b=[];return a&&f(a.split(i),function(a){a&&b.push(h?gd(a):a)}),b}}),e.$formatters.push(function(a){return ed(a)?a.join(g):c}),e.$isEmpty=function(a){return!a||!a.length}}}},nf="ng-valid",of="ng-invalid",pf="ng-pristine",qf="ng-dirty",rf="ng-pending",sf=d("ngModel"),tf=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,b,d,e,g,h,i,j,k,l){this.$modelValue=this.$viewValue=Number.NaN,this.$$rawModelValue=c,this.$validators={},this.$asyncValidators={},this.$parsers=[],this.$formatters=[],this.$viewChangeListeners=[],this.$untouched=!0,this.$touched=!1,this.$pristine=!0,this.$dirty=!1,this.$valid=!0,this.$invalid=!1,this.$error={},this.$$success={},this.$pending=c,this.$name=l(d.name||"",!1)(a),this.$$parentForm=Ge;var m,n=g(d.ngModel),p=n.assign,q=n,r=p,u=null,v=this;this.$$setOptions=function(a){if((v.$options=a)&&a.getterSetter){var b=g(d.ngModel+"()"),c=g(d.ngModel+"($$$p)");q=function(a){var c=n(a);return z(c)&&(c=b(a)),c},r=function(a,b){z(n(a))?c(a,{$$$p:v.$modelValue}):p(a,v.$modelValue)}}else if(!n.assign)throw sf("nonassign",d.ngModel,T(e))},this.$render=o,this.$isEmpty=function(a){return s(a)||""===a||null===a||a!==a};var w=0;Nc({ctrl:this,$element:e,set:function(a,b){a[b]=!0},unset:function(a,b){delete a[b]},$animate:h}),this.$setPristine=function(){v.$dirty=!1,v.$pristine=!0,h.removeClass(e,qf),h.addClass(e,pf)},this.$setDirty=function(){v.$dirty=!0,v.$pristine=!1,h.removeClass(e,pf),h.addClass(e,qf),v.$$parentForm.$setDirty()},this.$setUntouched=function(){v.$touched=!1,v.$untouched=!0,h.setClass(e,"ng-untouched","ng-touched")},this.$setTouched=function(){v.$touched=!0,v.$untouched=!1,h.setClass(e,"ng-touched","ng-untouched")},this.$rollbackViewValue=function(){i.cancel(u),v.$viewValue=v.$$lastCommittedViewValue,v.$render()},this.$validate=function(){if(!x(v.$modelValue)||!isNaN(v.$modelValue)){var a=v.$$rawModelValue,b=v.$valid,d=v.$modelValue,e=v.$options&&v.$options.allowInvalid;v.$$runValidators(a,v.$$lastCommittedViewValue,function(f){e||b===f||(v.$modelValue=f?a:c,v.$modelValue!==d&&v.$$writeModelToScope())})}},this.$$runValidators=function(a,b,d){function e(){var c=!0;return f(v.$validators,function(d,e){var f=d(a,b);c=c&&f,h(e,f)}),!!c||(f(v.$asyncValidators,function(a,b){h(b,null)}),!1)}function g(){var d=[],e=!0;f(v.$asyncValidators,function(f,g){var i=f(a,b);if(!i||!z(i.then))throw sf("nopromise",i);h(g,c),d.push(i.then(function(){h(g,!0)},function(a){e=!1,h(g,!1)}))}),d.length?k.all(d).then(function(){i(e)},o):i(!0)}function h(a,b){j===w&&v.$setValidity(a,b)}function i(a){j===w&&d(a)}w++;var j=w;(function(){var a=v.$$parserName||"parse";return s(m)?(h(a,null),!0):(m||(f(v.$validators,function(a,b){h(b,null)}),f(v.$asyncValidators,function(a,b){h(b,null)})),h(a,m),m)})()&&e()?g():i(!1)},this.$commitViewValue=function(){var a=v.$viewValue;i.cancel(u),(v.$$lastCommittedViewValue!==a||""===a&&v.$$hasNativeValidators)&&(v.$$lastCommittedViewValue=a,v.$pristine&&this.$setDirty(),this.$$parseAndValidate())},this.$$parseAndValidate=function(){var b=v.$$lastCommittedViewValue;if(m=!s(b)||c)for(var d=0;de||d.$isEmpty(b)||b.length<=e}}}}},Tf=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,c,d){if(d){var e=0;c.$observe("minlength",function(a){e=m(a)||0,d.$validate()}),d.$validators.minlength=function(a,b){return d.$isEmpty(b)||b.length>=e}}}}};a.angular.bootstrap?a.console&&console.log("WARNING: Tried to load angular more than once."):(da(),la(bd),bd.module("ngLocale",[],["$provide",function(a){function b(a){a+="";var b=a.indexOf(".");return-1==b?0:a.length-b-1}a.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM","PM"],DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:"January February March April May June July August September October November December".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),STANDALONEMONTH:"January February March April May June July August September October November December".split(" "),WEEKENDRANGE:[5,6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a","short":"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,minFrac:2,minInt:1,negPre:"-¤",negSuf:"",posPre:"¤",posSuf:""}]},id:"en-us",localeID:"en_US",pluralCat:function(a,d){var e=0|a,f=d;return c===f&&(f=Math.min(b(a),3)),Math.pow(10,f),1==e&&0==f?"one":"other"}})}]),Qc(b).ready(function(){$(b,_)}))}(window,document),!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend('');var duScrollDefaultEasing=function(a){return.5>a?Math.pow(2*a,2)/2:1-Math.pow(2*(1-a),2)/2},duScroll=angular.module("duScroll",["duScroll.scrollspy","duScroll.smoothScroll","duScroll.scrollContainer","duScroll.spyContext","duScroll.scrollHelpers"]).value("duScrollDuration",350).value("duScrollSpyWait",100).value("duScrollGreedy",!1).value("duScrollOffset",0).value("duScrollEasing",duScrollDefaultEasing).value("duScrollCancelOnEvents","scroll mousedown mousewheel touchmove keydown").value("duScrollBottomSpy",!1).value("duScrollActiveClass","active");"undefined"!=typeof module&&module&&module.exports&&(module.exports=duScroll),angular.module("duScroll.scrollHelpers",["duScroll.requestAnimation"]).run(["$window","$q","cancelAnimation","requestAnimation","duScrollEasing","duScrollDuration","duScrollOffset","duScrollCancelOnEvents",function(a,b,c,d,e,f,g,h){var i={},j=function(a){return"undefined"!=typeof HTMLDocument&&a instanceof HTMLDocument||a.nodeType&&a.nodeType===a.DOCUMENT_NODE},k=function(a){return"undefined"!=typeof HTMLElement&&a instanceof HTMLElement||a.nodeType&&a.nodeType===a.ELEMENT_NODE},l=function(a){return k(a)||j(a)?a:a[0]};i.duScrollTo=function(b,c,d,e){var f;if(angular.isElement(b)?f=this.duScrollToElement:angular.isDefined(d)&&(f=this.duScrollToAnimated),f)return f.apply(this,arguments);var g=l(this);return j(g)?a.scrollTo(b,c):(g.scrollLeft=b,void(g.scrollTop=c))};var m,n;i.duScrollToAnimated=function(a,f,g,i){g&&!i&&(i=e);var j=this.duScrollLeft(),k=this.duScrollTop(),l=Math.round(a-j),o=Math.round(f-k),p=null,q=0,r=this,s=function(a){(!a||q&&a.which>0)&&(h&&r.unbind(h,s),c(m),n.reject(),m=null)};if(m&&s(),n=b.defer(),0===g||!l&&!o)return 0===g&&r.duScrollTo(a,f),n.resolve(),n.promise;var t=function(a){null===p&&(p=a),q=a-p;var b=q>=g?1:i(q/g);r.scrollTo(j+Math.ceil(l*b),k+Math.ceil(o*b)),1>b?m=d(t):(h&&r.unbind(h,s),m=null,n.resolve())};return r.duScrollTo(j,k),h&&r.bind(h,s),m=d(t),n.promise},i.duScrollToElement=function(a,b,c,d){var e=l(this);(!angular.isNumber(b)||isNaN(b))&&(b=g);var f=this.duScrollTop()+l(a).getBoundingClientRect().top-b;return k(e)&&(f-=e.getBoundingClientRect().top),this.duScrollTo(0,f,c,d)},i.duScrollLeft=function(b,c,d){if(angular.isNumber(b))return this.duScrollTo(b,this.duScrollTop(),c,d);var e=l(this);return j(e)?a.scrollX||document.documentElement.scrollLeft||document.body.scrollLeft:e.scrollLeft},i.duScrollTop=function(b,c,d){if(angular.isNumber(b))return this.duScrollTo(this.duScrollLeft(),b,c,d);var e=l(this);return j(e)?a.scrollY||document.documentElement.scrollTop||document.body.scrollTop:e.scrollTop},i.duScrollToElementAnimated=function(a,b,c,d){return this.duScrollToElement(a,b,c||f,d)},i.duScrollTopAnimated=function(a,b,c){return this.duScrollTop(a,b||f,c)},i.duScrollLeftAnimated=function(a,b,c){return this.duScrollLeft(a,b||f,c)},angular.forEach(i,function(a,b){angular.element.prototype[b]=a;var c=b.replace(/^duScroll/,"scroll");angular.isUndefined(angular.element.prototype[c])&&(angular.element.prototype[c]=a)})}]),angular.module("duScroll.polyfill",[]).factory("polyfill",["$window",function(a){var b=["webkit","moz","o","ms"];return function(c,d){if(a[c])return a[c];for(var e,f=c.substr(0,1).toUpperCase()+c.substr(1),g=0;g=j.scrollHeight;else{var m=d[0].body.scrollHeight||d[0].documentElement.scrollHeight;b=Math.round(c.pageYOffset+c.innerHeight)>=m}var n,o,p,q,r,s,t=h&&b?"bottom":"top";for(q=e.spies,o=e.currentlyActive,p=void 0,n=0;n=112&&123>=a},isVerticalMovement:function(b){return~[a.UP,a.DOWN].indexOf(b)},isHorizontalMovement:function(b){return~[a.LEFT,a.RIGHT,a.BACKSPACE,a.DELETE].indexOf(b)},toSeparator:function(b){var c={ENTER:"\n",TAB:"\t",SPACE:" "}[b];return c?c:a[b]?void 0:b}};void 0===angular.element.prototype.querySelectorAll&&(angular.element.prototype.querySelectorAll=function(a){return angular.element(this[0].querySelectorAll(a))}),void 0===angular.element.prototype.closest&&(angular.element.prototype.closest=function(a){for(var b=this[0],c=b.matches||b.webkitMatchesSelector||b.mozMatchesSelector||b.msMatchesSelector;b;){if(c.bind(b)(a))return b;b=b.parentElement}return!1});var b=0,c=angular.module("ui.select",[]).constant("uiSelectConfig",{theme:"bootstrap",searchEnabled:!0,sortable:!1,placeholder:"",refreshDelay:1e3,closeOnSelect:!0,skipFocusser:!1,dropdownPosition:"auto",removeSelected:!0,generateId:function(){return b++},appendToBody:!1}).service("uiSelectMinErr",function(){var a=angular.$$minErr("ui.select");return function(){var b=a.apply(this,arguments),c=b.message.replace(new RegExp("\nhttp://errors.angularjs.org/.*"),"");return new Error(c)}}).directive("uisTranscludeAppend",function(){return{link:function(a,b,c,d,e){e(a,function(a){b.append(a)})}}}).filter("highlight",function(){function a(a){return(""+a).replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c&&b?(""+b).replace(new RegExp(a(c),"gi"),'$&'):b}}).factory("uisOffset",["$document","$window",function(a,b){return function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}}}]);c.directive("uiSelectChoices",["uiSelectConfig","uisRepeatParser","uiSelectMinErr","$compile","$window",function(a,b,c,d,e){return{restrict:"EA",require:"^uiSelect",replace:!0,transclude:!0,templateUrl:function(b){b.addClass("ui-select-choices");var c=b.parent().attr("theme")||a.theme;return c+"/choices.tpl.html"},compile:function(d,f){if(!f.repeat)throw c("repeat","Expected 'repeat' expression.");var g=f.groupBy,h=f.groupFilter;if(g){var i=d.querySelectorAll(".ui-select-choices-group");if(1!==i.length)throw c("rows","Expected 1 .ui-select-choices-group but got '{0}'.",i.length);i.attr("ng-repeat",b.getGroupNgRepeatExpression())}var j=b.parse(f.repeat),k=d.querySelectorAll(".ui-select-choices-row");if(1!==k.length)throw c("rows","Expected 1 .ui-select-choices-row but got '{0}'.",k.length);k.attr("ng-repeat",j.repeatExpression(g)).attr("ng-if","$select.open");var l=d.querySelectorAll(".ui-select-choices-row-inner");if(1!==l.length)throw c("rows","Expected 1 .ui-select-choices-row-inner but got '{0}'.",l.length);l.attr("uis-transclude-append","");var m=e.document.addEventListener?k:l;return m.attr("ng-click","$select.select("+j.itemName+",$select.skipFocusser,$event)"),function(b,c,d,e){e.parseRepeatAttr(d.repeat,g,h),e.disableChoiceExpression=d.uiDisableChoice,e.onHighlightCallback=d.onHighlight,e.dropdownPosition=d.position?d.position.toLowerCase():a.dropdownPosition,b.$on("$destroy",function(){k.remove()}),b.$watch("$select.search",function(a){a&&!e.open&&e.multiple&&e.activate(!1,!0),e.activeIndex=e.tagging.isActivated?-1:0,!d.minimumInputLength||e.search.length>=d.minimumInputLength?e.refresh(d.refresh):e.items=[]}),d.$observe("refreshDelay",function(){var c=b.$eval(d.refreshDelay);e.refreshDelay=void 0!==c?c:a.refreshDelay})}}}}]),c.controller("uiSelectCtrl",["$scope","$element","$timeout","$filter","$$uisDebounce","uisRepeatParser","uiSelectMinErr","uiSelectConfig","$parse","$injector","$window",function(b,c,d,e,f,g,h,i,j,k,l){function m(a,b,c){if(a.findIndex)return a.findIndex(b,c);for(var d,e=Object(a),f=e.length>>>0,g=0;f>g;g++)if(d=e[g],b.call(c,d,g,e))return g;return-1}function n(){(s.resetSearchInput||void 0===s.resetSearchInput&&i.resetSearchInput)&&(s.search=t,s.selected&&s.items.length&&!s.multiple&&(s.activeIndex=m(s.items,function(a){return angular.equals(this,a)},s.selected)))}function o(){(s.setSearchToAnswer||void 0===s.setSearchToAnswer&&i.setSearchToAnswer)&&(console.log("searchBy: "+s.searchBy),s.searchBy&&(console.log("_setSearchToAnswer"),s.resetSearchInput=!1,s.search=s.selected[s.searchBy]))}function p(a,b){var c,d,e=[];for(c=0;c0||0===s.search.length&&s.tagging.isActivated&&s.activeIndex>-1)&&s.activeIndex--;break;case a.TAB:s.multiple&&!s.open||s.select(s.items[s.activeIndex],!0);break;case a.ENTER:s.open&&(s.tagging.isActivated||s.activeIndex>=0)?s.select(s.items[s.activeIndex],s.skipFocusser):s.activate(!1,!0);break;case a.ESC:s.close();break;default:c=!1}return c}function r(){var a=c.querySelectorAll(".ui-select-choices-content"),b=a.querySelectorAll(".ui-select-choices-row");if(b.length<1)throw h("choices","Expected multiple .ui-select-choices-row but got '{0}'.",b.length);if(!(s.activeIndex<0)){var d=b[s.activeIndex],e=d.offsetTop+d.clientHeight-a[0].scrollTop,f=a[0].offsetHeight;e>f?a[0].scrollTop+=e-f:e=s.items.length?0:s.activeIndex,-1===s.activeIndex&&s.taggingLabel!==!1&&(s.activeIndex=0);var f=c.querySelectorAll(".ui-select-choices-content"),g=c.querySelectorAll(".ui-select-search");if(s.$animate&&s.$animate.on&&s.$animate.enabled(f[0])){var h=function(b,c){"start"===c&&0===s.items.length?(s.$animate.off("removeClass",g[0],h),d(function(){s.focusSearchInput(a)})):"close"===c&&(s.$animate.off("enter",f[0],h),d(function(){s.focusSearchInput(a)}))};s.items.length>0?s.$animate.on("enter",f[0],h):s.$animate.on("removeClass",g[0],h)}else d(function(){s.focusSearchInput(a),!s.tagging.isActivated&&s.items.length>1&&r()})}},s.focusSearchInput=function(a){s.search=a||s.search,s.searchInput[0].focus()},s.findGroupByName=function(a){return s.groups&&s.groups.filter(function(b){return b.name===a})[0]},s.parseRepeatAttr=function(a,c,d){function e(a){var e=b.$eval(c);if(s.groups=[],angular.forEach(a,function(a){var b=angular.isFunction(e)?e(a):a[e],c=s.findGroupByName(b);c?c.items.push(a):s.groups.push({name:b,items:[a]})}),d){var f=b.$eval(d);angular.isFunction(f)?s.groups=f(s.groups):angular.isArray(f)&&(s.groups=p(s.groups,f))}s.items=[],s.groups.forEach(function(a){s.items=s.items.concat(a.items)})}function f(a){s.items=a}s.setItemsFn=c?e:f,s.parserResult=g.parse(a),s.isGrouped=!!c,s.itemProperty=s.parserResult.itemName;var i=s.parserResult.source,k=function(){var a=i(b);b.$uisSource=Object.keys(a).map(function(b){var c={};return c[s.parserResult.keyName]=b,c.value=a[b],c})};s.parserResult.keyName&&(k(),s.parserResult.source=j("$uisSource"+s.parserResult.filters),b.$watch(i,function(a,b){a!==b&&k()},!0)),s.refreshItems=function(a){a=a||s.parserResult.source(b);var c=s.selected;if(s.isEmpty()||angular.isArray(c)&&!c.length||!s.removeSelected)s.setItemsFn(a);else if(void 0!==a){var d=a.filter(function(a){return angular.isArray(c)?c.every(function(b){return!angular.equals(a,b)}):!angular.equals(a,c)});s.setItemsFn(d)}"auto"!==s.dropdownPosition&&"up"!==s.dropdownPosition||b.calculateDropdownPos(),b.$broadcast("uis:refresh")},b.$watchCollection(s.parserResult.source,function(a){if(void 0===a||null===a)s.items=[];else{if(!angular.isArray(a))throw h("items","Expected an array but got '{0}'.",a);s.refreshItems(a),angular.isDefined(s.ngModel.$modelValue)&&(s.ngModel.$modelValue=null)}})};var u;s.refresh=function(a){void 0!==a&&(u&&d.cancel(u),u=d(function(){b.$eval(a)},s.refreshDelay))},s.isActive=function(a){if(!s.open)return!1;var b=s.items.indexOf(a[s.itemProperty]),c=b==s.activeIndex;return!(!c||0>b)&&(c&&!angular.isUndefined(s.onHighlightCallback)&&a.$eval(s.onHighlightCallback),c)};var v=function(a){return s.selected&&angular.isArray(s.selected)&&s.selected.filter(function(b){return angular.equals(b,a)}).length>0};s.isDisabled=function(a){if(s.open){var b,c=s.items.indexOf(a[s.itemProperty]),d=!1;return c>=0&&(!angular.isUndefined(s.disableChoiceExpression)||s.multiple)&&(b=s.items[c],d=!!a.$eval(s.disableChoiceExpression)||v(b),b._uiSelectChoiceDisabled=d),d}},s.select=function(a,c,e){if(void 0===a||!a._uiSelectChoiceDisabled){if(!s.items&&!s.search&&!s.tagging.isActivated)return;if(!a||!a._uiSelectChoiceDisabled){if(s.tagging.isActivated){if(s.taggingLabel===!1)if(s.activeIndex<0){if(a=void 0!==s.tagging.fct?s.tagging.fct(s.search):s.search,!a||angular.equals(s.items[0],a))return}else a=s.items[s.activeIndex];else if(0===s.activeIndex){if(void 0===a)return;if(void 0!==s.tagging.fct&&"string"==typeof a){if(a=s.tagging.fct(a),!a)return}else"string"==typeof a&&(a=a.replace(s.taggingLabel,"").trim())}if(v(a))return void s.close(c)}b.$broadcast("uis:select",a);var f={};f[s.parserResult.itemName]=a,d(function(){s.onSelectCallback(b,{$item:a,$model:s.parserResult.modelMapper(b,f)})}),s.closeOnSelect&&s.close(c),e&&"click"===e.type&&(s.clickTriggeredSelect=!0)}}},s.close=function(a){s.open&&(s.ngModel&&s.ngModel.$setTouched&&s.ngModel.$setTouched(),n(),o(),s.open=!1,b.$broadcast("uis:close",a))},s.setFocus=function(){s.focus||s.focusInput[0].focus()},s.clear=function(a){s.select(void 0),a.stopPropagation(),d(function(){s.focusser[0].focus()},0,!1)},s.toggle=function(a){s.open?(s.close(),a.preventDefault(),a.stopPropagation()):s.activate()},s.isLocked=function(a,b){var c,d=s.selected[b];return d&&!angular.isUndefined(s.lockChoiceExpression)&&(c=!!a.$eval(s.lockChoiceExpression),d._uiSelectChoiceLocked=c),c};var w=null,x=!1;s.sizeSearchInput=function(){var a=s.searchInput[0],c=s.searchInput.parent().parent()[0],e=function(){return c.clientWidth*!!a.offsetParent},f=function(b){if(0===b)return!1;var c=b-a.offsetLeft-10;return 50>c&&(c=b),s.searchInput.css("width",c+"px"),!0};s.searchInput.css("width","10px"),d(function(){null!==w||f(e())||(w=b.$watch(function(){x||(x=!0,b.$$postDigest(function(){x=!1,f(e())&&(w(),w=null)}))},angular.noop))})},s.searchInput.on("keydown",function(c){var e=c.which;~[a.ENTER,a.ESC].indexOf(e)&&(c.preventDefault(),c.stopPropagation()),b.$apply(function(){var b=!1;if((s.items.length>0||s.tagging.isActivated)&&(q(e),s.taggingTokens.isActivated)){for(var f=0;f0&&(b=!0);b&&d(function(){s.searchInput.triggerHandler("tagged");var b=s.search.replace(a.MAP[c.keyCode],"").trim();s.tagging.fct&&(b=s.tagging.fct(b)),b&&s.select(b,!0)})}}),a.isVerticalMovement(e)&&s.items.length>0&&r(),e!==a.ENTER&&e!==a.ESC||(c.preventDefault(),c.stopPropagation())}),s.searchInput.on("paste",function(b){var c;if(c=window.clipboardData&&window.clipboardData.getData?window.clipboardData.getData("Text"):(b.originalEvent||b).clipboardData.getData("text/plain"),c=s.search+c,c&&c.length>0)if(s.taggingTokens.isActivated){for(var d=[],e=0;e-1){d=c.split(f);break}}if(0===d.length&&(d=[c]),d.length>0){var g=s.search;angular.forEach(d,function(a){var b=s.tagging.fct?s.tagging.fct(a):a;b&&s.select(b,!0)}),s.search=g||t,b.preventDefault(),b.stopPropagation()}}else s.paste&&(s.paste(c),s.search=t,b.preventDefault(),b.stopPropagation())}),s.searchInput.on("tagged",function(){d(function(){n()})});var y=f(function(){s.sizeSearchInput()},50);angular.element(l).bind("resize",y),b.$on("$destroy",function(){s.searchInput.off("keyup keydown tagged blur paste"),angular.element(l).off("resize",y)})}]),c.directive("uiSelect",["$document","uiSelectConfig","uiSelectMinErr","uisOffset","$compile","$parse","$timeout",function(a,b,c,d,e,f,g){return{restrict:"EA",templateUrl:function(a,c){var d=c.theme||b.theme;return d+(angular.isDefined(c.multiple)?"/select-multiple.tpl.html":"/select.tpl.html")},replace:!0,transclude:!0,require:["uiSelect","^ngModel"],scope:!0,controller:"uiSelectCtrl",controllerAs:"$select",compile:function(e,h){var i=/{(.*)}\s*{(.*)}/.exec(h.ngClass);if(i){var j="{"+i[1]+", "+i[2]+"}";h.ngClass=j,e.attr("ng-class",j)}return angular.isDefined(h.multiple)?e.append("").removeAttr("multiple"):e.append(""),h.inputId&&(e.querySelectorAll("input.ui-select-search")[0].id=h.inputId),function(e,h,i,j,k){function l(a){if(o.open){var b=!1;if(b=window.jQuery?window.jQuery.contains(h[0],a.target):h[0].contains(a.target),!b&&!o.clickTriggeredSelect){var c;if(o.skipFocusser)c=!0;else{var d=["input","button","textarea","select"],f=angular.element(a.target).controller("uiSelect");c=f&&f!==o,c||(c=~d.indexOf(a.target.tagName.toLowerCase()))}o.close(c),e.$digest()}o.clickTriggeredSelect=!1}}function m(){var b=d(h);r=angular.element('
'),r[0].style.width=b.width+"px",r[0].style.height=b.height+"px",h.after(r),s=h[0].style.width,a.find("body").append(h),h[0].style.position="absolute",h[0].style.left=b.left+"px",h[0].style.top=b.top+"px",h[0].style.width=b.width+"px"}function n(){null!==r&&(r.replaceWith(h),r=null,h[0].style.position="",h[0].style.left="",h[0].style.top="",h[0].style.width=s,o.setFocus())}var o=j[0],p=j[1];o.generatedId=b.generateId(),o.baseTitle=i.title||"Select box",o.focusserTitle=o.baseTitle+" focus",o.focusserId="focusser-"+o.generatedId,o.closeOnSelect=function(){return angular.isDefined(i.closeOnSelect)?f(i.closeOnSelect)():b.closeOnSelect}(),e.$watch("skipFocusser",function(){var a=e.$eval(i.skipFocusser);o.skipFocusser=void 0!==a?a:b.skipFocusser}),o.onSelectCallback=f(i.onSelect),o.onRemoveCallback=f(i.onRemove),o.ngModel=p,o.choiceGrouped=function(a){return o.isGrouped&&a&&a.name},i.tabindex&&i.$observe("tabindex",function(a){o.focusInput.attr("tabindex",a),h.removeAttr("tabindex")}),e.$watch("searchEnabled",function(){var a=e.$eval(i.searchEnabled);o.searchEnabled=void 0!==a?a:b.searchEnabled}),e.$watch("sortable",function(){var a=e.$eval(i.sortable);o.sortable=void 0!==a?a:b.sortable}),i.$observe("limit",function(){o.limit=angular.isDefined(i.limit)?parseInt(i.limit,10):void 0}),e.$watch("removeSelected",function(){var a=e.$eval(i.removeSelected);o.removeSelected=void 0!==a?a:b.removeSelected}),i.$observe("disabled",function(){o.disabled=void 0!==i.disabled&&i.disabled}),i.$observe("resetSearchInput",function(){var a=e.$eval(i.resetSearchInput);o.resetSearchInput=void 0===a||a}),i.$observe("setSearchToAnswer",function(){var a=e.$eval(i.setSearchToAnswer);o.setSearchToAnswer=void 0===a||a}),i.$observe("searchBy",function(){o.searchBy=i.searchBy}),i.$observe("paste",function(){o.paste=e.$eval(i.paste)}),i.$observe("tagging",function(){if(void 0!==i.tagging){var a=e.$eval(i.tagging);o.tagging={isActivated:!0,fct:a!==!0?a:void 0}}else o.tagging={isActivated:!1,fct:void 0}}),i.$observe("taggingLabel",function(){void 0!==i.tagging&&("false"===i.taggingLabel?o.taggingLabel=!1:o.taggingLabel=void 0!==i.taggingLabel?i.taggingLabel:"(new)")}),i.$observe("taggingTokens",function(){if(void 0!==i.tagging){var a=void 0!==i.taggingTokens?i.taggingTokens.split("|"):[",","ENTER"];o.taggingTokens={isActivated:!0,tokens:a}}}),angular.isDefined(i.autofocus)&&g(function(){o.setFocus()}),angular.isDefined(i.focusOn)&&e.$on(i.focusOn,function(){g(function(){o.setFocus()})}),a.on("click",l),e.$on("$destroy",function(){a.off("click",l)}),k(e,function(a){var b=angular.element("
").append(a),d=b.querySelectorAll(".ui-select-match");if(d.removeAttr("ui-select-match"),d.removeAttr("data-ui-select-match"),1!==d.length)throw c("transcluded","Expected 1 .ui-select-match but got '{0}'.",d.length);h.querySelectorAll(".ui-select-match").replaceWith(d);var e=b.querySelectorAll(".ui-select-choices");if(e.removeAttr("ui-select-choices"),e.removeAttr("data-ui-select-choices"),1!==e.length)throw c("transcluded","Expected 1 .ui-select-choices but got '{0}'.",e.length);h.querySelectorAll(".ui-select-choices").replaceWith(e);var f=b.querySelectorAll(".ui-select-no-choice");f.removeAttr("ui-select-no-choice"),f.removeAttr("data-ui-select-no-choice"),1==f.length&&h.querySelectorAll(".ui-select-no-choice").replaceWith(f)});var q=e.$eval(i.appendToBody);(void 0!==q?q:b.appendToBody)&&(e.$watch("$select.open",function(a){a?m():n()}),e.$on("$destroy",function(){n()}));var r=null,s="",t=null,u="direction-up";e.$watch("$select.open",function(){"auto"!==o.dropdownPosition&&"up"!==o.dropdownPosition||e.calculateDropdownPos()});var v=function(a,b){a=a||d(h),b=b||d(t),t[0].style.position="absolute",t[0].style.top=-1*b.height+"px",h.addClass(u)},w=function(a,b){h.removeClass(u),a=a||d(h),b=b||d(t),t[0].style.position="",t[0].style.top=""},x=function(){g(function(){if("up"===o.dropdownPosition)v();else{h.removeClass(u);var b=d(h),c=d(t),e=a[0].documentElement.scrollTop||a[0].body.scrollTop;b.top+b.height+c.height>e+a[0].documentElement.clientHeight?v(b,c):w(b,c)}t[0].style.opacity=1})};e.calculateDropdownPos=function(){if(o.open){if(t=angular.element(h).querySelectorAll(".ui-select-dropdown"),0===t.length)return;if(t[0].style.opacity=0,!d(t).height&&o.$animate&&o.$animate.on&&o.$animate.enabled(t)){var a=!0;o.$animate.on("enter",t,function(b,c){"close"===c&&a&&(x(),a=!1)})}else x()}else{if(null===t||0===t.length)return;t[0].style.opacity=0,t[0].style.position="",t[0].style.top="",h.removeClass(u)}}}}}}]),c.directive("uiSelectMatch",["uiSelectConfig",function(a){function b(a,b){return a[0].hasAttribute(b)?a.attr(b):a[0].hasAttribute("data-"+b)?a.attr("data-"+b):a[0].hasAttribute("x-"+b)?a.attr("x-"+b):void 0}return{restrict:"EA",require:"^uiSelect",replace:!0,transclude:!0,templateUrl:function(c){c.addClass("ui-select-match");var d=c.parent(),e=b(d,"theme")||a.theme,f=angular.isDefined(b(d,"multiple"));return e+(f?"/match-multiple.tpl.html":"/match.tpl.html")},link:function(b,c,d,e){function f(a){e.allowClear=!!angular.isDefined(a)&&(""===a||"true"===a.toLowerCase())}e.lockChoiceExpression=d.uiLockChoice,d.$observe("placeholder",function(b){e.placeholder=void 0!==b?b:a.placeholder}),d.$observe("allowClear",f),f(d.allowClear),e.multiple&&e.sizeSearchInput()}}}]),c.directive("uiSelectMultiple",["uiSelectMinErr","$timeout",function(b,c){return{restrict:"EA",require:["^uiSelect","^ngModel"],controller:["$scope","$timeout",function(a,b){var c,d=this,e=a.$select;angular.isUndefined(e.selected)&&(e.selected=[]),a.$evalAsync(function(){c=a.ngModel}),d.activeMatchIndex=-1,d.updateModel=function(){c.$setViewValue(Date.now()),d.refreshComponent()},d.refreshComponent=function(){e.refreshItems(),e.sizeSearchInput()},d.removeChoice=function(c){var f=e.selected[c];if(!f._uiSelectChoiceLocked){var g={};g[e.parserResult.itemName]=f,e.selected.splice(c,1),d.activeMatchIndex=-1,e.sizeSearchInput(),b(function(){e.onRemoveCallback(a,{$item:f,$model:e.parserResult.modelMapper(a,g)})}),d.updateModel()}},d.getPlaceholder=function(){return e.selected&&e.selected.length?void 0:e.placeholder}}],controllerAs:"$selectMultiple",link:function(d,e,f,g){function h(a){return angular.isNumber(a.selectionStart)?a.selectionStart:a.value.length}function i(b){function c(){switch(b){case a.LEFT:return~n.activeMatchIndex?k:g;case a.RIGHT:return~n.activeMatchIndex&&i!==g?j:(l.activate(),!1);case a.BACKSPACE:return~n.activeMatchIndex?(n.removeChoice(i),k):g;case a.DELETE:return!!~n.activeMatchIndex&&(n.removeChoice(n.activeMatchIndex),i)}}var d=h(l.searchInput[0]),e=l.selected.length,f=0,g=e-1,i=n.activeMatchIndex,j=n.activeMatchIndex+1,k=n.activeMatchIndex-1,m=i;return!(d>0||l.search.length&&b==a.RIGHT)&&(l.close(),m=c(),l.selected.length&&m!==!1?n.activeMatchIndex=Math.min(g,Math.max(f,m)):n.activeMatchIndex=-1,!0)}function j(a){if(void 0===a||void 0===l.search)return!1;var b=a.filter(function(a){return void 0!==l.search.toUpperCase()&&void 0!==a&&a.toUpperCase()===l.search.toUpperCase()}).length>0;return b}function k(a,b){var c=-1;if(angular.isArray(a))for(var d=angular.copy(a),e=0;e=0;e--)b={},b[l.parserResult.itemName]=l.selected[e],a=l.parserResult.modelMapper(d,b),c.unshift(a);return c}),m.$formatters.unshift(function(a){var b,c=l.parserResult&&l.parserResult.source(d,{$select:{search:""}}),e={};if(!c)return a;var f=[],g=function(a,c){if(a&&a.length){for(var g=a.length-1;g>=0;g--){if(e[l.parserResult.itemName]=a[g],b=l.parserResult.modelMapper(d,e),l.parserResult.trackByExp){var h=/(\w*)\./.exec(l.parserResult.trackByExp),i=/\.([^\s]+)/.exec(l.parserResult.trackByExp);if(h&&h.length>0&&h[1]==l.parserResult.itemName&&i&&i.length>0&&b[i[1]]==c[i[1]])return f.unshift(a[g]),!0}if(angular.equals(b,c))return f.unshift(a[g]),!0}return!1}};if(!a)return f;for(var h=a.length-1;h>=0;h--)g(l.selected,a[h])||g(c,a[h])||f.unshift(a[h]);return f}),d.$watchCollection(function(){return m.$modelValue},function(a,b){b!=a&&(angular.isDefined(m.$modelValue)&&(m.$modelValue=null),n.refreshComponent())}),m.$render=function(){if(!angular.isArray(m.$viewValue)){if(!angular.isUndefined(m.$viewValue)&&null!==m.$viewValue)throw b("multiarr","Expected model value to be array but got '{0}'",m.$viewValue);l.selected=[]}l.selected=m.$viewValue,n.refreshComponent(),d.$evalAsync()},d.$on("uis:select",function(a,b){l.selected.length>=l.limit||(l.selected.push(b),n.updateModel())}),d.$on("uis:activate",function(){n.activeMatchIndex=-1}),d.$watch("$select.disabled",function(a,b){b&&!a&&l.sizeSearchInput()}),l.searchInput.on("keydown",function(b){var c=b.which;d.$apply(function(){var d=!1;a.isHorizontalMovement(c)&&(d=i(c)),d&&c!=a.TAB&&(b.preventDefault(),b.stopPropagation())})}),l.searchInput.on("keyup",function(b){if(a.isVerticalMovement(b.which)||d.$evalAsync(function(){l.activeIndex=l.taggingLabel===!1?-1:0}),l.tagging.isActivated&&l.search.length>0){if(b.which===a.TAB||a.isControl(b)||a.isFunctionKey(b)||b.which===a.ESC||a.isVerticalMovement(b.which))return;if(l.activeIndex=l.taggingLabel===!1?-1:0,l.taggingLabel===!1)return;var c,e,f,g,h=angular.copy(l.items),i=angular.copy(l.items),m=!1,n=-1;if(void 0!==l.tagging.fct){if(f=l.$filter("filter")(h,{isTag:!0}),f.length>0&&(g=f[0]),h.length>0&&g&&(m=!0,h=h.slice(1,h.length),i=i.slice(1,i.length)),c=l.tagging.fct(l.search),i.some(function(a){return angular.equals(a,c)})||l.selected.some(function(a){return angular.equals(a,c)}))return void d.$evalAsync(function(){l.activeIndex=0,l.items=h});c&&(c.isTag=!0)}else{if(f=l.$filter("filter")(h,function(a){return a.match(l.taggingLabel)}),f.length>0&&(g=f[0]),e=h[0],void 0!==e&&h.length>0&&g&&(m=!0,h=h.slice(1,h.length),i=i.slice(1,i.length)),c=l.search+" "+l.taggingLabel,k(l.selected,l.search)>-1)return;if(j(i.concat(l.selected)))return void(m&&(h=i,d.$evalAsync(function(){l.activeIndex=0,l.items=h})));if(j(i))return void(m&&(l.items=i.slice(1,i.length)))}m&&(n=k(l.selected,c)),n>-1?h=h.slice(n+1,h.length-1):(h=[],c&&h.push(c),h=h.concat(i)),d.$evalAsync(function(){if(l.activeIndex=0,l.items=h,l.isGrouped){var a=c?h.slice(1):h;l.setItemsFn(a),c&&(l.items.unshift(c),l.groups.unshift({name:"",items:[c],tagging:!0}))}})}}),l.searchInput.on("blur",function(){c(function(){n.activeMatchIndex=-1})})}}}]),c.directive("uiSelectNoChoice",["uiSelectConfig",function(a){return{restrict:"EA",require:"^uiSelect",replace:!0,transclude:!0,templateUrl:function(b){b.addClass("ui-select-no-choice");var c=b.parent().attr("theme")||a.theme;return c+"/no-choice.tpl.html"}}}]),c.directive("uiSelectSingle",["$timeout","$compile",function(b,c){return{restrict:"EA",require:["^uiSelect","^ngModel"],link:function(d,e,f,g){var h=g[0],i=g[1];i.$parsers.unshift(function(a){var b,c={};return c[h.parserResult.itemName]=a,b=h.parserResult.modelMapper(d,c)}),i.$formatters.unshift(function(a){var b,c=h.parserResult&&h.parserResult.source(d,{$select:{search:""}}),e={};if(c){var f=function(c){return e[h.parserResult.itemName]=c,b=h.parserResult.modelMapper(d,e),b===a};if(h.selected&&f(h.selected))return h.selected;for(var g=c.length-1;g>=0;g--)if(f(c[g]))return c[g]}return a}),d.$watch("$select.selected",function(a){i.$viewValue!==a&&i.$setViewValue(a)}),i.$render=function(){h.selected=i.$viewValue},d.$on("uis:select",function(a,b){h.selected=b}),d.$on("uis:close",function(a,c){b(function(){h.focusser.prop("disabled",!1),c||h.focusser[0].focus()},0,!1)}),d.$on("uis:activate",function(){j.prop("disabled",!0)});var j=angular.element("");c(j)(d),h.focusser=j,h.focusInput=j,e.parent().append(j),j.bind("focus",function(){d.$evalAsync(function(){h.focus=!0})}),j.bind("blur",function(){d.$evalAsync(function(){h.focus=!1})}),j.bind("keydown",function(b){return b.which===a.BACKSPACE?(b.preventDefault(),b.stopPropagation(),h.select(void 0),void d.$apply()):void(b.which===a.TAB||a.isControl(b)||a.isFunctionKey(b)||b.which===a.ESC||(b.which!=a.DOWN&&b.which!=a.UP&&b.which!=a.ENTER&&b.which!=a.SPACE||(b.preventDefault(),b.stopPropagation(),h.activate()),d.$digest()))}),j.bind("keyup input",function(b){b.which===a.TAB||a.isControl(b)||a.isFunctionKey(b)||b.which===a.ESC||b.which==a.ENTER||b.which===a.BACKSPACE||(h.activate(j.val()),j.val(""),d.$digest())})}}}]),c.directive("uiSelectSort",["$timeout","uiSelectConfig","uiSelectMinErr",function(a,b,c){return{require:["^^uiSelect","^ngModel"],link:function(b,d,e,f){if(null===b[e.uiSelectSort])throw c("sort","Expected a list to sort");var g=f[0],h=f[1],i=angular.extend({axis:"horizontal"},b.$eval(e.uiSelectSortOptions)),j=i.axis,k="dragging",l="dropping",m="dropping-before",n="dropping-after";b.$watch(function(){return g.sortable},function(a){a?d.attr("draggable",!0):d.removeAttr("draggable")}),d.on("dragstart",function(a){d.addClass(k),(a.dataTransfer||a.originalEvent.dataTransfer).setData("text",b.$index.toString())}),d.on("dragend",function(){q(k)});var o,p=function(a,b){this.splice(b,0,this.splice(a,1)[0])},q=function(a){angular.forEach(g.$element.querySelectorAll("."+a),function(b){angular.element(b).removeClass(a)})},r=function(a){a.preventDefault();var b="vertical"===j?a.offsetY||a.layerY||(a.originalEvent?a.originalEvent.offsetY:0):a.offsetX||a.layerX||(a.originalEvent?a.originalEvent.offsetX:0);b
  • '),a.put("bootstrap/match-multiple.tpl.html",' × '),a.put("bootstrap/match.tpl.html",'
    {{$select.placeholder}}
    '), -a.put("bootstrap/no-choice.tpl.html",''),a.put("bootstrap/select-multiple.tpl.html",''),a.put("bootstrap/select.tpl.html",''),a.put("select2/choices.tpl.html",'
    '),a.put("select2/match-multiple.tpl.html",'
  • '),a.put("select2/match.tpl.html",'{{$select.placeholder}} '),a.put("select2/select-multiple.tpl.html",'
    '),a.put("select2/select.tpl.html",'
    '),a.put("selectize/choices.tpl.html",'
    '),a.put("selectize/match.tpl.html",'
    '),a.put("selectize/select.tpl.html",'
    ')}]),!function(a){function b(b,c){return{restrict:"A",scope:{isBusy:"=vBusy",busyLabel:"@vBusyLabel",busyText:"@vBusyText"},compile:function(b,d){var e=a.element(b.find("span"));return e[0]||(b.html(""+b.html()+""),e=a.element(b.find("span"))),function(a,b){var f=e.html(),g=a.busyLabel||c.busyLabel,h=a.busyText;a.$watch("isBusy",function(a){a?(b.addClass(c.states.busy),e.html(g)):(b.removeClass(c.states.busy),e.html(h||f))}),d.$observe("vBusyLabel",function(a){g=a}),d.$observe("vBusyText",function(a){h=a})}}}}function c(b,c){return{restrict:"A",link:function(d,e){function f(c,d){var f,g,h=e[0].getBoundingClientRect(),i=e[0].querySelector("v-ripple");a.element(i).remove(),i=b[0].createElement("v-ripple"),i.style.height=i.style.width=Math.max(h.width,h.height)+"px",e.append(i),g=c-h.left-i.offsetWidth/2-l[0].scrollLeft,f=d-h.top-i.offsetHeight/2-l[0].scrollTop,i.style.left=g+"px",i.style.top=f+"px"}function g(a){f(a.pageX,a.pageY),e.addClass(c.states.pressed),l.bind(k,h)}function h(){e.removeClass(c.states.pressed),l.unbind(k,h)}var i=!("undefined"==typeof b[0].documentElement.ontouchstart),j=i?"touchstart":"mousedown",k=i?"touchend":"mouseup",l=a.element(b[0].body);e.bind(j,g)}}}a.module("vButton.config",[]).constant("buttonConfig",{busyLabel:"Loading",states:{busy:"is-busy",pressed:"is-pressed"}}),a.module("vButton.directives",[]),a.module("vButton",["vButton.config","vButton.directives"]),a.module("vButton.directives").directive("vBusy",b),b.$inject=["$document","buttonConfig"],a.module("vButton.directives").directive("vPressable",c),c.$inject=["$document","buttonConfig"]}(angular),function(a,b,c){function d(a,c){c=c||{},b.forEach(c,function(a,b){delete c[b]});for(var d in a)!a.hasOwnProperty(d)||"$"===d.charAt(0)&&"$"===d.charAt(1)||(c[d]=a[d]);return c}var e=b.$$minErr("$resource"),f=/^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;b.module("ngResource",["ng"]).provider("$resource",function(){var a=/^https?:\/\/[^\/]*/,g=this;this.defaults={stripTrailingSlashes:!0,actions:{get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}}},this.$get=["$http","$log","$q",function(h,i,j){function k(a,b){this.template=a,this.defaults=o({},g.defaults,b),this.urlParams={}}function l(a,r,s,t){function u(a,d){var g={};return d=o({},r,d),n(d,function(d,h){q(d)&&(d=d());var i;if(d&&d.charAt&&"@"==d.charAt(0)){i=a;var j=d.substr(1);if(null==j||""===j||"hasOwnProperty"===j||!f.test("."+j))throw e("badmember",j);for(var j=j.split("."),k=0,l=j.length;k>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function i(a,b,c,d){var e,i=f(c,d),j={},k=[];for(var l in i)if(i[l]&&i[l].params&&(e=g(i[l].params),e.length))for(var m in e)h(k,e[m])>=0||(k.push(e[m]),j[e[m]]=a[e[m]]);return R({},j,b)}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e "));if(s[c]=d,N(a))q.push(c,[function(){return b.get(a)}],j);else{var e=b.annotate(a);Q(e,function(a){a!==c&&i.hasOwnProperty(a)&&n(i[a],a)}),q.push(c,a,e)}r.pop(),s[c]=f}}function o(a){return O(a)&&a.then&&a.$$promises}if(!O(i))throw new Error("'invocables' must be an object");var p=g(i||{}),q=[],r=[],s={};return Q(i,n),i=r=s=null,function(d,f,g){function h(){--u||(v||e(t,f.$$values),r.$$values=t,r.$$promises=r.$$promises||!0,delete r.$$inheritedValues,n.resolve(t))}function i(a){r.$$failure=a,n.reject(a)}function j(c,e,f){function j(a){l.reject(a),i(a)}function k(){if(!L(r.$$failure))try{l.resolve(b.invoke(e,g,t)),l.promise.then(function(a){t[c]=a,h()},j)}catch(a){j(a)}}var l=a.defer(),m=0;Q(f,function(a){s.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,s[a].then(function(b){t[a]=b,--m||k()},j))}),m||k(),s[c]=l.promise}if(o(d)&&g===c&&(g=f,f=d,d=null),d){if(!O(d))throw new Error("'locals' must be an object")}else d=k;if(f){if(!o(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=l;var n=a.defer(),r=n.promise,s=r.$$promises={},t=R({},d),u=1+q.length/3,v=!1;if(L(f.$$failure))return i(f.$$failure),r;f.$$inheritedValues&&e(t,m(f.$$inheritedValues,p)),R(s,f.$$promises),f.$$values?(v=e(t,m(f.$$values,p)),r.$$inheritedValues=m(f.$$values,p),h()):(f.$$inheritedValues&&(r.$$inheritedValues=m(f.$$inheritedValues,p)),f.then(h,i));for(var w=0,x=q.length;x>w;w+=3)d.hasOwnProperty(q[w])?h():j(q[w],q[w+1],q[w+2]);return r}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function q(a,b,c){this.fromConfig=function(a,b,c){return L(a.template)?this.fromString(a.template,b):L(a.templateUrl)?this.fromUrl(a.templateUrl,b):L(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return M(a)?a(b):a},this.fromUrl=function(c,d){return M(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b,headers:{Accept:"text/html"}}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function r(a,b,e){function f(b,c,d,e){if(q.push(b),o[b])return o[b];if(!/^\w+([-.]+\w+)*(?:\[\])?$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(p[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");return p[b]=new U.Param(b,c,d,e),p[b]}function g(a,b,c,d){var e=["",""],f=a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&");if(!b)return f;switch(c){case!1:e=["(",")"+(d?"?":"")];break;case!0:f=f.replace(/\/$/,""),e=["(?:/(",")|/)?"];break;default:e=["("+c+"|",")?"]}return f+e[0]+b+e[1]}function h(e,f){var g,h,i,j,k;return g=e[2]||e[3],k=b.params[g],i=a.substring(m,e.index),h=f?e[4]:e[4]||("*"==e[1]?".*":null),h&&(j=U.type(h)||d(U.type("string"),{pattern:new RegExp(h,b.caseInsensitive?"i":c)})),{id:g,regexp:h,segment:i,type:j,cfg:k}}b=R({params:{}},O(b)?b:{});var i,j=/([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,k=/([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,l="^",m=0,n=this.segments=[],o=e?e.params:{},p=this.params=e?e.params.$$new():new U.ParamSet,q=[];this.source=a;for(var r,s,t;(i=j.exec(a))&&(r=h(i,!1),!(r.segment.indexOf("?")>=0));)s=f(r.id,r.type,r.cfg,"path"),l+=g(r.segment,s.type.pattern.source,s.squash,s.isOptional),n.push(r.segment),m=j.lastIndex;t=a.substring(m);var u=t.indexOf("?");if(u>=0){var v=this.sourceSearch=t.substring(u);if(t=t.substring(0,u),this.sourcePath=a.substring(0,m+u),v.length>0)for(m=0;i=k.exec(v);)r=h(i,!0),s=f(r.id,r.type,r.cfg,"search"),m=j.lastIndex}else this.sourcePath=a,this.sourceSearch="";l+=g(t)+(b.strict===!1?"/?":"")+"$",n.push(t),this.regexp=new RegExp(l,b.caseInsensitive?"i":c),this.prefix=n[0],this.$$paramNames=q}function s(a){R(this,a)}function t(){function a(a){return null!=a?a.toString().replace(/~/g,"~~").replace(/\//g,"~2F"):a}function e(a){return null!=a?a.toString().replace(/~2F/g,"/").replace(/~~/g,"~"):a}function f(){return{strict:p,caseInsensitive:m}}function i(a){return M(a)||P(a)&&M(a[a.length-1])}function j(){for(;w.length;){var a=w.shift();if(a.pattern)throw new Error("You cannot override a type's .pattern at runtime.");b.extend(u[a.name],l.invoke(a.def))}}function k(a){R(this,a||{})}U=this;var l,m=!1,p=!0,q=!1,u={},v=!0,w=[],x={string:{encode:a,decode:e,is:function(a){return null==a||!L(a)||"string"==typeof a},pattern:/[^\/]*/},"int":{encode:a,decode:function(a){return parseInt(a,10)},is:function(a){return L(a)&&this.decode(a.toString())===a},pattern:/\d+/},bool:{encode:function(a){return a?1:0},decode:function(a){return 0!==parseInt(a,10)},is:function(a){return a===!0||a===!1},pattern:/0|1/},date:{encode:function(a){return this.is(a)?[a.getFullYear(),("0"+(a.getMonth()+1)).slice(-2),("0"+a.getDate()).slice(-2)].join("-"):c},decode:function(a){if(this.is(a))return a;var b=this.capture.exec(a);return b?new Date(b[1],b[2]-1,b[3]):c},is:function(a){return a instanceof Date&&!isNaN(a.valueOf())},equals:function(a,b){return this.is(a)&&this.is(b)&&a.toISOString()===b.toISOString()},pattern:/[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,capture:/([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/},json:{encode:b.toJson,decode:b.fromJson,is:b.isObject,equals:b.equals,pattern:/[^\/]*/},any:{encode:b.identity,decode:b.identity,equals:b.equals,pattern:/.*/}};t.$$getDefaultValue=function(a){if(!i(a.value))return a.value;if(!l)throw new Error("Injectable functions cannot be called at configuration time");return l.invoke(a.value)},this.caseInsensitive=function(a){return L(a)&&(m=a),m},this.strictMode=function(a){return L(a)&&(p=a),p},this.defaultSquashPolicy=function(a){if(!L(a))return q;if(a!==!0&&a!==!1&&!N(a))throw new Error("Invalid squash policy: "+a+". Valid policies: false, true, arbitrary-string");return q=a,a},this.compile=function(a,b){return new r(a,R(f(),b))},this.isMatcher=function(a){if(!O(a))return!1;var b=!0;return Q(r.prototype,function(c,d){M(c)&&(b=b&&L(a[d])&&M(a[d]))}),b},this.type=function(a,b,c){if(!L(b))return u[a];if(u.hasOwnProperty(a))throw new Error("A type named '"+a+"' has already been defined.");return u[a]=new s(R({name:a},b)),c&&(w.push({name:a,def:c}),v||j()),this},Q(x,function(a,b){u[b]=new s(R({name:b},a))}),u=d(u,{}),this.$get=["$injector",function(a){return l=a,v=!1,j(),Q(x,function(a,b){u[b]||(u[b]=new s(a))}),this}],this.Param=function(a,d,e,f){function j(a){var b=O(a)?g(a):[],c=-1===h(b,"value")&&-1===h(b,"type")&&-1===h(b,"squash")&&-1===h(b,"array");return c&&(a={value:a}),a.$$fn=i(a.value)?a.value:function(){return a.value},a}function k(c,d,e){if(c.type&&d)throw new Error("Param '"+a+"' has two type configurations.");return d?d:c.type?b.isString(c.type)?u[c.type]:c.type instanceof s?c.type:new s(c.type):"config"===e?u.any:u.string}function m(){var b={array:"search"===f&&"auto"},c=a.match(/\[\]$/)?{array:!0}:{};return R(b,c,e).array}function p(a,b){var c=a.squash;if(!b||c===!1)return!1;if(!L(c)||null==c)return q;if(c===!0||N(c))return c;throw new Error("Invalid squash policy: '"+c+"'. Valid policies: false, true, or arbitrary string")}function r(a,b,d,e){var f,g,i=[{from:"",to:d||b?c:""},{from:null,to:d||b?c:""}];return f=P(a.replace)?a.replace:[],N(e)&&f.push({from:e,to:c}),g=o(f,function(a){return a.from}),n(i,function(a){return-1===h(g,a.from)}).concat(f)}function t(){if(!l)throw new Error("Injectable functions cannot be called at configuration time");var a=l.invoke(e.$$fn);if(null!==a&&a!==c&&!x.type.is(a))throw new Error("Default value ("+a+") for parameter '"+x.id+"' is not an instance of Type ("+x.type.name+")");return a}function v(a){function b(a){return function(b){return b.from===a}}function c(a){var c=o(n(x.replace,b(a)),function(a){return a.to});return c.length?c[0]:a}return a=c(a),L(a)?x.type.$normalize(a):t()}function w(){return"{Param:"+a+" "+d+" squash: '"+A+"' optional: "+z+"}"}var x=this;e=j(e),d=k(e,d,f);var y=m();d=y?d.$asArray(y,"search"===f):d,"string"!==d.name||y||"path"!==f||e.value!==c||(e.value="");var z=e.value!==c,A=p(e,z),B=r(e,y,z,A);R(this,{id:a,type:d,location:f,array:y,squash:A,replace:B,isOptional:z,value:v,dynamic:c,config:e,toString:w})},k.prototype={$$new:function(){return d(this,R(new k,{$$parent:this}))},$$keys:function(){for(var a=[],b=[],c=this,d=g(k.prototype);c;)b.push(c),c=c.$$parent;return b.reverse(),Q(b,function(b){Q(g(b),function(b){-1===h(a,b)&&-1===h(d,b)&&a.push(b)})}),a},$$values:function(a){var b={},c=this;return Q(c.$$keys(),function(d){b[d]=c[d].value(a&&a[d])}),b},$$equals:function(a,b){var c=!0,d=this;return Q(d.$$keys(),function(e){var f=a&&a[e],g=b&&b[e];d[e].type.equals(f,g)||(c=!1)}),c},$$validates:function(a){var d,e,f,g,h,i=this.$$keys();for(d=0;de;e++)if(b(j[e]))return;k&&b(k)}}function o(){return i=i||e.$on("$locationChangeSuccess",n)}var p,q=g.baseHref(),r=d.url();return l||o(),{sync:function(){n()},listen:function(){return o()},update:function(a){return a?void(r=d.url()):void(d.url()!==r&&(d.url(r),d.replace()))},push:function(a,b,e){var f=a.format(b||{});null!==f&&b&&b["#"]&&(f+="#"+b["#"]),d.url(f),p=e&&e.$$avoidResync?d.url():c,e&&e.replace&&d.replace()},href:function(c,e,f){if(!c.validates(e))return null;var g=a.html5Mode();b.isObject(g)&&(g=g.enabled),g=g&&h.history;var i=c.format(e);if(f=f||{},g||null===i||(i="#"+a.hashPrefix()+i),null!==i&&e&&e["#"]&&(i+="#"+e["#"]),i=m(i,g,f.absolute),!f.absolute||!i)return i;var j=!g&&i?"/":"",k=d.port();return k=80===k||443===k?"":":"+k,[d.protocol(),"://",d.host(),k,j,i].join("")}}}var i,j=[],k=null,l=!1;this.rule=function(a){if(!M(a))throw new Error("'rule' must be a function");return j.push(a),this},this.otherwise=function(a){if(N(a)){var b=a;a=function(){return b}}else if(!M(a))throw new Error("'rule' must be a function");return k=a,this},this.when=function(a,b){var c,h=N(b);if(N(a)&&(a=d.compile(a)),!h&&!M(b)&&!P(b))throw new Error("invalid 'handler' in when()");var i={matcher:function(a,b){return h&&(c=d.compile(b),b=["$match",function(a){return c.format(a)}]),R(function(c,d){return g(c,b,a.exec(d.path(),d.search()))},{prefix:N(a.prefix)?a.prefix:""})},regex:function(a,b){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(c=b,b=["$match",function(a){return f(c,a)}]),R(function(c,d){return g(c,b,a.exec(d.path()))},{prefix:e(a)})}},j={matcher:d.isMatcher(a),regex:a instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](a,b));throw new Error("invalid 'what' in when()")},this.deferIntercept=function(a){a===c&&(a=!0),l=a},this.$get=h,h.$inject=["$location","$rootScope","$injector","$browser","$sniffer"]}function v(a,e){function f(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function m(a,b){if(!a)return c;var d=N(a),e=d?a:a.name,g=f(e);if(g){if(!b)throw new Error("No reference point given for path '"+e+"'");b=m(b);for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=z[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function n(a,b){A[a]||(A[a]=[]),A[a].push(b)}function p(a){for(var b=A[a]||[];b.length;)q(b.shift())}function q(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!N(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(z.hasOwnProperty(c))throw new Error("State '"+c+"' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):N(b.parent)?b.parent:O(b.parent)&&N(b.parent.name)?b.parent.name:"";if(e&&!z[e])return n(e,b.self);for(var f in C)M(C[f])&&(b[f]=C[f](b,C.$delegates[f]));return z[c]=b,!b[B]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){y.$current.navigable==b&&j(a,c)||y.transitionTo(b,a,{inherit:!0,location:!1})}]),p(c),b}function r(a){return a.indexOf("*")>-1}function s(a){for(var b=a.split("."),c=y.$current.name.split("."),d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return"**"===b[0]&&(c=c.slice(h(c,b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(h(c,b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length==c.length&&c.join("")===b.join("")}function t(a,b){return N(a)&&!L(b)?C[a]:M(b)&&N(a)?(C[a]&&!C.$delegates[a]&&(C.$delegates[a]=C[a]),C[a]=b,this):this}function u(a,b){return O(a)?b=a:b.name=a,q(b),this}function v(a,e,f,h,l,n,p,q,t){function u(b,c,d,f){var g=a.$broadcast("$stateNotFound",b,c,d);if(g.defaultPrevented)return p.update(),D;if(!g.retry)return null;if(f.$retry)return p.update(),E;var h=y.transition=e.when(g.retry);return h.then(function(){return h!==y.transition?A:(b.options.$retry=!0,y.transitionTo(b.to,b.toParams,b.options))},function(){return D}),p.update(),h}function v(a,c,d,g,i,j){function m(){var c=[];return Q(a.views,function(d,e){var g=d.resolve&&d.resolve!==a.resolve?d.resolve:{};g.$template=[function(){return f.load(e,{view:d,locals:i.globals,params:n,notify:j.notify})||""}],c.push(l.resolve(g,i.globals,i.resolve,a).then(function(c){if(M(d.controllerProvider)||P(d.controllerProvider)){var f=b.extend({},g,i.globals);c.$$controller=h.invoke(d.controllerProvider,null,f)}else c.$$controller=d.controller;c.$$state=a,c.$$controllerAs=d.controllerAs,i[e]=c}))}),e.all(c).then(function(){return i.globals})}var n=d?c:k(a.params.$$keys(),c),o={$stateParams:n};i.resolve=l.resolve(a.resolve,o,i.resolve,a);var p=[i.resolve.then(function(a){i.globals=a})];return g&&p.push(g),e.all(p).then(m).then(function(a){return i})}var A=e.reject(new Error("transition superseded")),C=e.reject(new Error("transition prevented")),D=e.reject(new Error("transition aborted")),E=e.reject(new Error("transition failed"));return x.locals={resolve:null,globals:{$stateParams:{}}},y={params:{},current:x.self,$current:x,transition:null},y.reload=function(a){return y.transitionTo(y.current,n,{reload:a||!0,inherit:!1,notify:!0})},y.go=function(a,b,c){return y.transitionTo(a,b,R({inherit:!0,relative:y.$current},c))},y.transitionTo=function(b,c,f){c=c||{},f=R({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,j=y.$current,l=y.params,o=j.path,q=m(b,f.relative),r=c["#"];if(!L(q)){var s={to:b,toParams:c,options:f},t=u(s,j.self,l,f);if(t)return t;if(b=s.to,c=s.toParams,f=s.options,q=m(b,f.relative),!L(q)){if(!f.relative)throw new Error("No such state '"+b+"'");throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'")}}if(q[B])throw new Error("Cannot transition to abstract state '"+b+"'");if(f.inherit&&(c=i(n,c||{},y.$current,q)),!q.params.$$validates(c))return E;c=q.params.$$values(c),b=q;var z=b.path,D=0,F=z[D],G=x.locals,H=[];if(f.reload){if(N(f.reload)||O(f.reload)){if(O(f.reload)&&!f.reload.name)throw new Error("Invalid reload state object");var I=f.reload===!0?o[0]:m(f.reload);if(f.reload&&!I)throw new Error("No such reload state '"+(N(f.reload)?f.reload:f.reload.name)+"'");for(;F&&F===o[D]&&F!==I;)G=H[D]=F.locals,D++,F=z[D]}}else for(;F&&F===o[D]&&F.ownParams.$$equals(c,l);)G=H[D]=F.locals,D++,F=z[D];if(w(b,c,j,l,G,f))return r&&(c["#"]=r),y.params=c,S(y.params,n),S(k(b.params.$$keys(),n),b.locals.globals.$stateParams),f.location&&b.navigable&&b.navigable.url&&(p.push(b.navigable.url,c,{$$avoidResync:!0,replace:"replace"===f.location}),p.update(!0)),y.transition=null,e.when(y.current);if(c=k(b.params.$$keys(),c||{}),r&&(c["#"]=r),f.notify&&a.$broadcast("$stateChangeStart",b.self,c,j.self,l,f).defaultPrevented)return a.$broadcast("$stateChangeCancel",b.self,c,j.self,l),null==y.transition&&p.update(),C;for(var J=e.when(G),K=D;K=D;d--)g=o[d],g.self.onExit&&h.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=D;d=4?!!j.enabled(a):1===V&&W>=2?!!j.enabled():!!i}var e={enter:function(a,b,c){b.after(a),c()},leave:function(a,b){a.remove(),b()}};if(a.noanimation)return e;if(j)return{enter:function(a,c,f){d(a)?b.version.minor>2?j.enter(a,null,c).then(f):j.enter(a,null,c,f):e.enter(a,c,f)},leave:function(a,c){d(a)?b.version.minor>2?j.leave(a).then(c):j.leave(a,c):e.leave(a,c)}};if(i){var f=i&&i(c,a);return{enter:function(a,b,c){f.enter(a,null,b),c()},leave:function(a,b){f.leave(a),b()}}}return e}var h=f(),i=h("$animator"),j=h("$animate"),k={restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(c,f,h){return function(c,f,i){function j(){function a(){b&&b.remove(),c&&c.$destroy()}var b=l,c=n;c&&(c._willBeDestroyed=!0),m?(r.leave(m,function(){a(),l=null}),l=m):(a(),l=null),m=null,n=null}function k(g){var k,l=A(c,i,f,e),s=l&&a.$current&&a.$current.locals[l];if((g||s!==o)&&!c._willBeDestroyed){k=c.$new(),o=a.$current.locals[l],k.$emit("$viewContentLoading",l);var t=h(k,function(a){r.enter(a,f,function(){n&&n.$emit("$viewContentAnimationEnded"),(b.isDefined(q)&&!q||c.$eval(q))&&d(a)}),j()});m=t,n=k,n.$emit("$viewContentLoaded",l),n.$eval(p)}}var l,m,n,o,p=i.onload||"",q=i.autoscroll,r=g(i,c);c.$on("$stateChangeSuccess",function(){k(!1)}),k(!0)}}};return k}function z(a,b,c,d){return{restrict:"ECA",priority:-400,compile:function(e){var f=e.html();return function(e,g,h){var i=c.$current,j=A(e,h,g,d),k=i&&i.locals[j];if(k){g.data("$uiView",{name:j,state:k.$$state}),g.html(k.$template?k.$template:f);var l=a(g.contents());if(k.$$controller){k.$scope=e,k.$element=g;var m=b(k.$$controller,k);k.$$controllerAs&&(e[k.$$controllerAs]=m),g.data("$ngControllerController",m),g.children().data("$ngControllerController",m)}l(e)}}}}}function A(a,b,c,d){var e=d(b.uiView||b.name||"")(a),f=c.inheritedData("$uiView");return e.indexOf("@")>=0?e:e+"@"+(f?f.state.name:"")}function B(a,b){var c,d=a.match(/^\s*({[^}]*})\s*$/);if(d&&(a=b+"("+d[1]+")"),c=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/),!c||4!==c.length)throw new Error("Invalid state ref '"+a+"'");return{state:c[1],paramExpr:c[3]||null}}function C(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function D(a){var b="[object SVGAnimatedString]"===Object.prototype.toString.call(a.prop("href")),c="FORM"===a[0].nodeName;return{attr:c?"action":b?"xlink:href":"href",isAnchor:"A"===a.prop("tagName").toUpperCase(),clickable:!c}}function E(a,b,c,d,e){return function(f){var g=f.which||f.button,h=e();if(!(g>1||f.ctrlKey||f.metaKey||f.shiftKey||a.attr("target"))){var i=c(function(){b.go(h.state,h.params,h.options)});f.preventDefault();var j=d.isAnchor&&!h.href?1:0;f.preventDefault=function(){j--<=0&&c.cancel(i)}}}}function F(a,b){return{relative:C(a)||b.$current,inherit:!0}}function G(a,c){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(d,e,f,g){var h=B(f.uiSref,a.current.name),i={state:h.state,href:null,params:null},j=D(e),k=g[1]||g[0];i.options=R(F(e,a),f.uiSrefOpts?d.$eval(f.uiSrefOpts):{});var l=function(c){c&&(i.params=b.copy(c)),i.href=a.href(h.state,i.params,i.options),k&&k.$$addStateInfo(h.state,i.params),null!==i.href&&f.$set(j.attr,i.href)};h.paramExpr&&(d.$watch(h.paramExpr,function(a){a!==i.params&&l(a)},!0),i.params=b.copy(d.$eval(h.paramExpr))),l(),j.clickable&&e.bind("click",E(e,a,c,j,function(){return i}))}}}function H(a,b){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(c,d,e,f){function g(b){l.state=b[0],l.params=b[1],l.options=b[2],l.href=a.href(l.state,l.params,l.options),i&&i.$$addStateInfo(l.state,l.params),l.href&&e.$set(h.attr,l.href)}var h=D(d),i=f[1]||f[0],j=[e.uiState,e.uiStateParams||null,e.uiStateOpts||null],k="["+j.map(function(a){return a||"null"}).join(", ")+"]",l={state:null,params:null,options:null,href:null};c.$watch(k,g,!0),g(c.$eval(k)),h.clickable&&d.bind("click",E(d,a,b,h,function(){return l}))}}}function I(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs","$timeout",function(b,d,e,f){function g(b,c,e){var f=a.get(b,C(d)),g=h(b,c);p.push({state:f||{name:b},params:c,hash:g}),q[g]=e}function h(a,c){if(!N(a))throw new Error("state should be a string");return O(c)?a+T(c):(c=b.$eval(c),O(c)?a+T(c):a)}function i(){for(var a=0;a0||(g(a,b,o),i())},b.$on("$stateChangeSuccess",i),i()}]}}function J(a){var b=function(b,c){return a.is(b,c)};return b.$stateful=!0,b}function K(a){var b=function(b,c,d){return a.includes(b,c,d)};return b.$stateful=!0,b}var L=b.isDefined,M=b.isFunction,N=b.isString,O=b.isObject,P=b.isArray,Q=b.forEach,R=b.extend,S=b.copy,T=b.toJson;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),p.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",p),q.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",q);var U;r.prototype.concat=function(a,b){var c={caseInsensitive:U.caseInsensitive(),strict:U.strictMode(),squash:U.defaultSquashPolicy()};return new r(this.sourcePath+a+this.sourceSearch,R(c,b),this)},r.prototype.toString=function(){return this.source},r.prototype.exec=function(a,b){function c(a){function b(a){return a.split("").reverse().join("")}function c(a){return a.replace(/\\-/g,"-")}var d=b(a).split(/-(?!\\)/),e=o(d,b);return o(e,c).reverse()}var d=this.regexp.exec(a);if(!d)return null;b=b||{};var e,f,g,h=this.parameters(),i=h.length,j=this.segments.length-1,k={};if(j!==d.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");var l,m;for(e=0;j>e;e++){for(g=h[e],l=this.params[g],m=d[e+1],f=0;fe;e++){for(g=h[e],k[g]=this.params[g].value(b[g]),l=this.params[g],m=b[g],f=0;ff;f++){var k=h>f,l=d[f],m=e[l],n=m.value(a[l]),p=m.isOptional&&m.type.equals(m.value(),n),q=!!p&&m.squash,r=m.type.encode(n);if(k){var s=c[f+1],t=f+1===h;if(q===!1)null!=r&&(j+=P(r)?o(r,b).join("-"):encodeURIComponent(r)),j+=s;else if(q===!0){var u=j.match(/\/$/)?/\/?(.*)/:/(.*)/;j+=s.match(u)[1]}else N(q)&&(j+=q+s);t&&m.squash===!0&&"/"===j.slice(-1)&&(j=j.slice(0,-1))}else{if(null==r||p&&q!==!1)continue;if(P(r)||(r=[r]),0===r.length)continue;r=o(r,encodeURIComponent).join("&"+l+"="),j+=(g?"&":"?")+(l+"="+r),g=!0}}return j},s.prototype.is=function(a,b){return!0},s.prototype.encode=function(a,b){return a},s.prototype.decode=function(a,b){return a},s.prototype.equals=function(a,b){return a==b},s.prototype.$subPattern=function(){var a=this.pattern.toString();return a.substr(1,a.length-2)},s.prototype.pattern=/.*/,s.prototype.toString=function(){return"{Type:"+this.name+"}"},s.prototype.$normalize=function(a){return this.is(a)?a:this.decode(a)},s.prototype.$asArray=function(a,b){function d(a,b){function d(a,b){return function(){return a[b].apply(a,arguments)}}function e(a){return P(a)?a:L(a)?[a]:[]}function f(a){switch(a.length){case 0:return c;case 1:return"auto"===b?a[0]:a;default:return a}}function g(a){return!a}function h(a,b){return function(c){if(P(c)&&0===c.length)return c;c=e(c);var d=o(c,a);return b===!0?0===n(d,g).length:f(d)}}function i(a){return function(b,c){var d=e(b),f=e(c);if(d.length!==f.length)return!1;for(var g=0;g1&&(b.$element.data(q,b.direction),m.currentSlide&&m.currentSlide.$element&&m.currentSlide.$element.data(q,b.direction),a.$currentTransition=!0,o?d.on("addClass",b.$element,function(b,c){"close"===c&&(a.$currentTransition=null,d.off("addClass",b))}):b.$element.one("$animate:close",function(){a.$currentTransition=null})),m.currentSlide=b,r=c,g())}function f(a){if(angular.isUndefined(n[a].index))return n[a];var b;n.length;for(b=0;b0&&(k=c(i,b))}function h(){k&&(c.cancel(k),k=null)}function i(){var b=+a.interval;l&&!isNaN(b)&&b>0&&n.length?a.next():a.pause()}function j(b){b.length||(a.$currentTransition=null)}var k,l,m=this,n=m.slides=a.slides=[],o=angular.version.minor>=4,p="uib-noTransition",q="uib-slideDirection",r=-1;m.currentSlide=null;var s=!1;m.select=a.select=function(b,c){var d=a.indexOfSlide(b);void 0===c&&(c=d>m.getCurrentIndex()?"next":"prev"),b&&b!==m.currentSlide&&!a.$currentTransition&&e(b,d,c)},a.$on("$destroy",function(){s=!0}),m.getCurrentIndex=function(){return m.currentSlide&&angular.isDefined(m.currentSlide.index)?+m.currentSlide.index:r},a.indexOfSlide=function(a){return angular.isDefined(a.index)?+a.index:n.indexOf(a)},a.next=function(){var b=(m.getCurrentIndex()+1)%n.length;return 0===b&&a.noWrap()?void a.pause():m.select(f(b),"next")},a.prev=function(){var b=m.getCurrentIndex()-1<0?n.length-1:m.getCurrentIndex()-1;return a.noWrap()&&b===n.length-1?void a.pause():m.select(f(b),"prev")},a.isActive=function(a){return m.currentSlide===a},a.$watch("interval",g),a.$watchCollection("slides",j),a.$on("$destroy",h),a.play=function(){l||(l=!0,g())},a.pause=function(){a.noPause||(l=!1,h())},m.addSlide=function(b,c){b.$element=c,n.push(b),1===n.length||b.active?(m.select(n[n.length-1]),1===n.length&&a.play()):b.active=!1},m.removeSlide=function(a){angular.isDefined(a.index)&&n.sort(function(a,b){return+a.index>+b.index});var b=n.indexOf(a);n.splice(b,1),n.length>0&&a.active?b>=n.length?m.select(n[b-1]):m.select(n[b]):r>b&&r--,0===n.length&&(m.currentSlide=null)},a.$watch("noTransition",function(a){b.data(p,a)})}]).directive("uibCarousel",[function(){return{transclude:!0,replace:!0,controller:"UibCarouselController",controllerAs:"carousel",require:"carousel",templateUrl:function(a,b){return b.templateUrl||"template/carousel/carousel.html"},scope:{interval:"=",noTransition:"=",noPause:"=",noWrap:"&"}}}]).directive("uibSlide",function(){return{require:"^uibCarousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/carousel/slide.html"},scope:{active:"=?",actual:"=?",index:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}).animation(".item",["$injector","$animate",function(a,b){function c(a,b,c){a.removeClass(b),c&&c()}var d="uib-noTransition",e="uib-slideDirection",f=null;return a.has("$animateCss")&&(f=a.get("$animateCss")),{beforeAddClass:function(a,g,h){if("active"==g&&a.parent()&&a.parent().parent()&&!a.parent().parent().data(d)){var i=!1,j=a.data(e),k="next"==j?"left":"right",l=c.bind(this,a,k+" "+j,h);return a.addClass(j),f?f(a,{addClass:k}).start().done(l):b.addClass(a,k).then(function(){i||l(),h()}),function(){i=!0}}h()},beforeRemoveClass:function(a,g,h){if("active"===g&&a.parent()&&a.parent().parent()&&!a.parent().parent().data(d)){var i=!1,j=a.data(e),k="next"==j?"left":"right",l=c.bind(this,a,k,h);return f?f(a,{addClass:k}).start().done(l):b.addClass(a,k).then(function(){i||l(),h()}),function(){i=!0}}h()}}}]),angular.module("ui.bootstrap.carousel").value("$carouselSuppressWarning",!1).controller("CarouselController",["$scope","$element","$controller","$log","$carouselSuppressWarning",function(a,b,c,d,e){e||d.warn("CarouselController is now deprecated. Use UibCarouselController instead."),angular.extend(this,c("UibCarouselController",{$scope:a,$element:b}))}]).directive("carousel",["$log","$carouselSuppressWarning",function(a,b){return{transclude:!0,replace:!0,controller:"CarouselController",controllerAs:"carousel",require:"carousel",templateUrl:function(a,b){return b.templateUrl||"template/carousel/carousel.html"},scope:{interval:"=",noTransition:"=",noPause:"=",noWrap:"&"},link:function(){b||a.warn("carousel is now deprecated. Use uib-carousel instead.")}}}]).directive("slide",["$log","$carouselSuppressWarning",function(a,b){return{require:"^carousel",transclude:!0,replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/carousel/slide.html"},scope:{active:"=?",actual:"=?",index:"=?"},link:function(c,d,e,f){b||a.warn("slide is now deprecated. Use uib-slide instead."),f.addSlide(c,d),c.$on("$destroy",function(){f.removeSlide(c)}),c.$watch("active",function(a){a&&f.select(c)})}}}]),angular.module("ui.bootstrap.dateparser",[]).service("uibDateParser",["$log","$locale","orderByFilter",function(a,b,c){function d(a){var b=[],d=a.split("");return angular.forEach(g,function(c,e){var f=a.indexOf(e);if(f>-1){a=a.split(""),d[f]="("+c.regex+")",a[f]="$";for(var g=f+1,h=f+e.length;g28?29===c&&(a%4===0&&a%100!==0||a%400===0):3!==b&&5!==b&&8!==b&&10!==b||c<31)}var f,g,h=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;this.init=function(){f=b.id,this.parsers={},g={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:b.DATETIME_FORMATS.MONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.MONTH.indexOf(a)}},MMM:{regex:b.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.SHORTMONTH.indexOf(a)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:b.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:b.DATETIME_FORMATS.SHORTDAY.join("|")},HH:{regex:"(?:0|1)[0-9]|2[0-3]",apply:function(a){this.hours=+a}},hh:{regex:"0[0-9]|1[0-2]",apply:function(a){this.hours=+a}},H:{regex:"1?[0-9]|2[0-3]",apply:function(a){this.hours=+a}},h:{regex:"[0-9]|1[0-2]",apply:function(a){this.hours=+a}},mm:{regex:"[0-5][0-9]",apply:function(a){this.minutes=+a}},m:{regex:"[0-9]|[1-5][0-9]",apply:function(a){this.minutes=+a}},sss:{regex:"[0-9][0-9][0-9]",apply:function(a){this.milliseconds=+a}},ss:{regex:"[0-5][0-9]",apply:function(a){ -this.seconds=+a}},s:{regex:"[0-9]|[1-5][0-9]",apply:function(a){this.seconds=+a}},a:{regex:b.DATETIME_FORMATS.AMPMS.join("|"),apply:function(a){12===this.hours&&(this.hours=0),"PM"===a&&(this.hours+=12)}}}},this.init(),this.parse=function(c,g,i){if(!angular.isString(c)||!g)return c;g=b.DATETIME_FORMATS[g]||g,g=g.replace(h,"\\$&"),b.id!==f&&this.init(),this.parsers[g]||(this.parsers[g]=d(g));var j=this.parsers[g],k=j.regex,l=j.map,m=c.match(k);if(m&&m.length){var n,o;angular.isDate(i)&&!isNaN(i.getTime())?n={year:i.getFullYear(),month:i.getMonth(),date:i.getDate(),hours:i.getHours(),minutes:i.getMinutes(),seconds:i.getSeconds(),milliseconds:i.getMilliseconds()}:(i&&a.warn("dateparser:","baseDate is not a valid date"),n={year:1900,month:0,date:1,hours:0,minutes:0,seconds:0,milliseconds:0});for(var p=1,q=m.length;pi.modes.indexOf(i[d]))&&(a.datepickerMode=i[d])}):(i[d]=g[d]||null,a[d]=i[d])}),a.datepickerMode=a.datepickerMode||g.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),angular.isDefined(b.initDate)?(this.activeDate=a.$parent.$eval(b.initDate)||new Date,a.$parent.$watch(b.initDate,function(a){a&&(j.$isEmpty(j.$modelValue)||j.$invalid)&&(i.activeDate=a,i.refreshView())})):this.activeDate=new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)&&(a.activeDateId=b.uid,!0)},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$viewValue){var a=new Date(j.$viewValue),b=!isNaN(a);b?this.activeDate=a:h||e.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$viewValue?new Date(j.$viewValue):null;j.$setValidity("dateDisabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$viewValue?new Date(j.$viewValue):null;return{date:a,label:f(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date),customClass:this.customClass(a)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$viewValue?new Date(j.$viewValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&b===-1||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){i.element[0].focus()};a.$on("uib:datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),i.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate)}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):a.toggleMode("up"===c?1:-1)}}]).controller("UibDaypickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?f[b]:29}function e(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}var f=[31,28,31,30,31,30,31,31,30,31,30,31];this.step={months:1},this.element=b,this.init=function(b){angular.extend(b,this),a.showWeeks=b.showWeeks,b.refreshView()},this.getDates=function(a,b){for(var c,d=new Array(b),e=new Date(a),f=0;f0?7-g:-g,i=new Date(f);h>0&&i.setDate(-h+1);for(var j=this.getDates(i,42),k=0;k<42;k++)j[k]=angular.extend(this.createDateObject(j[k],this.formatDay),{secondary:j[k].getMonth()!==d,uid:a.uniqueId+"-"+k});a.labels=new Array(7);for(var l=0;l<7;l++)a.labels[l]={abbr:c(j[l].date,this.formatDayHeader),full:c(j[l].date,"EEEE")};if(a.title=c(this.activeDate,this.formatDayTitle),a.rows=this.split(j,7),a.showWeeks){a.weekNumbers=[];for(var m=(11-this.startingDay)%7,n=a.rows.length,o=0;o
    "),x.attr({"ng-model":"date","ng-change":"dateSelection(date)","template-url":v}),y=angular.element(x.children()[0]),y.attr("template-url",w),C&&"month"===c.type&&(y.attr("datepicker-mode",'"month"'),y.attr("min-mode","month")),c.datepickerOptions){var l=a.$parent.$eval(c.datepickerOptions);l&&l.initDate&&(a.initDate=l.initDate,y.attr("init-date","initDate"),delete l.initDate),angular.forEach(l,function(a,b){y.attr(m(b),a)})}angular.forEach(["minMode","maxMode","minDate","maxDate","datepickerMode","initDate","shortcutPropagation"],function(b){if(c[b]){var d=e(c[b]);if(a.$parent.$watch(d,function(c){a.watchData[b]=c,"minDate"!==b&&"maxDate"!==b||(B[b]=new Date(c))}),y.attr(m(b),"watchData."+b),"datepickerMode"===b){var f=d.assign;a.$watch("watchData."+b,function(b,c){angular.isFunction(f)&&b!==c&&f(a.$parent,b)})}}}),c.dateDisabled&&y.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),c.showWeeks&&y.attr("show-weeks",c.showWeeks),c.customClass&&y.attr("custom-class","customClass({ date: date, mode: mode })"),C?z.$formatters.push(function(b){return a.date=b,b}):(z.$$parserName="date",z.$validators.date=o,z.$parsers.unshift(n),z.$formatters.push(function(b){return a.date=b,z.$isEmpty(b)?b:i(b,r)})),z.$viewChangeListeners.push(function(){a.date=j.parse(z.$viewValue,r,a.date)}),b.bind("keydown",q),A=d(x)(a),x.remove(),t?f.find("body").append(A):b.after(A),a.$on("$destroy",function(){a.isOpen===!0&&(g.$$phase||a.$apply(function(){a.isOpen=!1})),A.remove(),b.unbind("keydown",q),f.unbind("click",p)})},a.getText=function(b){return a[b+"Text"]||k[b+"Text"]},a.isDisabled=function(b){return"today"===b&&(b=new Date),a.watchData.minDate&&a.compare(b,B.minDate)<0||a.watchData.maxDate&&a.compare(b,B.maxDate)>0},a.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},a.dateSelection=function(c){angular.isDefined(c)&&(a.date=c);var d=a.date?i(a.date,r):null;b.val(d),z.$setViewValue(d),s&&(a.isOpen=!1,b[0].focus())},a.keydown=function(c){27===c.which&&(a.isOpen=!1,b[0].focus())},a.select=function(b){if("today"===b){var c=new Date;angular.isDate(a.date)?(b=new Date(a.date),b.setFullYear(c.getFullYear(),c.getMonth(),c.getDate())):b=new Date(c.setHours(0,0,0,0))}a.dateSelection(b)},a.close=function(){a.isOpen=!1,b[0].focus()},a.$watch("isOpen",function(c){c?(a.position=t?h.offset(b):h.position(b),a.position.top=a.position.top+b.prop("offsetHeight"),l(function(){u&&a.$broadcast("uib:datepicker.focus"),f.bind("click",p)},0,!1)):f.unbind("click",p)})}]).directive("uibDatepickerPopup",function(){return{require:["ngModel","uibDatepickerPopup"],controller:"UibDatepickerPopupController",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&",customClass:"&"},link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibDatepickerPopupWrap",function(){return{replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/popup.html"}}}),angular.module("ui.bootstrap.datepicker").value("$datepickerSuppressWarning",!1).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$log","dateFilter","uibDatepickerConfig","$datepickerSuppressError","$datepickerSuppressWarning",function(a,b,c,d,e,f,g,h,i){i||e.warn("DatepickerController is now deprecated. Use UibDatepickerController instead.");var j=this,k={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","showWeeks","startingDay","yearRange","shortcutPropagation"],function(c,e){j[c]=angular.isDefined(b[c])?e<6?d(b[c])(a.$parent):a.$parent.$eval(b[c]):g[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){j[d]=a?new Date(a):null,j.refreshView()}):j[d]=g[d]?new Date(g[d]):null}),angular.forEach(["minMode","maxMode"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(c){j[d]=angular.isDefined(c)?c:b[d],a[d]=j[d],("minMode"==d&&j.modes.indexOf(a.datepickerMode)j.modes.indexOf(j[d]))&&(a.datepickerMode=j[d])}):(j[d]=g[d]||null,a[d]=j[d])}),a.datepickerMode=a.datepickerMode||g.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),angular.isDefined(b.initDate)?(this.activeDate=a.$parent.$eval(b.initDate)||new Date,a.$parent.$watch(b.initDate,function(a){a&&(k.$isEmpty(k.$modelValue)||k.$invalid)&&(j.activeDate=a,j.refreshView())})):this.activeDate=new Date,a.isActive=function(b){return 0===j.compare(b.date,j.activeDate)&&(a.activeDateId=b.uid,!0)},this.init=function(a){k=a,k.$render=function(){j.render()}},this.render=function(){if(k.$viewValue){var a=new Date(k.$viewValue),b=!isNaN(a);b?this.activeDate=a:h||e.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=k.$viewValue?new Date(k.$viewValue):null;k.$setValidity("dateDisabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=k.$viewValue?new Date(k.$viewValue):null;return{date:a,label:f(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date),customClass:this.customClass(a)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},this.fixTimeZone=function(a){var b=a.getHours();a.setHours(23===b?b+2:0)},a.select=function(b){if(a.datepickerMode===j.minMode){var c=k.$viewValue?new Date(k.$viewValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),k.$setViewValue(c),k.$render()}else j.activeDate=b,a.datepickerMode=j.modes[j.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=j.activeDate.getFullYear()+a*(j.step.years||0),c=j.activeDate.getMonth()+a*(j.step.months||0);j.activeDate.setFullYear(b,c,1),j.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===j.maxMode&&1===b||a.datepickerMode===j.minMode&&b===-1||(a.datepickerMode=j.modes[j.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var l=function(){j.element[0].focus()};a.$on("uib:datepicker.focus",l),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),j.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(j.isDisabled(j.activeDate))return;a.select(j.activeDate)}else!b.ctrlKey||"up"!==c&&"down"!==c?(j.handleKeyDown(c,b),j.refreshView()):a.toggleMode("up"===c?1:-1)}}]).directive("datepicker",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/datepicker.html"},scope:{datepickerMode:"=?",dateDisabled:"&",customClass:"&",shortcutPropagation:"&?"},require:["datepicker","^ngModel"],controller:"DatepickerController",controllerAs:"datepicker",link:function(c,d,e,f){b||a.warn("datepicker is now deprecated. Use uib-datepicker instead.");var g=f[0],h=f[1];g.init(h)}}}]).directive("daypicker",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,templateUrl:"template/datepicker/day.html",require:["^datepicker","daypicker"],controller:"UibDaypickerController",link:function(c,d,e,f){b||a.warn("daypicker is now deprecated. Use uib-daypicker instead.");var g=f[0],h=f[1];h.init(g)}}}]).directive("monthpicker",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,templateUrl:"template/datepicker/month.html",require:["^datepicker","monthpicker"],controller:"UibMonthpickerController",link:function(c,d,e,f){b||a.warn("monthpicker is now deprecated. Use uib-monthpicker instead.");var g=f[0],h=f[1];h.init(g)}}}]).directive("yearpicker",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,templateUrl:"template/datepicker/year.html",require:["^datepicker","yearpicker"],controller:"UibYearpickerController",link:function(c,d,e,f){b||a.warn("yearpicker is now deprecated. Use uib-yearpicker instead.");var g=f[0];angular.extend(g,f[1]),g.yearpickerInit(),g.refreshView()}}}]).directive("datepickerPopup",["$log","$datepickerSuppressWarning",function(a,b){return{require:["ngModel","datepickerPopup"],controller:"UibDatepickerPopupController",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&",customClass:"&"},link:function(c,d,e,f){b||a.warn("datepicker-popup is now deprecated. Use uib-datepicker-popup instead.");var g=f[0],h=f[1];h.init(g)}}}]).directive("datepickerPopupWrap",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/popup.html"},link:function(){b||a.warn("datepicker-popup-wrap is now deprecated. Use uib-datepicker-popup-wrap instead.")}}}]),angular.module("ui.bootstrap.dropdown",["ui.bootstrap.position"]).constant("uibDropdownConfig",{openClass:"open"}).service("uibDropdownService",["$document","$rootScope",function(a,b){var c=null;this.open=function(b){c||(a.bind("click",d),a.bind("keydown",e)),c&&c!==b&&(c.isOpen=!1),c=b},this.close=function(b){c===b&&(c=null,a.unbind("click",d),a.unbind("keydown",e))};var d=function(a){if(c&&(!a||"disabled"!==c.getAutoClose())){var d=c.getToggleElement();if(!(a&&d&&d[0].contains(a.target))){var e=c.getDropdownElement();a&&"outsideClick"===c.getAutoClose()&&e&&e[0].contains(a.target)||(c.isOpen=!1,b.$$phase||c.$apply())}}},e=function(a){27===a.which?(c.focusToggleElement(),d()):c.isKeynavEnabled()&&/(38|40)/.test(a.which)&&c.isOpen&&(a.preventDefault(),a.stopPropagation(),c.focusDropdownEntry(a.which))}}]).controller("UibDropdownController",["$scope","$element","$attrs","$parse","uibDropdownConfig","uibDropdownService","$animate","$uibPosition","$document","$compile","$templateRequest",function(a,b,c,d,e,f,g,h,i,j,k){var l,m,n=this,o=a.$new(),p=e.openClass,q=angular.noop,r=c.onToggle?d(c.onToggle):angular.noop,s=!1,t=!1;b.addClass("dropdown"),this.init=function(){c.isOpen&&(m=d(c.isOpen),q=m.assign,a.$watch(m,function(a){o.isOpen=!!a})),s=angular.isDefined(c.dropdownAppendToBody),t=angular.isDefined(c.uibKeyboardNav),s&&n.dropdownMenu&&(i.find("body").append(n.dropdownMenu),b.on("$destroy",function(){n.dropdownMenu.remove()}))},this.toggle=function(a){return o.isOpen=arguments.length?!!a:!o.isOpen},this.isOpen=function(){return o.isOpen},o.getToggleElement=function(){return n.toggleElement},o.getAutoClose=function(){return c.autoClose||"always"},o.getElement=function(){return b},o.isKeynavEnabled=function(){return t},o.focusDropdownEntry=function(a){var c=n.dropdownMenu?angular.element(n.dropdownMenu).find("a"):angular.element(b).find("ul").eq(0).find("a");switch(a){case 40:angular.isNumber(n.selectedOption)?n.selectedOption=n.selectedOption===c.length-1?n.selectedOption:n.selectedOption+1:n.selectedOption=0;break;case 38:angular.isNumber(n.selectedOption)?n.selectedOption=0===n.selectedOption?0:n.selectedOption-1:n.selectedOption=c.length-1}c[n.selectedOption].focus()},o.getDropdownElement=function(){return n.dropdownMenu},o.focusToggleElement=function(){n.toggleElement&&n.toggleElement[0].focus()},o.$watch("isOpen",function(c,d){if(s&&n.dropdownMenu){var e=h.positionElements(b,n.dropdownMenu,"bottom-left",!0),i={top:e.top+"px",display:c?"block":"none"},m=n.dropdownMenu.hasClass("dropdown-menu-right");m?(i.left="auto",i.right=window.innerWidth-(e.left+b.prop("offsetWidth"))+"px"):(i.left=e.left+"px",i.right="auto"),n.dropdownMenu.css(i)}if(g[c?"addClass":"removeClass"](b,p).then(function(){angular.isDefined(c)&&c!==d&&r(a,{open:!!c})}),c)n.dropdownMenuTemplateUrl&&k(n.dropdownMenuTemplateUrl).then(function(a){l=o.$new(),j(a.trim())(l,function(a){var b=a;n.dropdownMenu.replaceWith(b),n.dropdownMenu=b})}),o.focusToggleElement(),f.open(o);else{if(n.dropdownMenuTemplateUrl){l&&l.$destroy();var t=angular.element('');n.dropdownMenu.replaceWith(t),n.dropdownMenu=t}f.close(o),n.selectedOption=null}angular.isFunction(q)&&q(a,c)}),a.$on("$locationChangeSuccess",function(){"disabled"!==o.getAutoClose()&&(o.isOpen=!1)});var u=a.$on("$destroy",function(){o.$destroy()});o.$on("$destroy",u)}]).directive("uibDropdown",function(){return{controller:"UibDropdownController",link:function(a,b,c,d){d.init()}}}).directive("uibDropdownMenu",function(){return{restrict:"AC",require:"?^uibDropdown",link:function(a,b,c,d){if(d&&!angular.isDefined(c.dropdownNested)){b.addClass("dropdown-menu");var e=c.templateUrl;e&&(d.dropdownMenuTemplateUrl=e),d.dropdownMenu||(d.dropdownMenu=b)}}}}).directive("uibKeyboardNav",function(){return{restrict:"A",require:"?^uibDropdown",link:function(a,b,c,d){b.bind("keydown",function(a){if([38,40].indexOf(a.which)!==-1){a.preventDefault(),a.stopPropagation();var b=d.dropdownMenu.find("a");switch(a.which){case 40:angular.isNumber(d.selectedOption)?d.selectedOption=d.selectedOption===b.length-1?d.selectedOption:d.selectedOption+1:d.selectedOption=0;break;case 38:angular.isNumber(d.selectedOption)?d.selectedOption=0===d.selectedOption?0:d.selectedOption-1:d.selectedOption=b.length-1}b[d.selectedOption].focus()}})}}}).directive("uibDropdownToggle",function(){return{require:"?^uibDropdown",link:function(a,b,c,d){if(d){b.addClass("dropdown-toggle"),d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.dropdown").value("$dropdownSuppressWarning",!1).service("dropdownService",["$log","$dropdownSuppressWarning","uibDropdownService",function(a,b,c){b||a.warn("dropdownService is now deprecated. Use uibDropdownService instead."),angular.extend(this,c)}]).controller("DropdownController",["$scope","$element","$attrs","$parse","uibDropdownConfig","uibDropdownService","$animate","$uibPosition","$document","$compile","$templateRequest","$log","$dropdownSuppressWarning",function(a,b,c,d,e,f,g,h,i,j,k,l,m){m||l.warn("DropdownController is now deprecated. Use UibDropdownController instead.");var n,o,p=this,q=a.$new(),r=e.openClass,s=angular.noop,t=c.onToggle?d(c.onToggle):angular.noop,u=!1,v=!1;b.addClass("dropdown"),this.init=function(){c.isOpen&&(o=d(c.isOpen),s=o.assign,a.$watch(o,function(a){q.isOpen=!!a})),u=angular.isDefined(c.dropdownAppendToBody),v=angular.isDefined(c.uibKeyboardNav),u&&p.dropdownMenu&&(i.find("body").append(p.dropdownMenu),b.on("$destroy",function(){p.dropdownMenu.remove()}))},this.toggle=function(a){return q.isOpen=arguments.length?!!a:!q.isOpen},this.isOpen=function(){return q.isOpen},q.getToggleElement=function(){return p.toggleElement},q.getAutoClose=function(){return c.autoClose||"always"},q.getElement=function(){return b},q.isKeynavEnabled=function(){return v},q.focusDropdownEntry=function(a){var c=p.dropdownMenu?angular.element(p.dropdownMenu).find("a"):angular.element(b).find("ul").eq(0).find("a");switch(a){case 40:angular.isNumber(p.selectedOption)?p.selectedOption=p.selectedOption===c.length-1?p.selectedOption:p.selectedOption+1:p.selectedOption=0;break;case 38:angular.isNumber(p.selectedOption)?p.selectedOption=0===p.selectedOption?0:p.selectedOption-1:p.selectedOption=c.length-1}c[p.selectedOption].focus()},q.getDropdownElement=function(){return p.dropdownMenu},q.focusToggleElement=function(){p.toggleElement&&p.toggleElement[0].focus()},q.$watch("isOpen",function(c,d){if(u&&p.dropdownMenu){var e=h.positionElements(b,p.dropdownMenu,"bottom-left",!0),i={top:e.top+"px",display:c?"block":"none"},l=p.dropdownMenu.hasClass("dropdown-menu-right");l?(i.left="auto",i.right=window.innerWidth-(e.left+b.prop("offsetWidth"))+"px"):(i.left=e.left+"px",i.right="auto"),p.dropdownMenu.css(i)}if(g[c?"addClass":"removeClass"](b,r).then(function(){angular.isDefined(c)&&c!==d&&t(a,{open:!!c})}),c)p.dropdownMenuTemplateUrl&&k(p.dropdownMenuTemplateUrl).then(function(a){n=q.$new(),j(a.trim())(n,function(a){var b=a;p.dropdownMenu.replaceWith(b),p.dropdownMenu=b})}),q.focusToggleElement(),f.open(q);else{if(p.dropdownMenuTemplateUrl){n&&n.$destroy();var m=angular.element('');p.dropdownMenu.replaceWith(m), -p.dropdownMenu=m}f.close(q),p.selectedOption=null}angular.isFunction(s)&&s(a,c)}),a.$on("$locationChangeSuccess",function(){"disabled"!==q.getAutoClose()&&(q.isOpen=!1)});var w=a.$on("$destroy",function(){q.$destroy()});q.$on("$destroy",w)}]).directive("dropdown",["$log","$dropdownSuppressWarning",function(a,b){return{controller:"DropdownController",link:function(c,d,e,f){b||a.warn("dropdown is now deprecated. Use uib-dropdown instead."),f.init()}}}]).directive("dropdownMenu",["$log","$dropdownSuppressWarning",function(a,b){return{restrict:"AC",require:"?^dropdown",link:function(c,d,e,f){if(f&&!angular.isDefined(e.dropdownNested)){b||a.warn("dropdown-menu is now deprecated. Use uib-dropdown-menu instead."),d.addClass("dropdown-menu");var g=e.templateUrl;g&&(f.dropdownMenuTemplateUrl=g),f.dropdownMenu||(f.dropdownMenu=d)}}}}]).directive("keyboardNav",["$log","$dropdownSuppressWarning",function(a,b){return{restrict:"A",require:"?^dropdown",link:function(c,d,e,f){b||a.warn("keyboard-nav is now deprecated. Use uib-keyboard-nav instead."),d.bind("keydown",function(a){if([38,40].indexOf(a.which)!==-1){a.preventDefault(),a.stopPropagation();var b=f.dropdownMenu.find("a");switch(a.which){case 40:angular.isNumber(f.selectedOption)?f.selectedOption=f.selectedOption===b.length-1?f.selectedOption:f.selectedOption+1:f.selectedOption=0;break;case 38:angular.isNumber(f.selectedOption)?f.selectedOption=0===f.selectedOption?0:f.selectedOption-1:f.selectedOption=b.length-1}b[f.selectedOption].focus()}})}}}]).directive("dropdownToggle",["$log","$dropdownSuppressWarning",function(a,b){return{require:"?^dropdown",link:function(c,d,e,f){if(b||a.warn("dropdown-toggle is now deprecated. Use uib-dropdown-toggle instead."),f){d.addClass("dropdown-toggle"),f.toggleElement=d;var g=function(a){a.preventDefault(),d.hasClass("disabled")||e.disabled||c.$apply(function(){f.toggle()})};d.bind("click",g),d.attr({"aria-haspopup":!0,"aria-expanded":!1}),c.$watch(f.isOpen,function(a){d.attr("aria-expanded",!!a)}),c.$on("$destroy",function(){d.unbind("click",g)})}}}}]),angular.module("ui.bootstrap.stackedMap",[]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c0&&(b=u.top().value,b.modalDomEl.toggleClass(b.windowTopClass||"",a))}function m(){if(q&&j()==-1){var a=r;n(q,r,function(){a=null}),q=void 0,r=void 0}}function n(b,c,d){function e(){e.done||(e.done=!0,p?p(b,{event:"leave"}).start().then(function(){b.remove()}):a.leave(b),c.$destroy(),d&&d())}var g,h=null,i=function(){return g||(g=f.defer(),h=g.promise),function(){g.resolve()}};return c.$broadcast(w.NOW_CLOSING_EVENT,i),f.when(h).then(e)}function o(a,b,c){return!a.value.modalScope.$broadcast("modal.closing",b,c).defaultPrevented}var p=null;g.has("$animateCss")&&(p=g.get("$animateCss"));var q,r,s,t="modal-open",u=i.createNew(),v=h.createNew(),w={NOW_CLOSING_EVENT:"modal.stack.now-closing"},x=0,y="a[href], area[href], input:not([disabled]), button:not([disabled]),select:not([disabled]), textarea:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable=true]";return e.$watch(j,function(a){r&&(r.index=a)}),c.bind("keydown",function(a){if(a.isDefaultPrevented())return a;var b=u.top();if(b&&b.value.keyboard)switch(a.which){case 27:a.preventDefault(),e.$apply(function(){w.dismiss(b.key,"escape key press")});break;case 9:w.loadFocusElementList(b);var c=!1;a.shiftKey?w.isFocusInFirstItem(a)&&(c=w.focusLastFocusableElement()):w.isFocusInLastItem(a)&&(c=w.focusFirstFocusableElement()),c&&(a.preventDefault(),a.stopPropagation())}}),w.open=function(a,b){var f=c[0].activeElement,g=b.openedClass||t;l(!1),u.add(a,{deferred:b.deferred,renderDeferred:b.renderDeferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard,openedClass:b.openedClass,windowTopClass:b.windowTopClass}),v.put(g,a);var h=c.find("body").eq(0),i=j();if(i>=0&&!q){r=e.$new(!0),r.index=i;var k=angular.element('
    ');k.attr("backdrop-class",b.backdropClass),b.animation&&k.attr("modal-animation","true"),q=d(k)(r),h.append(q)}var m=angular.element('
    ');m.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,"window-top-class":b.windowTopClass,size:b.size,index:u.length()-1,animate:"animate"}).html(b.content),b.animation&&m.attr("modal-animation","true");var n=d(m)(b.scope);u.top().value.modalDomEl=n,u.top().value.modalOpener=f,h.append(n),h.addClass(g),w.clearFocusListCache()},w.close=function(a,b){var c=u.get(a);return c&&o(c,b,!0)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.resolve(b),k(a,c.value.modalOpener),!0):!c},w.dismiss=function(a,b){var c=u.get(a);return c&&o(c,b,!1)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.reject(b),k(a,c.value.modalOpener),!0):!c},w.dismissAll=function(a){for(var b=this.getTop();b&&this.dismiss(b.key,a);)b=this.getTop()},w.getTop=function(){return u.top()},w.modalRendered=function(a){var b=u.get(a);b&&b.value.renderDeferred.resolve()},w.focusFirstFocusableElement=function(){return s.length>0&&(s[0].focus(),!0)},w.focusLastFocusableElement=function(){return s.length>0&&(s[s.length-1].focus(),!0)},w.isFocusInFirstItem=function(a){return s.length>0&&(a.target||a.srcElement)==s[0]},w.isFocusInLastItem=function(a){return s.length>0&&(a.target||a.srcElement)==s[s.length-1]},w.clearFocusListCache=function(){s=[],x=0},w.loadFocusElementList=function(a){if((void 0===s||!s.length)&&a){var b=a.value.modalDomEl;b&&b.length&&(s=b[0].querySelectorAll(y))}},w}]).provider("$uibModal",function(){var a={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$templateRequest","$controller","$uibModalStack","$modalSuppressWarning","$log",function(b,c,d,e,f,g,h,i){function j(a){return a.template?d.when(a.template):e(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl)}function k(a){var c=[];return angular.forEach(a,function(a){angular.isFunction(a)||angular.isArray(a)?c.push(d.when(b.invoke(a))):angular.isString(a)?c.push(d.when(b.get(a))):c.push(d.when(a))}),c}var l={},m=null;return l.getPromiseChain=function(){return m},l.open=function(b){function e(){return r}var l=d.defer(),n=d.defer(),o=d.defer(),p={result:l.promise,opened:n.promise,rendered:o.promise,close:function(a){return g.close(p,a)},dismiss:function(a){return g.dismiss(p,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var q,r=d.all([j(b)].concat(k(b.resolve)));return q=m=d.all([m]).then(e,e).then(function(a){var d=(b.scope||c).$new();d.$close=p.close,d.$dismiss=p.dismiss,d.$on("$destroy",function(){d.$$uibDestructionScheduled||d.$dismiss("$uibUnscheduledDestruction")});var e,j={},k=1;b.controller&&(j.$scope=d,j.$uibModalInstance=p,Object.defineProperty(j,"$modalInstance",{get:function(){return h||i.warn("$modalInstance is now deprecated. Use $uibModalInstance instead."),p}}),angular.forEach(b.resolve,function(b,c){j[c]=a[k++]}),e=f(b.controller,j),b.controllerAs&&(b.bindToController&&angular.extend(e,d),d[b.controllerAs]=e)),g.open(p,{scope:d,deferred:l,renderDeferred:o,content:a[0],animation:b.animation,backdrop:b.backdrop,keyboard:b.keyboard,backdropClass:b.backdropClass,windowTopClass:b.windowTopClass,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size,openedClass:b.openedClass}),n.resolve(!0)},function(a){n.reject(a),l.reject(a)})["finally"](function(){m===q&&(m=null)}),p},l}]};return a}),angular.module("ui.bootstrap.modal").value("$modalSuppressWarning",!1).directive("modalBackdrop",["$animate","$injector","$modalStack","$log","$modalSuppressWarning",function(a,b,c,d,e){function f(b,f,h){e||d.warn("modal-backdrop is now deprecated. Use uib-modal-backdrop instead."),f.addClass("modal-backdrop"),h.modalInClass&&(g?g(f,{addClass:h.modalInClass}).start():a.addClass(f,h.modalInClass),b.$on(c.NOW_CLOSING_EVENT,function(b,c){var d=c();g?g(f,{removeClass:h.modalInClass}).start().then(d):a.removeClass(f,h.modalInClass).then(d)}))}var g=null;return b.has("$animateCss")&&(g=b.get("$animateCss")),{replace:!0,templateUrl:"template/modal/backdrop.html",compile:function(a,b){return a.addClass(b.backdropClass),f}}}]).directive("modalWindow",["$modalStack","$q","$animate","$injector","$log","$modalSuppressWarning",function(a,b,c,d,e,f){var g=null;return d.has("$animateCss")&&(g=d.get("$animateCss")),{scope:{index:"@"},replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/modal/window.html"},link:function(d,h,i){f||e.warn("modal-window is now deprecated. Use uib-modal-window instead."),h.addClass(i.windowClass||""),h.addClass(i.windowTopClass||""),d.size=i.size,d.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!==c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))},h.on("click",d.close),d.$isRendered=!0;var j=b.defer();i.$observe("modalRender",function(a){"true"==a&&j.resolve()}),j.promise.then(function(){var e=null;i.modalInClass&&(e=g?g(h,{addClass:i.modalInClass}).start():c.addClass(h,i.modalInClass),d.$on(a.NOW_CLOSING_EVENT,function(a,b){var d=b();g?g(h,{removeClass:i.modalInClass}).start().then(d):c.removeClass(h,i.modalInClass).then(d)})),b.when(e).then(function(){var a=h[0].querySelector("[autofocus]");a?a.focus():h[0].focus()});var f=a.getTop();f&&a.modalRendered(f.key)})}}}]).directive("modalAnimationClass",["$log","$modalSuppressWarning",function(a,b){return{compile:function(c,d){b||a.warn("modal-animation-class is now deprecated. Use uib-modal-animation-class instead."),d.modalAnimation&&c.addClass(d.modalAnimationClass)}}}]).directive("modalTransclude",["$log","$modalSuppressWarning",function(a,b){return{link:function(c,d,e,f,g){b||a.warn("modal-transclude is now deprecated. Use uib-modal-transclude instead."),g(c.$parent,function(a){d.empty(),d.append(a)})}}}]).service("$modalStack",["$animate","$timeout","$document","$compile","$rootScope","$q","$injector","$$multiMap","$$stackedMap","$uibModalStack","$log","$modalSuppressWarning",function(a,b,c,d,e,f,g,h,i,j,k,l){l||k.warn("$modalStack is now deprecated. Use $uibModalStack instead."),angular.extend(this,j)}]).provider("$modal",["$uibModalProvider",function(a){angular.extend(this,a),this.$get=["$injector","$log","$modalSuppressWarning",function(b,c,d){return d||c.warn("$modal is now deprecated. Use $uibModal instead."),b.invoke(a.$get)}]}]),angular.module("ui.bootstrap.pagination",[]).controller("UibPaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(g,h){e=g,this.config=h,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=h.itemsPerPage,a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b,c){c&&c.preventDefault();var d=!a.ngDisabled||!c;d&&a.page!==b&&b>0&&b<=a.totalPages&&(c&&c.target&&c.target.blur(),e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages}}]).constant("uibPaginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("uibPagination",["$parse","uibPaginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@",ngDisabled:"="},require:["uibPagination","?ngModel"],controller:"UibPaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"template/pagination/pagination.html"},replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&kb&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;h<=e;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(e0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("uibPagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("uibPager",["uibPagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@",ngDisabled:"="},require:["uibPager","?ngModel"],controller:"UibPaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"template/pagination/pager.html"},replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.pagination").value("$paginationSuppressWarning",!1).controller("PaginationController",["$scope","$attrs","$parse","$log","$paginationSuppressWarning",function(a,b,c,d,e){e||d.warn("PaginationController is now deprecated. Use UibPaginationController instead.");var f=this,g={$setViewValue:angular.noop},h=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(d,e){g=d,this.config=e,g.$render=function(){f.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){f.itemsPerPage=parseInt(b,10),a.totalPages=f.calculateTotalPages()}):this.itemsPerPage=e.itemsPerPage,a.$watch("totalItems",function(){a.totalPages=f.calculateTotalPages()}),a.$watch("totalPages",function(b){h(a.$parent,b),a.page>b?a.selectPage(b):g.$render()})},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(g.$viewValue,10)||1},a.selectPage=function(b,c){c&&c.preventDefault();var d=!a.ngDisabled||!c;d&&a.page!==b&&b>0&&b<=a.totalPages&&(c&&c.target&&c.target.blur(),g.$setViewValue(b),g.$render())},a.getText=function(b){return a[b+"Text"]||f.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages}}]).directive("pagination",["$parse","uibPaginationConfig","$log","$paginationSuppressWarning",function(a,b,c,d){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@",ngDisabled:"="},require:["pagination","?ngModel"],controller:"PaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"template/pagination/pagination.html"},replace:!0,link:function(e,f,g,h){function i(a,b,c){return{number:a,text:b,active:c}}function j(a,b){var c=[],d=1,e=b,f=angular.isDefined(m)&&mb&&(e=b,d=e-m+1)):(d=(Math.ceil(a/m)-1)*m+1,e=Math.min(d+m-1,b)));for(var g=d;g<=e;g++){var h=i(g,g,g===a);c.push(h)}if(f&&!n){if(d>1){var j=i(d-1,"...",!1);c.unshift(j)}if(e0&&e.page<=e.totalPages&&(e.pages=j(e.page,e.totalPages))}}}}}]).directive("pager",["uibPagerConfig","$log","$paginationSuppressWarning",function(a,b,c){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@",ngDisabled:"="},require:["pager","?ngModel"],controller:"PaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"template/pagination/pager.html"},replace:!0,link:function(d,e,f,g){c||b.warn("pager is now deprecated. Use uib-pager instead.");var h=g[0],i=g[1];i&&(d.align=angular.isDefined(f.align)?d.$parent.$eval(f.align):a.align,h.init(i,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.stackedMap"]).provider("$uibTooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0,popupCloseDelay:0,useContentExp:!1},c={mouseenter:"mouseleave",click:"click",focus:"blur",none:""},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$uibPosition","$interpolate","$rootScope","$parse","$$stackedMap",function(e,f,g,h,i,j,k,l,m){var n=m.createNew();return h.on("keypress",function(a){if(27===a.which){var b=n.top();b&&(b.value.close(),n.removeTop(),b=null)}}),function(e,k,m,o){function p(a){var b=(a||o.trigger||m).split(" "),d=b.map(function(a){return c[a]||a});return{show:b,hide:d}}o=angular.extend({},b,d,o);var q=a(e),r=j.startSymbol(),s=j.endSymbol(),t="
    ';return{compile:function(a,b){var c=f(t);return function(a,b,d,f){function j(){L.isOpen?q():m()}function m(){K&&!a.$eval(d[k+"Enable"])||(u(),x(),L.popupDelay?F||(F=g(r,L.popupDelay,!1)):r())}function q(){s(),L.popupCloseDelay?G||(G=g(t,L.popupCloseDelay,!1)):t()}function r(){return s(),u(),L.content?(v(),void L.$evalAsync(function(){L.isOpen=!0,y(!0),Q()})):angular.noop}function s(){F&&(g.cancel(F),F=null),H&&(g.cancel(H),H=null)}function t(){s(),u(),L&&L.$evalAsync(function(){L.isOpen=!1,y(!1),L.animation?E||(E=g(w,150,!1)):w()})}function u(){G&&(g.cancel(G),G=null),E&&(g.cancel(E),E=null)}function v(){C||(D=L.$new(),C=c(D,function(a){I?h.find("body").append(a):b.after(a)}),z())}function w(){A(),E=null,C&&(C.remove(),C=null),D&&(D.$destroy(),D=null)}function x(){L.title=d[k+"Title"],O?L.content=O(a):L.content=d[e],L.popupClass=d[k+"Class"],L.placement=angular.isDefined(d[k+"Placement"])?d[k+"Placement"]:o.placement;var b=parseInt(d[k+"PopupDelay"],10),c=parseInt(d[k+"PopupCloseDelay"],10);L.popupDelay=isNaN(b)?o.popupDelay:b,L.popupCloseDelay=isNaN(c)?o.popupCloseDelay:c}function y(b){N&&angular.isFunction(N.assign)&&N.assign(a,b)}function z(){P.length=0,O?(P.push(a.$watch(O,function(a){L.content=a,!a&&L.isOpen&&t()})),P.push(D.$watch(function(){M||(M=!0,D.$$postDigest(function(){M=!1,L&&L.isOpen&&Q()}))}))):P.push(d.$observe(e,function(a){L.content=a,!a&&L.isOpen?t():Q()})),P.push(d.$observe(k+"Title",function(a){L.title=a,L.isOpen&&Q()})),P.push(d.$observe(k+"Placement",function(a){L.placement=a?a:o.placement,L.isOpen&&Q()}))}function A(){P.length&&(angular.forEach(P,function(a){a()}),P.length=0)}function B(){var a=d[k+"Trigger"];R(),J=p(a),"none"!==J.show&&J.show.forEach(function(a,c){a===J.hide[c]?b[0].addEventListener(a,j):a&&(b[0].addEventListener(a,m),J.hide[c].split(" ").forEach(function(a){b[0].addEventListener(a,q)})),b.on("keypress",function(a){27===a.which&&q()})})}var C,D,E,F,G,H,I=!!angular.isDefined(o.appendToBody)&&o.appendToBody,J=p(void 0),K=angular.isDefined(d[k+"Enable"]),L=a.$new(!0),M=!1,N=!!angular.isDefined(d[k+"IsOpen"])&&l(d[k+"IsOpen"]),O=!!o.useContentExp&&l(d[e]),P=[],Q=function(){C&&C.html()&&(H||(H=g(function(){C.css({top:0,left:0});var a=i.positionElements(b,C,L.placement,I);a.top+="px",a.left+="px",a.visibility="visible",C.css(a),H=null},0,!1)))};L.origScope=a,L.isOpen=!1,n.add(L,{close:t}),L.contentExp=function(){return L.content},d.$observe("disabled",function(a){a&&s(),a&&L.isOpen&&t()}),N&&a.$watch(N,function(a){L&&!a===L.isOpen&&j()});var R=function(){J.show.forEach(function(a){b.unbind(a,m)}),J.hide.forEach(function(a){a.split(" ").forEach(function(a){b[0].removeEventListener(a,q)})})};B();var S=a.$eval(d[k+"Animation"]);L.animation=angular.isDefined(S)?!!S:o.animation;var T=a.$eval(d[k+"AppendToBody"]);I=angular.isDefined(T)?T:I,I&&a.$on("$locationChangeSuccess",function(){L.isOpen&&t()}),a.$on("$destroy",function(){s(),u(),R(),w(),n.remove(L),L=null})}}}}}]}).directive("uibTooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest",function(a,b,c,d){return{link:function(e,f,g){var h,i,j,k=e.$eval(g.tooltipTemplateTranscludeScope),l=0,m=function(){i&&(i.remove(),i=null),h&&(h.$destroy(),h=null),j&&(a.leave(j).then(function(){i=null}),i=j,j=null)};e.$watch(b.parseAsResourceUrl(g.uibTooltipTemplateTransclude),function(b){var g=++l;b?(d(b,!0).then(function(d){if(g===l){var e=k.$new(),i=d,n=c(i)(e,function(b){m(),a.enter(b,f)});h=e,j=n,h.$emit("$includeContentLoaded",b)}},function(){g===l&&(m(),e.$emit("$includeContentError",b))}),e.$emit("$includeContentRequested",b)):m()}),e.$on("$destroy",m)}}}]).directive("uibTooltipClasses",function(){return{restrict:"A",link:function(a,b,c){a.placement&&b.addClass(a.placement),a.popupClass&&b.addClass(a.popupClass),a.animation()&&b.addClass(c.tooltipAnimationClass)}}}).directive("uibTooltipPopup",function(){return{replace:!0,scope:{content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html",link:function(a,b){b.addClass("tooltip")}}}).directive("uibTooltip",["$uibTooltip",function(a){return a("uibTooltip","tooltip","mouseenter")}]).directive("uibTooltipTemplatePopup",function(){return{replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/tooltip/tooltip-template-popup.html",link:function(a,b){b.addClass("tooltip")}}}).directive("uibTooltipTemplate",["$uibTooltip",function(a){return a("uibTooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("uibTooltipHtmlPopup",function(){return{replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-popup.html",link:function(a,b){b.addClass("tooltip")}}}).directive("uibTooltipHtml",["$uibTooltip",function(a){return a("uibTooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]),angular.module("ui.bootstrap.tooltip").value("$tooltipSuppressWarning",!1).provider("$tooltip",["$uibTooltipProvider",function(a){angular.extend(this,a),this.$get=["$log","$tooltipSuppressWarning","$injector",function(b,c,d){return c||b.warn("$tooltip is now deprecated. Use $uibTooltip instead."),d.invoke(a.$get)}]}]).directive("tooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest","$log","$tooltipSuppressWarning",function(a,b,c,d,e,f){return{link:function(g,h,i){f||e.warn("tooltip-template-transclude is now deprecated. Use uib-tooltip-template-transclude instead.");var j,k,l,m=g.$eval(i.tooltipTemplateTranscludeScope),n=0,o=function(){k&&(k.remove(),k=null),j&&(j.$destroy(),j=null),l&&(a.leave(l).then(function(){k=null}),k=l,l=null)};g.$watch(b.parseAsResourceUrl(i.tooltipTemplateTransclude),function(b){var e=++n;b?(d(b,!0).then(function(d){if(e===n){var f=m.$new(),g=d,i=c(g)(f,function(b){o(),a.enter(b,h)});j=f,l=i,j.$emit("$includeContentLoaded",b)}},function(){e===n&&(o(),g.$emit("$includeContentError",b))}),g.$emit("$includeContentRequested",b)):o()}),g.$on("$destroy",o)}}}]).directive("tooltipClasses",["$log","$tooltipSuppressWarning",function(a,b){return{restrict:"A",link:function(c,d,e){b||a.warn("tooltip-classes is now deprecated. Use uib-tooltip-classes instead."),c.placement&&d.addClass(c.placement),c.popupClass&&d.addClass(c.popupClass),c.animation()&&d.addClass(e.tooltipAnimationClass)}}}]).directive("tooltipPopup",["$log","$tooltipSuppressWarning",function(a,b){return{replace:!0,scope:{content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html",link:function(c,d){b||a.warn("tooltip-popup is now deprecated. Use uib-tooltip-popup instead."),d.addClass("tooltip")}}}]).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipTemplatePopup",["$log","$tooltipSuppressWarning",function(a,b){return{replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/tooltip/tooltip-template-popup.html",link:function(c,d){b||a.warn("tooltip-template-popup is now deprecated. Use uib-tooltip-template-popup instead."),d.addClass("tooltip")}}}]).directive("tooltipTemplate",["$tooltip",function(a){return a("tooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("tooltipHtmlPopup",["$log","$tooltipSuppressWarning",function(a,b){return{replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-popup.html",link:function(c,d){b||a.warn("tooltip-html-popup is now deprecated. Use uib-tooltip-html-popup instead."),d.addClass("tooltip")}}}]).directive("tooltipHtml",["$tooltip",function(a){return a("tooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("uibPopoverTemplatePopup",function(){return{replace:!0,scope:{title:"@",contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/popover/popover-template.html",link:function(a,b){b.addClass("popover")}}}).directive("uibPopoverTemplate",["$uibTooltip",function(a){return a("uibPopoverTemplate","popover","click",{useContentExp:!0})}]).directive("uibPopoverHtmlPopup",function(){return{replace:!0,scope:{contentExp:"&",title:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover-html.html",link:function(a,b){b.addClass("popover")}}}).directive("uibPopoverHtml",["$uibTooltip",function(a){return a("uibPopoverHtml","popover","click",{useContentExp:!0})}]).directive("uibPopoverPopup",function(){return{replace:!0,scope:{title:"@",content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html",link:function(a,b){b.addClass("popover")}}}).directive("uibPopover",["$uibTooltip",function(a){return a("uibPopover","popover","click")}]),angular.module("ui.bootstrap.popover").value("$popoverSuppressWarning",!1).directive("popoverTemplatePopup",["$log","$popoverSuppressWarning",function(a,b){return{replace:!0,scope:{title:"@",contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/popover/popover-template.html",link:function(c,d){b||a.warn("popover-template-popup is now deprecated. Use uib-popover-template-popup instead."),d.addClass("popover")}}}]).directive("popoverTemplate",["$tooltip",function(a){return a("popoverTemplate","popover","click",{useContentExp:!0})}]).directive("popoverHtmlPopup",["$log","$popoverSuppressWarning",function(a,b){return{replace:!0,scope:{contentExp:"&",title:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover-html.html",link:function(c,d){b||a.warn("popover-html-popup is now deprecated. Use uib-popover-html-popup instead."),d.addClass("popover")}}}]).directive("popoverHtml",["$tooltip",function(a){return a("popoverHtml","popover","click",{useContentExp:!0})}]).directive("popoverPopup",["$log","$popoverSuppressWarning",function(a,b){return{replace:!0,scope:{title:"@",content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html",link:function(c,d){b||a.warn("popover-popup is now deprecated. Use uib-popover-popup instead."),d.addClass("popover")}}}]).directive("popover",["$tooltip",function(a){ -return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("uibProgressConfig",{animate:!0,max:100}).controller("UibProgressController",["$scope","$attrs","uibProgressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(a.max)?a.max:c.max,this.addBar=function(b,c,f){e||c.css({transition:"none"}),this.bars.push(b),b.max=a.max,b.title=f&&angular.isDefined(f.title)?f.title:"progressbar",b.$watch("value",function(a){b.recalculatePercentage()}),b.recalculatePercentage=function(){var a=d.bars.reduce(function(a,b){return b.percent=+(100*b.value/b.max).toFixed(2),a+b.percent},0);a>100&&(b.percent-=a-100)},b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1),this.bars.forEach(function(a){a.recalculatePercentage()})},a.$watch("max",function(b){d.bars.forEach(function(b){b.max=a.max,b.recalculatePercentage()})})}]).directive("uibProgress",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",require:"uibProgress",scope:{max:"=?"},templateUrl:"template/progressbar/progress.html"}}).directive("uibBar",function(){return{replace:!0,transclude:!0,require:"^uibProgress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b,c)}}}).directive("uibProgressbar",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",scope:{value:"=",max:"=?",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]),{title:c.title})}}}),angular.module("ui.bootstrap.progressbar").value("$progressSuppressWarning",!1).controller("ProgressController",["$scope","$attrs","uibProgressConfig","$log","$progressSuppressWarning",function(a,b,c,d,e){e||d.warn("ProgressController is now deprecated. Use UibProgressController instead.");var f=this,g=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(a.max)?a.max:c.max,this.addBar=function(b,c,d){g||c.css({transition:"none"}),this.bars.push(b),b.max=a.max,b.title=d&&angular.isDefined(d.title)?d.title:"progressbar",b.$watch("value",function(a){b.recalculatePercentage()}),b.recalculatePercentage=function(){b.percent=+(100*b.value/b.max).toFixed(2);var a=f.bars.reduce(function(a,b){return a+b.percent},0);a>100&&(b.percent-=a-100)},b.$on("$destroy",function(){c=null,f.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)},a.$watch("max",function(b){f.bars.forEach(function(b){b.max=a.max,b.recalculatePercentage()})})}]).directive("progress",["$log","$progressSuppressWarning",function(a,b){return{replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{max:"=?",title:"@?"},templateUrl:"template/progressbar/progress.html",link:function(){b||a.warn("progress is now deprecated. Use uib-progress instead.")}}}]).directive("bar",["$log","$progressSuppressWarning",function(a,b){return{replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(c,d,e,f){b||a.warn("bar is now deprecated. Use uib-bar instead."),f.addBar(c,d)}}}]).directive("progressbar",["$log","$progressSuppressWarning",function(a,b){return{replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",max:"=?",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(c,d,e,f){b||a.warn("progressbar is now deprecated. Use uib-progressbar instead."),f.addBar(c,angular.element(d.children()[0]),{title:e.title})}}}]),angular.module("ui.bootstrap.rating",[]).constant("uibRatingConfig",{max:5,stateOn:null,stateOff:null,titles:["one","two","three","four","five"]}).controller("UibRatingController",["$scope","$attrs","uibRatingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,d.$formatters.push(function(a){return angular.isNumber(a)&&a<<0!==a&&(a=Math.round(a)),a}),this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.titles)?a.$parent.$eval(b.titles):c.titles;this.titles=angular.isArray(f)&&f.length>0?f:c.titles;var g=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(g)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;b=this.titles.length?a+1:this.titles[a]},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(d.$viewValue===b?0:b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("uibRating",function(){return{require:["uibRating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"UibRatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}),angular.module("ui.bootstrap.rating").value("$ratingSuppressWarning",!1).controller("RatingController",["$scope","$attrs","$controller","$log","$ratingSuppressWarning",function(a,b,c,d,e){e||d.warn("RatingController is now deprecated. Use UibRatingController instead."),angular.extend(this,c("UibRatingController",{$scope:a,$attrs:b}))}]).directive("rating",["$log","$ratingSuppressWarning",function(a,b){return{require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(c,d,e,f){b||a.warn("rating is now deprecated. Use uib-rating instead.");var g=f[0],h=f[1];g.init(h)}}}]),angular.module("ui.bootstrap.tabs",[]).controller("UibTabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect(),a.selectCalled=!1)}),a.active=!0,a.selectCalled||(a.onSelect(),a.selectCalled=!0)},b.addTab=function(a){c.push(a),1===c.length&&a.active!==!1?a.active=!0:a.active?b.select(a):a.active=!1},b.removeTab=function(a){var e=c.indexOf(a);if(a.active&&c.length>1&&!d){var f=e==c.length-1?e-1:e+1;b.select(c[f])}c.splice(e,1)};var d;a.$on("$destroy",function(){d=!0})}]).directive("uibTabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"UibTabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=!!angular.isDefined(c.vertical)&&a.$parent.$eval(c.vertical),a.justified=!!angular.isDefined(c.justified)&&a.$parent.$eval(c.justified)}}}).directive("uibTab",["$parse",function(a){return{require:"^uibTabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},link:function(b,c,d,e,f){b.$watch("active",function(a){a&&e.select(b)}),b.disabled=!1,d.disable&&b.$parent.$watch(a(d.disable),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},e.addTab(b),b.$on("$destroy",function(){e.removeTab(b)}),b.$transcludeFn=f}}}]).directive("uibTabHeadingTransclude",function(){return{restrict:"A",require:["?^uibTab","?^tab"],link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}).directive("uibTabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||a.hasAttribute("x-tab-heading")||a.hasAttribute("uib-tab-heading")||a.hasAttribute("data-uib-tab-heading")||a.hasAttribute("x-uib-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase()||"x-tab-heading"===a.tagName.toLowerCase()||"uib-tab-heading"===a.tagName.toLowerCase()||"data-uib-tab-heading"===a.tagName.toLowerCase()||"x-uib-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:["?^uibTabset","?^tabset"],link:function(b,c,d){var e=b.$eval(d.uibTabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.tabs").value("$tabsSuppressWarning",!1).controller("TabsetController",["$scope","$controller","$log","$tabsSuppressWarning",function(a,b,c,d){d||c.warn("TabsetController is now deprecated. Use UibTabsetController instead."),angular.extend(this,b("UibTabsetController",{$scope:a}))}]).directive("tabset",["$log","$tabsSuppressWarning",function(a,b){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(c,d,e){b||a.warn("tabset is now deprecated. Use uib-tabset instead."),c.vertical=!!angular.isDefined(e.vertical)&&c.$parent.$eval(e.vertical),c.justified=!!angular.isDefined(e.justified)&&c.$parent.$eval(e.justified)}}}]).directive("tab",["$parse","$log","$tabsSuppressWarning",function(a,b,c){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},link:function(d,e,f,g,h){c||b.warn("tab is now deprecated. Use uib-tab instead."),d.$watch("active",function(a){a&&g.select(d)}),d.disabled=!1,f.disable&&d.$parent.$watch(a(f.disable),function(a){d.disabled=!!a}),d.select=function(){d.disabled||(d.active=!0)},g.addTab(d),d.$on("$destroy",function(){g.removeTab(d)}),d.$transcludeFn=h}}}]).directive("tabHeadingTransclude",["$log","$tabsSuppressWarning",function(a,b){return{restrict:"A",require:"^tab",link:function(c,d){b||a.warn("tab-heading-transclude is now deprecated. Use uib-tab-heading-transclude instead."),c.$watch("headingElement",function(a){a&&(d.html(""),d.append(a))})}}}]).directive("tabContentTransclude",["$log","$tabsSuppressWarning",function(a,b){function c(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||a.hasAttribute("x-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase()||"x-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(d,e,f){b||a.warn("tab-content-transclude is now deprecated. Use uib-tab-content-transclude instead.");var g=d.$eval(f.tabContentTransclude);g.$transcludeFn(g.$parent,function(a){angular.forEach(a,function(a){c(a)?g.headingElement=a:e.append(a)})})}}}]),angular.module("ui.bootstrap.timepicker",[]).constant("uibTimepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0,arrowkeys:!0,showSpinners:!0}).controller("UibTimepickerController",["$scope","$element","$attrs","$parse","$log","$locale","uibTimepickerConfig",function(a,b,c,d,e,f,g){function h(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&b<13:b>=0&&b<24;if(c)return a.showMeridian&&(12===b&&(b=0),a.meridian===r[1]&&(b+=12)),b}function i(){var b=parseInt(a.minutes,10);return b>=0&&b<60?b:void 0}function j(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a.toString()}function k(a){l(),q.$setViewValue(new Date(p)),m(a)}function l(){q.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function m(b){var c=p.getHours(),d=p.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:j(c),"m"!==b&&(a.minutes=j(d)),a.meridian=p.getHours()<12?r[0]:r[1]}function n(a,b){var c=new Date(a.getTime()+6e4*b),d=new Date(a);return d.setHours(c.getHours(),c.getMinutes()),d}function o(a){p=n(p,a),k()}var p=new Date,q={$setViewValue:angular.noop},r=angular.isDefined(c.meridians)?a.$parent.$eval(c.meridians):g.meridians||f.DATETIME_FORMATS.AMPMS;a.tabindex=angular.isDefined(c.tabindex)?c.tabindex:0,b.removeAttr("tabindex"),this.init=function(b,d){q=b,q.$render=this.render,q.$formatters.unshift(function(a){return a?new Date(a):null});var e=d.eq(0),f=d.eq(1),h=angular.isDefined(c.mousewheel)?a.$parent.$eval(c.mousewheel):g.mousewheel;h&&this.setupMousewheelEvents(e,f);var i=angular.isDefined(c.arrowkeys)?a.$parent.$eval(c.arrowkeys):g.arrowkeys;i&&this.setupArrowkeyEvents(e,f),a.readonlyInput=angular.isDefined(c.readonlyInput)?a.$parent.$eval(c.readonlyInput):g.readonlyInput,this.setupInputEvents(e,f)};var s=g.hourStep;c.hourStep&&a.$parent.$watch(d(c.hourStep),function(a){s=parseInt(a,10)});var t=g.minuteStep;c.minuteStep&&a.$parent.$watch(d(c.minuteStep),function(a){t=parseInt(a,10)});var u;a.$parent.$watch(d(c.min),function(a){var b=new Date(a);u=isNaN(b)?void 0:b});var v;a.$parent.$watch(d(c.max),function(a){var b=new Date(a);v=isNaN(b)?void 0:b}),a.noIncrementHours=function(){var a=n(p,60*s);return a>v||ap&&a>v},a.noIncrementMinutes=function(){var a=n(p,t);return a>v||ap&&a>v},a.noToggleMeridian=function(){return p.getHours()<13?n(p,720)>v:n(p,-720)0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupArrowkeyEvents=function(b,c){b.bind("keydown",function(b){38===b.which?(b.preventDefault(),a.incrementHours(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementHours(),a.$apply())}),c.bind("keydown",function(b){38===b.which?(b.preventDefault(),a.incrementMinutes(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementMinutes(),a.$apply())})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){q.$setViewValue(null),q.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=h(),b=i();angular.isDefined(a)&&angular.isDefined(b)?(p.setHours(a),pv?d(!0):k("h")):d(!0)},b.bind("blur",function(b){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=j(a.hours)})}),a.updateMinutes=function(){var a=i(),b=h();angular.isDefined(a)&&angular.isDefined(b)?(p.setMinutes(a),pv?d(void 0,!0):k("m")):d(void 0,!0)},c.bind("blur",function(b){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=j(a.minutes)})})},this.render=function(){var b=q.$viewValue;isNaN(b)?(q.$setValidity("time",!1),e.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(b&&(p=b),pv?(q.$setValidity("time",!1),a.invalidHours=!0,a.invalidMinutes=!0):l(),m())},a.showSpinners=angular.isDefined(c.showSpinners)?a.$parent.$eval(c.showSpinners):g.showSpinners,a.incrementHours=function(){a.noIncrementHours()||o(60*s)},a.decrementHours=function(){a.noDecrementHours()||o(60*-s)},a.incrementMinutes=function(){a.noIncrementMinutes()||o(t)},a.decrementMinutes=function(){a.noDecrementMinutes()||o(-t)},a.toggleMeridian=function(){a.noToggleMeridian()||o(720*(p.getHours()<12?1:-1))}}]).directive("uibTimepicker",function(){return{restrict:"EA",require:["uibTimepicker","?^ngModel"],controller:"UibTimepickerController",controllerAs:"timepicker",replace:!0,scope:{},templateUrl:function(a,b){return b.templateUrl||"template/timepicker/timepicker.html"},link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.timepicker").value("$timepickerSuppressWarning",!1).controller("TimepickerController",["$scope","$element","$attrs","$controller","$log","$timepickerSuppressWarning",function(a,b,c,d,e,f){f||e.warn("TimepickerController is now deprecated. Use UibTimepickerController instead."),angular.extend(this,d("UibTimepickerController",{$scope:a,$element:b,$attrs:c}))}]).directive("timepicker",["$log","$timepickerSuppressWarning",function(a,b){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",controllerAs:"timepicker",replace:!0,scope:{},templateUrl:function(a,b){return b.templateUrl||"template/timepicker/timepicker.html"},link:function(c,d,e,f){b||a.warn("timepicker is now deprecated. Use uib-timepicker instead.");var g=f[0],h=f[1];h&&g.init(h,d.find("input"))}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position"]).factory("uibTypeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).controller("UibTypeaheadController",["$scope","$element","$attrs","$compile","$parse","$q","$timeout","$document","$window","$rootScope","$uibPosition","uibTypeaheadParser",function(a,b,c,d,e,f,g,h,i,j,k,l){function m(){K.moveInProgress||(K.moveInProgress=!0,K.$digest()),S&&g.cancel(S),S=g(function(){K.matches.length&&n(),K.moveInProgress=!1},r)}function n(){K.position=C?k.offset(b):k.position(b),K.position.top+=b.prop("offsetHeight")}var o,p,q=[9,13,27,38,40],r=200,s=a.$eval(c.typeaheadMinLength);s||0===s||(s=1);var t,u,v=a.$eval(c.typeaheadWaitMs)||0,w=a.$eval(c.typeaheadEditable)!==!1,x=e(c.typeaheadLoading).assign||angular.noop,y=e(c.typeaheadOnSelect),z=!!angular.isDefined(c.typeaheadSelectOnBlur)&&a.$eval(c.typeaheadSelectOnBlur),A=e(c.typeaheadNoResults).assign||angular.noop,B=c.typeaheadInputFormatter?e(c.typeaheadInputFormatter):void 0,C=!!c.typeaheadAppendToBody&&a.$eval(c.typeaheadAppendToBody),D=c.typeaheadAppendToElementId||!1,E=a.$eval(c.typeaheadFocusFirst)!==!1,F=!!c.typeaheadSelectOnExact&&a.$eval(c.typeaheadSelectOnExact),G=e(c.ngModel),H=e(c.ngModel+"($$$p)"),I=function(b,c){return angular.isFunction(G(a))&&p&&p.$options&&p.$options.getterSetter?H(b,{$$$p:c}):G.assign(b,c)},J=l.parse(c.uibTypeahead),K=a.$new(),L=a.$on("$destroy",function(){K.$destroy()});K.$on("$destroy",L);var M="typeahead-"+K.$id+"-"+Math.floor(1e4*Math.random());b.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":M});var N=angular.element("
    ");N.attr({id:M,matches:"matches",active:"activeIdx",select:"select(activeIdx)","move-in-progress":"moveInProgress",query:"query",position:"position"}),angular.isDefined(c.typeaheadTemplateUrl)&&N.attr("template-url",c.typeaheadTemplateUrl),angular.isDefined(c.typeaheadPopupTemplateUrl)&&N.attr("popup-template-url",c.typeaheadPopupTemplateUrl);var O=function(){K.matches=[],K.activeIdx=-1,b.attr("aria-expanded",!1)},P=function(a){return M+"-option-"+a};K.$watch("activeIdx",function(a){a<0?b.removeAttr("aria-activedescendant"):b.attr("aria-activedescendant",P(a))});var Q=function(a,b){return!!(K.matches.length>b&&a)&&a.toUpperCase()===K.matches[b].label.toUpperCase()},R=function(c){var d={$viewValue:c};x(a,!0),A(a,!1),f.when(J.source(a,d)).then(function(e){var f=c===o.$viewValue;if(f&&t)if(e&&e.length>0){K.activeIdx=E?0:-1,A(a,!1),K.matches.length=0;for(var g=0;g0?K.activeIdx:K.matches.length)-1,K.$digest()):13===a.which||9===a.which?K.$apply(function(){K.select(K.activeIdx)}):27===a.which&&(a.stopPropagation(),O(),K.$digest())}}),b.bind("blur",function(){z&&K.matches.length&&K.activeIdx!==-1&&!u&&(u=!0,K.$apply(function(){K.select(K.activeIdx)})),t=!1,u=!1});var W=function(a){b[0]!==a.target&&3!==a.which&&0!==K.matches.length&&(O(),j.$$phase||K.$digest())};h.bind("click",W),a.$on("$destroy",function(){h.unbind("click",W),(C||D)&&X.remove(),C&&(angular.element(i).unbind("resize",m),h.find("body").unbind("scroll",m)),N.remove()});var X=d(N)(K);C?h.find("body").append(X):D!==!1?angular.element(h[0].getElementById(D)).append(X):b.after(X),this.init=function(b,c){o=b,p=c,o.$parsers.unshift(function(b){return t=!0,0===s||b&&b.length>=s?v>0?(V(),U(b)):R(b):(x(a,!1),V(),O()),w?b:b?void o.$setValidity("editable",!1):(o.$setValidity("editable",!0),null)}),o.$formatters.push(function(b){var c,d,e={};return w||o.$setValidity("editable",!0),B?(e.$model=b,B(a,e)):(e[J.itemName]=b,c=J.viewMapper(a,e),e[J.itemName]=void 0,d=J.viewMapper(a,e),c!==d?c:b)})}}]).directive("uibTypeahead",function(){return{controller:"UibTypeaheadController",require:["ngModel","^?ngModelOptions","uibTypeahead"],link:function(a,b,c,d){d[2].init(d[0],d[1])}}}).directive("uibTypeaheadPopup",function(){return{scope:{matches:"=",query:"=",active:"=",position:"&",moveInProgress:"=",select:"&"},replace:!0,templateUrl:function(a,b){return b.popupTemplateUrl||"template/typeahead/typeahead-popup.html"},link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("uibTypeaheadMatch",["$templateRequest","$compile","$parse",function(a,b,c){return{scope:{index:"=",match:"=",query:"="},link:function(d,e,f){var g=c(f.templateUrl)(d.$parent)||"template/typeahead/typeahead-match.html";a(g).then(function(a){b(a.trim())(d,function(a){e.replaceWith(a)})})}}}]).filter("uibTypeaheadHighlight",["$sce","$injector","$log",function(a,b,c){function d(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function e(a){return/<.*>/g.test(a)}var f;return f=b.has("$sanitize"),function(b,g){return!f&&e(b)&&c.warn("Unsafe use of typeahead please use ngSanitize"),b=g?(""+b).replace(new RegExp(d(g),"gi"),"$&"):b,f||(b=a.trustAsHtml(b)),b}}]),angular.module("ui.bootstrap.typeahead").value("$typeaheadSuppressWarning",!1).service("typeaheadParser",["$parse","uibTypeaheadParser","$log","$typeaheadSuppressWarning",function(a,b,c,d){return d||c.warn("typeaheadParser is now deprecated. Use uibTypeaheadParser instead."),b}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$window","$rootScope","$uibPosition","typeaheadParser","$log","$typeaheadSuppressWarning",function(a,b,c,d,e,f,g,h,i,j,k){var l=[9,13,27,38,40],m=200;return{require:["ngModel","^?ngModelOptions"],link:function(n,o,p,q){function r(){N.moveInProgress||(N.moveInProgress=!0,N.$digest()),V&&d.cancel(V),V=d(function(){N.matches.length&&s(),N.moveInProgress=!1},m)}function s(){N.position=F?h.offset(o):h.position(o),N.position.top+=o.prop("offsetHeight")}k||j.warn("typeahead is now deprecated. Use uib-typeahead instead.");var t=q[0],u=q[1],v=n.$eval(p.typeaheadMinLength);v||0===v||(v=1);var w,x,y=n.$eval(p.typeaheadWaitMs)||0,z=n.$eval(p.typeaheadEditable)!==!1,A=b(p.typeaheadLoading).assign||angular.noop,B=b(p.typeaheadOnSelect),C=!!angular.isDefined(p.typeaheadSelectOnBlur)&&n.$eval(p.typeaheadSelectOnBlur),D=b(p.typeaheadNoResults).assign||angular.noop,E=p.typeaheadInputFormatter?b(p.typeaheadInputFormatter):void 0,F=!!p.typeaheadAppendToBody&&n.$eval(p.typeaheadAppendToBody),G=p.typeaheadAppendToElementId||!1,H=n.$eval(p.typeaheadFocusFirst)!==!1,I=!!p.typeaheadSelectOnExact&&n.$eval(p.typeaheadSelectOnExact),J=b(p.ngModel),K=b(p.ngModel+"($$$p)"),L=function(a,b){return angular.isFunction(J(n))&&u&&u.$options&&u.$options.getterSetter?K(a,{$$$p:b}):J.assign(a,b)},M=i.parse(p.typeahead),N=n.$new(),O=n.$on("$destroy",function(){N.$destroy()});N.$on("$destroy",O);var P="typeahead-"+N.$id+"-"+Math.floor(1e4*Math.random());o.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":P});var Q=angular.element("
    ");Q.attr({id:P,matches:"matches",active:"activeIdx",select:"select(activeIdx)","move-in-progress":"moveInProgress",query:"query",position:"position"}),angular.isDefined(p.typeaheadTemplateUrl)&&Q.attr("template-url",p.typeaheadTemplateUrl),angular.isDefined(p.typeaheadPopupTemplateUrl)&&Q.attr("popup-template-url",p.typeaheadPopupTemplateUrl);var R=function(){N.matches=[],N.activeIdx=-1,o.attr("aria-expanded",!1)},S=function(a){return P+"-option-"+a};N.$watch("activeIdx",function(a){a<0?o.removeAttr("aria-activedescendant"):o.attr("aria-activedescendant",S(a))});var T=function(a,b){return!!(N.matches.length>b&&a)&&a.toUpperCase()===N.matches[b].label.toUpperCase()},U=function(a){var b={$viewValue:a};A(n,!0),D(n,!1),c.when(M.source(n,b)).then(function(c){var d=a===t.$viewValue;if(d&&w)if(c&&c.length>0){N.activeIdx=H?0:-1,D(n,!1),N.matches.length=0;for(var e=0;e=v?y>0?(Y(),X(a)):U(a):(A(n,!1),Y(),R()),z?a:a?void t.$setValidity("editable",!1):(t.$setValidity("editable",!0),null)}),t.$formatters.push(function(a){var b,c,d={};return z||t.$setValidity("editable",!0),E?(d.$model=a,E(n,d)):(d[M.itemName]=a,b=M.viewMapper(n,d),d[M.itemName]=void 0,c=M.viewMapper(n,d),b!==c?b:a)}),N.select=function(a){var b,c,e={};x=!0,e[M.itemName]=c=N.matches[a].model,b=M.modelMapper(n,e),L(n,b),t.$setValidity("editable",!0),t.$setValidity("parse",!0),B(n,{$item:c,$model:b,$label:M.viewMapper(n,e)}),R(),N.$eval(p.typeaheadFocusOnSelect)!==!1&&d(function(){o[0].focus()},0,!1)},o.bind("keydown",function(a){if(0!==N.matches.length&&l.indexOf(a.which)!==-1){if(N.activeIdx===-1&&(9===a.which||13===a.which))return R(),void N.$digest();a.preventDefault(),40===a.which?(N.activeIdx=(N.activeIdx+1)%N.matches.length,N.$digest()):38===a.which?(N.activeIdx=(N.activeIdx>0?N.activeIdx:N.matches.length)-1,N.$digest()):13===a.which||9===a.which?N.$apply(function(){N.select(N.activeIdx)}):27===a.which&&(a.stopPropagation(),R(),N.$digest())}}),o.bind("blur",function(){C&&N.matches.length&&N.activeIdx!==-1&&!x&&(x=!0,N.$apply(function(){N.select(N.activeIdx)})),w=!1,x=!1});var Z=function(a){o[0]!==a.target&&3!==a.which&&0!==N.matches.length&&(R(),g.$$phase||N.$digest())};e.bind("click",Z),n.$on("$destroy",function(){e.unbind("click",Z),(F||G)&&$.remove(),F&&(angular.element(f).unbind("resize",r),e.find("body").unbind("scroll",r)),Q.remove()});var $=a(Q)(N);F?e.find("body").append($):G!==!1?angular.element(e[0].getElementById(G)).append($):o.after($)}}}]).directive("typeaheadPopup",["$typeaheadSuppressWarning","$log",function(a,b){return{scope:{matches:"=",query:"=",active:"=",position:"&",moveInProgress:"=",select:"&"},replace:!0,templateUrl:function(a,b){return b.popupTemplateUrl||"template/typeahead/typeahead-popup.html"},link:function(c,d,e){a||b.warn("typeahead-popup is now deprecated. Use uib-typeahead-popup instead."),c.templateUrl=e.templateUrl,c.isOpen=function(){return c.matches.length>0},c.isActive=function(a){return c.active==a},c.selectActive=function(a){c.active=a},c.selectMatch=function(a){c.select({activeIdx:a})}}}}]).directive("typeaheadMatch",["$templateRequest","$compile","$parse","$typeaheadSuppressWarning","$log",function(a,b,c,d,e){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(f,g,h){d||e.warn("typeahead-match is now deprecated. Use uib-typeahead-match instead.");var i=c(h.templateUrl)(f.$parent)||"template/typeahead/typeahead-match.html";a(i).then(function(a){b(a.trim())(f,function(a){g.replaceWith(a)})})}}}]).filter("typeaheadHighlight",["$sce","$injector","$log","$typeaheadSuppressWarning",function(a,b,c,d){function e(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function f(a){return/<.*>/g.test(a)}var g;return g=b.has("$sanitize"),function(b,h){return d||c.warn("typeaheadHighlight is now deprecated. Use uibTypeaheadHighlight instead."),!g&&f(b)&&c.warn("Unsafe use of typeahead please use ngSanitize"),b=h?(""+b).replace(new RegExp(e(h),"gi"),"$&"):b,g||(b=a.trustAsHtml(b)),b}}]),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion-group.html",'
    \n
    \n

    \n {{heading}}\n

    \n
    \n
    \n\t
    \n
    \n
    \n')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion.html",'
    ')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("template/alert/alert.html",'\n')}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("template/carousel/carousel.html",''); -}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("template/carousel/slide.html",'
    \n')}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/datepicker.html",'
    \n \n \n \n
    ')}]),angular.module("template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/day.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    {{::label.abbr}}
    {{ weekNumbers[$index] }}\n \n
    \n')}]),angular.module("template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/month.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n
    \n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/popup.html",'\n')}]),angular.module("template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/year.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n
    \n')}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'
    \n')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'\n')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pager.html",'\n')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pagination.html",'\n')}]),angular.module("template/tooltip/tooltip-html-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-popup.html",'\n
    \n
    \n\n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-popup.html",'\n
    \n
    \n\n')}]),angular.module("template/tooltip/tooltip-template-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-template-popup.html",'\n
    \n
    \n\n')}]),angular.module("template/popover/popover-html.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover-html.html",'
    \n
    \n\n
    \n

    \n
    \n
    \n
    \n')}]),angular.module("template/popover/popover-template.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover-template.html",'
    \n
    \n\n
    \n

    \n
    \n
    \n
    \n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover.html",'
    \n
    \n\n
    \n

    \n
    \n
    \n
    \n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/bar.html",'
    \n')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progress.html",'
    ')}]),angular.module("template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progressbar.html",'
    \n
    \n
    \n')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("template/rating/rating.html",'\n ({{ $index < value ? \'*\' : \' \' }})\n \n\n')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'
  • \n {{heading}}\n
  • \n')}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset.html",'
    \n \n
    \n
    \n
    \n
    \n
    \n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("template/timepicker/timepicker.html",'\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')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-match.html",'\n')}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-popup.html",'\n')}]),!angular.$$csp()&&angular.element(document).find("head").prepend(''),!function(a,b){"function"==typeof define&&define.amd?define([],function(){return b()}):"object"==typeof exports?module.exports=b():b()}(this,function(){function a(a){var b=a.storageKey(),c=a.storage(),d=function(){var d=a.preferredLanguage();angular.isString(d)?a.use(d):c.put(b,a.use())};d.displayName="fallbackFromIncorrectStorageValue",c?c.get(b)?a.use(c.get(b))["catch"](d):d():angular.isString(a.preferredLanguage())&&a.use(a.preferredLanguage())}function b(){var a,b,c=null,d=!1,e=!1;b={sanitize:function(a,b){return"text"===b&&(a=g(a)),a},escape:function(a,b){return"text"===b&&(a=f(a)),a},sanitizeParameters:function(a,b){return"params"===b&&(a=h(a,g)),a},escapeParameters:function(a,b){return"params"===b&&(a=h(a,f)),a}},b.escaped=b.escapeParameters,this.addStrategy=function(a,c){return b[a]=c,this},this.removeStrategy=function(a){return delete b[a],this},this.useStrategy=function(a){return d=!0,c=a,this},this.$get=["$injector","$log",function(f,g){var h={},i=function(a,c,d){return angular.forEach(d,function(d){if(angular.isFunction(d))a=d(a,c);else if(angular.isFunction(b[d]))a=b[d](a,c);else{if(!angular.isString(b[d]))throw new Error("pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: '"+d+"'");if(!h[b[d]])try{h[b[d]]=f.get(b[d])}catch(e){throw h[b[d]]=function(){},new Error("pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: '"+d+"'")}a=h[b[d]](a,c)}}),a},j=function(){d||e||(g.warn("pascalprecht.translate.$translateSanitization: No sanitization strategy has been configured. This can have serious security implications. See http://angular-translate.github.io/docs/#/guide/19_security for details."),e=!0)};return f.has("$sanitize")&&(a=f.get("$sanitize")),{useStrategy:function(a){return function(b){a.useStrategy(b)}}(this),sanitize:function(a,b,d){if(c||j(),arguments.length<3&&(d=c),!d)return a;var e=angular.isArray(d)?d:[d];return i(a,b,e)}}}];var f=function(a){var b=angular.element("
    ");return b.text(a),b.html()},g=function(b){if(!a)throw new Error("pascalprecht.translate.$translateSanitization: Error cannot find $sanitize service. Either include the ngSanitize module (https://docs.angularjs.org/api/ngSanitize) or use a sanitization strategy which does not depend on $sanitize, such as 'escape'.");return a(b)},h=function(a,b,c){if(angular.isObject(a)){var d=angular.isArray(a)?[]:{};if(c){if(c.indexOf(a)>-1)throw new Error("pascalprecht.translate.$translateSanitization: Error cannot interpolate parameter due recursive object")}else c=[];return c.push(a),angular.forEach(a,function(a,e){d[e]=h(a,b,c)}),c.splice(-1,1),d}return angular.isNumber(a)?a:b(a)}}function c(a,b,c,d){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u={},v=[],w=a,x=[],y="translate-cloak",z=!1,A=!1,B=".",C=!1,D=0,E=!0,F="default",G={"default":function(a){return(a||"").split("-").join("_")},java:function(a){var b=(a||"").split("-").join("_"),c=b.split("_");return c.length>1?c[0].toLowerCase()+"_"+c[1].toUpperCase():b},bcp47:function(a){var b=(a||"").split("_").join("-"),c=b.split("-");return c.length>1?c[0].toLowerCase()+"-"+c[1].toUpperCase():b},"iso639-1":function(a){var b=(a||"").split("_").join("-"),c=b.split("-");return c[0].toLowerCase()}},H="2.11.0",I=function(){if(angular.isFunction(d.getLocale))return d.getLocale();var a,c,e=b.$get().navigator,f=["language","browserLanguage","systemLanguage","userLanguage"];if(angular.isArray(e.languages))for(a=0;ac;c++)if(a[c]===b)return c;return-1},L=function(){return this.toString().replace(/^\s+|\s+$/g,"")},M=function(a){if(a){for(var b=[],c=angular.lowercase(a),d=0,e=v.length;e>d;d++)b.push(angular.lowercase(v[d]));if(K(b,c)>-1)return a;if(f){var g;for(var h in f)if(f.hasOwnProperty(h)){var i=!1,j=Object.prototype.hasOwnProperty.call(f,h)&&angular.lowercase(h)===angular.lowercase(a);if("*"===h.slice(-1)&&(i=h.slice(0,-1)===a.slice(0,h.length-1)),(j||i)&&(g=f[h],K(b,angular.lowercase(g))>-1))return g}}var k=a.split("_");return k.length>1&&K(b,angular.lowercase(k[0]))>-1?k[0]:void 0}},N=function(a,b){if(!a&&!b)return u;if(a&&!b){if(angular.isString(a))return u[a]}else angular.isObject(u[a])||(u[a]={}),angular.extend(u[a],O(b));return this};this.translations=N,this.cloakClassName=function(a){return a?(y=a,this):y},this.nestedObjectDelimeter=function(a){return a?(B=a,this):B};var O=function(a,b,c,d){var e,f,g,h;b||(b=[]),c||(c={});for(e in a)Object.prototype.hasOwnProperty.call(a,e)&&(h=a[e],angular.isObject(h)?O(h,b.concat(e),c,e):(f=b.length?""+b.join(B)+B+e:e,b.length&&e===d&&(g=""+b.join(B),c[g]="@:"+f),c[f]=h));return c};O.displayName="flatObject",this.addInterpolation=function(a){return x.push(a),this},this.useMessageFormatInterpolation=function(){return this.useInterpolation("$translateMessageFormatInterpolation")},this.useInterpolation=function(a){return n=a,this},this.useSanitizeValueStrategy=function(a){return c.useStrategy(a),this},this.preferredLanguage=function(a){return a?(P(a),this):e};var P=function(a){return a&&(e=a),e};this.translationNotFoundIndicator=function(a){return this.translationNotFoundIndicatorLeft(a),this.translationNotFoundIndicatorRight(a),this},this.translationNotFoundIndicatorLeft=function(a){return a?(q=a,this):q},this.translationNotFoundIndicatorRight=function(a){return a?(r=a,this):r},this.fallbackLanguage=function(a){return Q(a),this};var Q=function(a){return a?(angular.isString(a)?(h=!0,g=[a]):angular.isArray(a)&&(h=!1,g=a),angular.isString(e)&&K(g,e)<0&&g.push(e),this):h?g[0]:g};this.use=function(a){if(a){if(!u[a]&&!o)throw new Error("$translateProvider couldn't find translationTable for langKey: '"+a+"'");return i=a,this}return i},this.resolveClientLocale=function(){return J()};var R=function(a){return a?(w=a,this):l?l+w:w};this.storageKey=R,this.useUrlLoader=function(a,b){return this.useLoader("$translateUrlLoader",angular.extend({url:a},b))},this.useStaticFilesLoader=function(a){return this.useLoader("$translateStaticFilesLoader",a)},this.useLoader=function(a,b){return o=a,p=b||{},this},this.useLocalStorage=function(){return this.useStorage("$translateLocalStorage")},this.useCookieStorage=function(){return this.useStorage("$translateCookieStorage")},this.useStorage=function(a){return k=a,this},this.storagePrefix=function(a){return a?(l=a,this):a},this.useMissingTranslationHandlerLog=function(){return this.useMissingTranslationHandler("$translateMissingTranslationHandlerLog")},this.useMissingTranslationHandler=function(a){return m=a,this},this.usePostCompiling=function(a){return z=!!a,this},this.forceAsyncReload=function(a){return A=!!a,this},this.uniformLanguageTag=function(a){return a?angular.isString(a)&&(a={standard:a}):a={},F=a.standard,this},this.determinePreferredLanguage=function(a){var b=a&&angular.isFunction(a)?a():J();return e=v.length?M(b)||b:b,this},this.registerAvailableLanguageKeys=function(a,b){return a?(v=a,b&&(f=b),this):v},this.useLoaderCache=function(a){return a===!1?s=void 0:a===!0?s=!0:"undefined"==typeof a?s="$translationCache":a&&(s=a),this},this.directivePriority=function(a){return void 0===a?D:(D=a,this)},this.statefulFilter=function(a){return void 0===a?E:(E=a,this)},this.postProcess=function(a){return t=a?a:void 0,this},this.$get=["$log","$injector","$rootScope","$q",function(a,b,c,d){var f,l,F,G=b.get(n||"$translateDefaultInterpolation"),I=!1,S={},T={},U=function(a,b,c,h,j){!i&&e&&(i=e);var m=j&&j!==i?M(j)||j:i;if(j&&ja(j),angular.isArray(a)){var n=function(a){for(var e={},f=[],g=function(a){var f=d.defer(),g=function(b){e[a]=b,f.resolve([a,b])};return U(a,b,c,h,j).then(g,g),f.promise},i=0,k=a.length;k>i;i++)f.push(g(a[i]));return d.all(f).then(function(){return e})};return n(a)}var o=d.defer();a&&(a=L.apply(a));var p=function(){var a=e?T[e]:T[m];if(l=0,k&&!a){var b=f.get(w);if(a=T[b],g&&g.length){var c=K(g,b);l=0===c?1:0,K(g,e)<0&&g.push(e)}}return a}();if(p){var q=function(){j||(m=i),fa(a,b,c,h,m).then(o.resolve,o.reject)};q.displayName="promiseResolved",p["finally"](q)}else fa(a,b,c,h,m).then(o.resolve,o.reject);return o.promise},V=function(a){return q&&(a=[q,a].join(" ")),r&&(a=[a,r].join(" ")),a},W=function(a){i=a,k&&f.put(U.storageKey(),i),c.$emit("$translateChangeSuccess",{language:a}),G.setLocale(i);var b=function(a,b){S[b].setLocale(i)};b.displayName="eachInterpolatorLocaleSetter",angular.forEach(S,b),c.$emit("$translateChangeEnd",{language:a})},X=function(a){if(!a)throw"No language key specified for loading.";var e=d.defer();c.$emit("$translateLoadingStart",{language:a}),I=!0;var f=s;"string"==typeof f&&(f=b.get(f));var g=angular.extend({},p,{key:a,$http:angular.extend({},{cache:f},p.$http)}),h=function(b){var d={};c.$emit("$translateLoadingSuccess",{language:a}),angular.isArray(b)?angular.forEach(b,function(a){angular.extend(d,O(a))}):angular.extend(d,O(b)),I=!1,e.resolve({key:a,table:d}),c.$emit("$translateLoadingEnd",{language:a})};h.displayName="onLoaderSuccess";var i=function(a){c.$emit("$translateLoadingError",{language:a}),e.reject(a),c.$emit("$translateLoadingEnd",{language:a})};return i.displayName="onLoaderError",b.get(o)(g).then(h,i),e.promise};if(k&&(f=b.get(k),!f.get||!f.put))throw new Error("Couldn't use storage '"+k+"', missing get() or put() method!");if(x.length){var Y=function(a){var c=b.get(a);c.setLocale(e||i),S[c.getInterpolationIdentifier()]=c};Y.displayName="interpolationFactoryAdder",angular.forEach(x,Y)}var Z=function(a){var b=d.defer();if(Object.prototype.hasOwnProperty.call(u,a))b.resolve(u[a]);else if(T[a]){var c=function(a){N(a.key,a.table),b.resolve(a.table)};c.displayName="translationTableResolver",T[a].then(c,b.reject)}else b.reject();return b.promise},$=function(a,b,c,e){var f=d.defer(),g=function(d){if(Object.prototype.hasOwnProperty.call(d,b)){e.setLocale(a);var g=d[b];if("@:"===g.substr(0,2))$(a,g.substr(2),c,e).then(f.resolve,f.reject);else{var h=e.interpolate(d[b],c);h=ia(b,d[b],h,c,a),f.resolve(h)}e.setLocale(i)}else f.reject()};return g.displayName="fallbackTranslationResolver",Z(a).then(g,f.reject),f.promise},_=function(a,b,c,d){var e,f=u[a];if(f&&Object.prototype.hasOwnProperty.call(f,b)){if(d.setLocale(a),e=d.interpolate(f[b],c),"@:"===e.substr(0,2))return _(a,e.substr(2),c,d);d.setLocale(i)}return e},aa=function(a,c,d){if(m){var e=b.get(m)(a,i,c,d);return void 0!==e?e:a}return a},ba=function(a,b,c,e,f){var h=d.defer();if(a0?F:l,a,b,c,d)},ea=function(a,b,c){return ca(F>0?F:l,a,b,c)},fa=function(a,b,c,e,f){var h=d.defer(),i=f?u[f]:u,j=c?S[c]:G;if(i&&Object.prototype.hasOwnProperty.call(i,a)){var k=i[a];if("@:"===k.substr(0,2))U(k.substr(2),b,c,e,f).then(h.resolve,h.reject);else{var l=j.interpolate(k,b);l=ia(a,k,l,b,f),h.resolve(l)}}else{var n;m&&!I&&(n=aa(a,b,e)),f&&g&&g.length?da(a,b,j,e).then(function(a){h.resolve(a)},function(a){h.reject(V(a))}):m&&!I&&n?e?h.resolve(e):h.resolve(n):e?h.resolve(e):h.reject(V(a))}return h.promise},ga=function(a,b,c,d){var e,f=d?u[d]:u,h=G;if(S&&Object.prototype.hasOwnProperty.call(S,c)&&(h=S[c]),f&&Object.prototype.hasOwnProperty.call(f,a)){var i=f[a];e="@:"===i.substr(0,2)?ga(i.substr(2),b,c,d):h.interpolate(i,b)}else{var j;m&&!I&&(j=aa(a,b)),d&&g&&g.length?(l=0,e=ea(a,b,h)):e=m&&!I&&j?j:V(a)}return e},ha=function(a){j===a&&(j=void 0),T[a]=void 0},ia=function(a,c,d,e,f){var g=t;return g&&("string"==typeof g&&(g=b.get(g)),g)?g(a,c,d,e,f):d},ja=function(a){u[a]||!o||T[a]||(T[a]=X(a).then(function(a){N(a.key,a.table)}))};U.preferredLanguage=function(a){return a&&P(a),e},U.cloakClassName=function(){return y},U.nestedObjectDelimeter=function(){return B},U.fallbackLanguage=function(a){if(void 0!==a&&null!==a){if(Q(a),o&&g&&g.length)for(var b=0,c=g.length;c>b;b++)T[g[b]]||(T[g[b]]=X(g[b]));U.use(U.use())}return h?g[0]:g},U.useFallbackLanguage=function(a){if(void 0!==a&&null!==a)if(a){var b=K(g,a);b>-1&&(F=b)}else F=0},U.proposedLanguage=function(){return j},U.storage=function(){return f},U.negotiateLocale=M,U.use=function(a){if(!a)return i;var b=d.defer();c.$emit("$translateChangeStart",{language:a});var e=M(a);return v.length>0&&!e?d.reject(a):(e&&(a=e),j=a,!A&&u[a]||!o||T[a]?T[a]?T[a].then(function(a){return j===a.key&&W(a.key),b.resolve(a.key),a},function(a){return!i&&g&&g.length>0?U.use(g[0]).then(b.resolve,b.reject):b.reject(a)}):(b.resolve(a),W(a)):(T[a]=X(a).then(function(c){return N(c.key,c.table),b.resolve(c.key),j===a&&W(c.key),c},function(a){return c.$emit("$translateChangeError",{language:a}),b.reject(a),c.$emit("$translateChangeEnd",{language:a}),d.reject(a)}),T[a]["finally"](function(){ha(a)})),b.promise)},U.resolveClientLocale=function(){return J()},U.storageKey=function(){return R()},U.isPostCompilingEnabled=function(){return z},U.isForceAsyncReloadEnabled=function(){return A},U.refresh=function(a){function b(){f.resolve(),c.$emit("$translateRefreshEnd",{language:a})}function e(){f.reject(),c.$emit("$translateRefreshEnd",{language:a})}if(!o)throw new Error("Couldn't refresh translation table, no loader registered!");var f=d.defer();if(c.$emit("$translateRefreshStart",{language:a}),a)if(u[a]){var h=function(c){N(c.key,c.table),a===i&&W(i),b()};h.displayName="refreshPostProcessor",X(a).then(h,e)}else e();else{var j=[],k={};if(g&&g.length)for(var l=0,m=g.length;m>l;l++)j.push(X(g[l])),k[g[l]]=!0;i&&!k[i]&&j.push(X(i));var n=function(a){u={},angular.forEach(a,function(a){N(a.key,a.table)}),i&&W(i),b()};n.displayName="refreshPostProcessor",d.all(j).then(n,e)}return f.promise},U.instant=function(a,b,c,d){var f=d&&d!==i?M(d)||d:i;if(null===a||angular.isUndefined(a))return a;if(d&&ja(d),angular.isArray(a)){for(var h={},j=0,k=a.length;k>j;j++)h[a[j]]=U.instant(a[j],b,c,d);return h}if(angular.isString(a)&&a.length<1)return a;a&&(a=L.apply(a));var l,n=[];e&&n.push(e),f&&n.push(f),g&&g.length&&(n=n.concat(g));for(var o=0,p=n.length;p>o;o++){var s=n[o];if(u[s]&&"undefined"!=typeof u[s][a]&&(l=ga(a,b,c,f)),"undefined"!=typeof l)break}return l||""===l||(q||r?l=V(a):(l=G.interpolate(a,b),m&&!I&&(l=aa(a,b)))),l},U.versionInfo=function(){return H},U.loaderCache=function(){return s},U.directivePriority=function(){return D},U.statefulFilter=function(){return E},U.isReady=function(){return C};var ka=d.defer();ka.promise.then(function(){C=!0}),U.onReady=function(a){var b=d.defer();return angular.isFunction(a)&&b.promise.then(a),C?b.resolve():ka.promise.then(b.resolve), -b.promise},U.getAvailableLanguageKeys=function(){return v.length>0?v:null};var la=c.$on("$translateReady",function(){ka.resolve(),la(),la=null}),ma=c.$on("$translateChangeEnd",function(){ka.resolve(),ma(),ma=null});if(o){if(angular.equals(u,{})&&U.use()&&U.use(U.use()),g&&g.length)for(var na=function(a){return N(a.key,a.table),c.$emit("$translateChangeEnd",{language:a.key}),a},oa=0,pa=g.length;pa>oa;oa++){var qa=g[oa];!A&&u[qa]||(T[qa]=X(qa).then(na))}}else c.$emit("$translateReady",{language:U.use()});return U}]}function d(a,b){var c,d={},e="default";return d.setLocale=function(a){c=a},d.getInterpolationIdentifier=function(){return e},d.useSanitizeValueStrategy=function(a){return b.useStrategy(a),this},d.interpolate=function(c,d){d=d||{},d=b.sanitize(d,"params");var e=a(c)(d);return e=b.sanitize(e,"text")},d}function e(a,b,c,d,e,g){var h=function(){return this.toString().replace(/^\s+|\s+$/g,"")};return{restrict:"AE",scope:!0,priority:a.directivePriority(),compile:function(b,i){var j=i.translateValues?i.translateValues:void 0,k=i.translateInterpolation?i.translateInterpolation:void 0,l=b[0].outerHTML.match(/translate-value-+/i),m="^(.*)("+c.startSymbol()+".*"+c.endSymbol()+")(.*)",n="^(.*)"+c.startSymbol()+"(.*)"+c.endSymbol()+"(.*)";return function(b,o,p){b.interpolateParams={},b.preText="",b.postText="",b.translateNamespace=f(b);var q={},r=function(a,c,d){if(c.translateValues&&angular.extend(a,e(c.translateValues)(b.$parent)),l)for(var f in d)if(Object.prototype.hasOwnProperty.call(c,f)&&"translateValue"===f.substr(0,14)&&"translateValues"!==f){var g=angular.lowercase(f.substr(14,1))+f.substr(15);a[g]=d[f]}},s=function(a){if(angular.isFunction(s._unwatchOld)&&(s._unwatchOld(),s._unwatchOld=void 0),angular.equals(a,"")||!angular.isDefined(a)){var d=h.apply(o.text()),e=d.match(m);if(angular.isArray(e)){b.preText=e[1],b.postText=e[3],q.translate=c(e[2])(b.$parent);var f=d.match(n);angular.isArray(f)&&f[2]&&f[2].length&&(s._unwatchOld=b.$watch(f[2],function(a){q.translate=a,y()}))}else q.translate=d?d:void 0}else q.translate=a;y()},t=function(a){p.$observe(a,function(b){q[a]=b,y()})};r(b.interpolateParams,p,i);var u=!0;p.$observe("translate",function(a){"undefined"==typeof a?s(""):""===a&&u||(q.translate=a,y()),u=!1});for(var v in p)p.hasOwnProperty(v)&&"translateAttr"===v.substr(0,13)&&t(v);if(p.$observe("translateDefault",function(a){b.defaultText=a,y()}),j&&p.$observe("translateValues",function(a){a&&b.$parent.$watch(function(){angular.extend(b.interpolateParams,e(a)(b.$parent))})}),l){var w=function(a){p.$observe(a,function(c){var d=angular.lowercase(a.substr(14,1))+a.substr(15);b.interpolateParams[d]=c})};for(var x in p)Object.prototype.hasOwnProperty.call(p,x)&&"translateValue"===x.substr(0,14)&&"translateValues"!==x&&w(x)}var y=function(){for(var a in q)q.hasOwnProperty(a)&&void 0!==q[a]&&z(a,q[a],b,b.interpolateParams,b.defaultText,b.translateNamespace)},z=function(b,c,d,e,f,g){c?(g&&"."===c.charAt(0)&&(c=g+c),a(c,e,k,f,d.translateLanguage).then(function(a){A(a,d,!0,b)},function(a){A(a,d,!1,b)})):A(c,d,!1,b)},A=function(b,c,e,f){if(e||"undefined"!=typeof c.defaultText&&(b=c.defaultText),"translate"===f){(e||!e&&"undefined"==typeof p.translateKeepContent)&&o.empty().append(c.preText+b+c.postText);var g=a.isPostCompilingEnabled(),h="undefined"!=typeof i.translateCompile,j=h&&"false"!==i.translateCompile;(g&&!h||j)&&d(o.contents())(c)}else{var k=p.$attr[f];"data-"===k.substr(0,5)&&(k=k.substr(5)),k=k.substr(15),o.attr(k,b)}};(j||l||p.translateDefault)&&b.$watch("interpolateParams",y,!0);var B=b.$on("translateLanguageChanged",y),C=g.$on("$translateChangeSuccess",y);o.text().length?s(p.translate?p.translate:""):p.translate&&s(p.translate),y(),b.$on("$destroy",function(){B(),C()})}}}}function f(a){return a.translateNamespace?a.translateNamespace:a.$parent?f(a.$parent):void 0}function g(a,b){return{compile:function(c){var d=function(){c.addClass(a.cloakClassName())},e=function(){c.removeClass(a.cloakClassName())};return a.onReady(function(){e()}),d(),function(c,f,g){g.translateCloak&&g.translateCloak.length&&(g.$observe("translateCloak",function(b){a(b).then(e,d)}),b.$on("$translateChangeSuccess",function(){a(g.translateCloak).then(e,d)}))}}}}function h(){return{restrict:"A",scope:!0,compile:function(){return{pre:function(a,b,c){a.translateNamespace=f(a),a.translateNamespace&&"."===c.translateNamespace.charAt(0)?a.translateNamespace+=c.translateNamespace:a.translateNamespace=c.translateNamespace}}}}}function f(a){return a.translateNamespace?a.translateNamespace:a.$parent?f(a.$parent):void 0}function i(){return{restrict:"A",scope:!0,compile:function(){return function(a,b,c){c.$observe("translateLanguage",function(b){a.translateLanguage=b}),a.$watch("translateLanguage",function(){a.$broadcast("translateLanguageChanged")})}}}}function j(a,b){var c=function(c,d,e,f){return angular.isObject(d)||(d=a(d)(this)),b.instant(c,d,e,f)};return b.statefulFilter()&&(c.$stateful=!0),c}function k(a){return a("translations")}return a.$inject=["$translate"],c.$inject=["$STORAGE_KEY","$windowProvider","$translateSanitizationProvider","pascalprechtTranslateOverrider"],d.$inject=["$interpolate","$translateSanitization"],e.$inject=["$translate","$q","$interpolate","$compile","$parse","$rootScope"],g.$inject=["$translate","$rootScope"],j.$inject=["$parse","$translate"],k.$inject=["$cacheFactory"],angular.module("pascalprecht.translate",["ng"]).run(a),a.displayName="runTranslate",angular.module("pascalprecht.translate").provider("$translateSanitization",b),angular.module("pascalprecht.translate").constant("pascalprechtTranslateOverrider",{}).provider("$translate",c),c.displayName="displayName",angular.module("pascalprecht.translate").factory("$translateDefaultInterpolation",d),d.displayName="$translateDefaultInterpolation",angular.module("pascalprecht.translate").constant("$STORAGE_KEY","NG_TRANSLATE_LANG_KEY"),angular.module("pascalprecht.translate").directive("translate",e),e.displayName="translateDirective",angular.module("pascalprecht.translate").directive("translateCloak",g),g.displayName="translateCloakDirective",angular.module("pascalprecht.translate").directive("translateNamespace",h),h.displayName="translateNamespaceDirective",angular.module("pascalprecht.translate").directive("translateLanguage",i),i.displayName="translateLanguageDirective",angular.module("pascalprecht.translate").filter("translate",j),j.displayName="translateFilterFactory",angular.module("pascalprecht.translate").factory("$translationCache",k),k.displayName="$translationCache","pascalprecht.translate"}),!function(){function a(a,b){window.XMLHttpRequest.prototype[a]=b(window.XMLHttpRequest.prototype[a])}function b(a,b,c){try{Object.defineProperty(a,b,{get:c})}catch(d){}}if(window.FileAPI||(window.FileAPI={}),!window.XMLHttpRequest)throw"AJAX is not supported. XMLHttpRequest is not defined.";if(FileAPI.shouldLoad=!window.FormData||FileAPI.forceLoad,FileAPI.shouldLoad){var c=function(a){if(!a.__listeners){a.upload||(a.upload={}),a.__listeners=[];var b=a.upload.addEventListener;a.upload.addEventListener=function(c,d){a.__listeners[c]=d,b&&b.apply(this,arguments)}}};a("open",function(a){return function(b,d,e){c(this),this.__url=d;try{a.apply(this,[b,d,e])}catch(f){f.message.indexOf("Access is denied")>-1&&(this.__origError=f,a.apply(this,[b,"_fix_for_ie_crossdomain__",e]))}}}),a("getResponseHeader",function(a){return function(b){return this.__fileApiXHR&&this.__fileApiXHR.getResponseHeader?this.__fileApiXHR.getResponseHeader(b):null==a?null:a.apply(this,[b])}}),a("getAllResponseHeaders",function(a){return function(){return this.__fileApiXHR&&this.__fileApiXHR.getAllResponseHeaders?this.__fileApiXHR.getAllResponseHeaders():null==a?null:a.apply(this)}}),a("abort",function(a){return function(){return this.__fileApiXHR&&this.__fileApiXHR.abort?this.__fileApiXHR.abort():null==a?null:a.apply(this)}}),a("setRequestHeader",function(a){return function(b,d){if("__setXHR_"===b){c(this);var e=d(this);e instanceof Function&&e(this)}else this.__requestHeaders=this.__requestHeaders||{},this.__requestHeaders[b]=d,a.apply(this,arguments)}}),a("send",function(a){return function(){var c=this;if(arguments[0]&&arguments[0].__isFileAPIShim){var d=arguments[0],e={url:c.__url,jsonp:!1,cache:!0,complete:function(a,d){a&&angular.isString(a)&&-1!==a.indexOf("#2174")&&(a=null),c.__completed=!0,!a&&c.__listeners.load&&c.__listeners.load({type:"load",loaded:c.__loaded,total:c.__total,target:c,lengthComputable:!0}),!a&&c.__listeners.loadend&&c.__listeners.loadend({type:"loadend",loaded:c.__loaded,total:c.__total,target:c,lengthComputable:!0}),"abort"===a&&c.__listeners.abort&&c.__listeners.abort({type:"abort",loaded:c.__loaded,total:c.__total,target:c,lengthComputable:!0}),void 0!==d.status&&b(c,"status",function(){return 0===d.status&&a&&"abort"!==a?500:d.status}),void 0!==d.statusText&&b(c,"statusText",function(){return d.statusText}),b(c,"readyState",function(){return 4}),void 0!==d.response&&b(c,"response",function(){return d.response});var e=d.responseText||(a&&0===d.status&&"abort"!==a?a:void 0);b(c,"responseText",function(){return e}),b(c,"response",function(){return e}),a&&b(c,"err",function(){return a}),c.__fileApiXHR=d,c.onreadystatechange&&c.onreadystatechange(),c.onload&&c.onload()},progress:function(a){if(a.target=c,c.__listeners.progress&&c.__listeners.progress(a),c.__total=a.total,c.__loaded=a.loaded,a.total===a.loaded){var b=this;setTimeout(function(){c.__completed||(c.getAllResponseHeaders=function(){},b.complete(null,{status:204,statusText:"No Content"}))},FileAPI.noContentTimeout||1e4)}},headers:c.__requestHeaders};e.data={},e.files={};for(var f=0;f-1){e=h.substring(0,g+1);break}null==FileAPI.staticPath&&(FileAPI.staticPath=e),i.setAttribute("src",d||e+"FileAPI.min.js"),document.getElementsByTagName("head")[0].appendChild(i)}FileAPI.ngfFixIE=function(d,e,f){if(!b())throw'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"';var g=function(){var b=e.parent();d.attr("disabled")?b&&b.removeClass("js-fileapi-wrapper"):(e.attr("__ngf_flash_")||(e.unbind("change"),e.unbind("click"),e.bind("change",function(a){h.apply(this,[a]),f.apply(this,[a])}),e.attr("__ngf_flash_","true")),b.addClass("js-fileapi-wrapper"),a(d)||(b.css("position","absolute").css("top",c(d[0]).top+"px").css("left",c(d[0]).left+"px").css("width",d[0].offsetWidth+"px").css("height",d[0].offsetHeight+"px").css("filter","alpha(opacity=0)").css("display",d.css("display")).css("overflow","hidden").css("z-index","900000").css("visibility","visible"),e.css("width",d[0].offsetWidth+"px").css("height",d[0].offsetHeight+"px").css("position","absolute").css("top","0px").css("left","0px")))};d.bind("mouseenter",g);var h=function(a){for(var b=FileAPI.getFiles(a),c=0;c0},this.rename=function(a,b){return a.ngfName=b,a},this.jsonBlob=function(a){null==a||angular.isString(a)||(a=JSON.stringify(a));var b=new window.Blob([a],{type:"application/json"});return b._ngfBlob=!0,b},this.json=function(a){return angular.toJson(a)},this.isFile=function(a){return null!=a&&(a instanceof window.Blob||a.flashId&&a.name&&a.size)},this.upload=function(a,b){function c(b,c){if(b._ngfBlob)return b;if(a._file=a._file||b,null!=a._start&&g){a._end&&a._end>=b.size&&(a._finished=!0,a._end=b.size);var d=b.slice(a._start,a._end||b.size);return d.name=b.name,d.ngfName=b.ngfName,a._chunkSize&&(c.append("_chunkSize",a._chunkSize),c.append("_currentChunkSize",a._end-a._start),c.append("_chunkNumber",Math.floor(a._start/a._chunkSize)),c.append("_totalSize",a._file.size)),d}return b}function h(b,d,e){if(void 0!==d)if(angular.isDate(d)&&(d=d.toISOString()),angular.isString(d))b.append(e,d);else if(f.isFile(d)){var g=c(d,b),i=e.split(",");i[1]&&(g.ngfName=i[1].replace(/^\s+|\s+$/g,""),e=i[0]),a._fileKey=a._fileKey||e,b.append(e,g,g.ngfName||g.name)}else if(angular.isObject(d)){if(d.$$ngfCircularDetection)throw"ngFileUpload: Circular reference in config.data. Make sure specified data for Upload.upload() has no circular reference: "+e;d.$$ngfCircularDetection=!0;try{for(var j in d)if(d.hasOwnProperty(j)&&"$$ngfCircularDetection"!==j){var k=null==a.objectKey?"[i]":a.objectKey;d.length&&parseInt(j)>-1&&(k=null==a.arrayKey?k:a.arrayKey),h(b,d[j],e+k.replace(/[ik]/g,j))}}finally{delete d.$$ngfCircularDetection}}else b.append(e,d)}function i(){a._chunkSize=f.translateScalars(a.resumeChunkSize),a._chunkSize=a._chunkSize?parseInt(a._chunkSize.toString()):null,a.headers=a.headers||{},a.headers["Content-Type"]=void 0,a.transformRequest=a.transformRequest?angular.isArray(a.transformRequest)?a.transformRequest:[a.transformRequest]:[],a.transformRequest.push(function(b){var c,d=new window.FormData;b=b||a.fields||{},a.file&&(b.file=a.file);for(c in b)if(b.hasOwnProperty(c)){var e=b[c];a.formDataAppender?a.formDataAppender(d,c,e):h(d,e,c)}return d})}return b||(a=e(a)),a._isDigested||(a._isDigested=!0,i()),d(a)},this.http=function(b){return b=e(b),b.transformRequest=b.transformRequest||function(b){return window.ArrayBuffer&&b instanceof window.ArrayBuffer||b instanceof window.Blob?b:a.defaults.transformRequest[0].apply(this,arguments)},b._chunkSize=f.translateScalars(b.resumeChunkSize),b._chunkSize=b._chunkSize?parseInt(b._chunkSize.toString()):null,d(b)},this.translateScalars=function(a){if(angular.isString(a)){if(a.search(/kb/i)===a.length-2)return parseFloat(1024*a.substring(0,a.length-2));if(a.search(/mb/i)===a.length-2)return parseFloat(1048576*a.substring(0,a.length-2));if(a.search(/gb/i)===a.length-2)return parseFloat(1073741824*a.substring(0,a.length-2));if(a.search(/b/i)===a.length-1)return parseFloat(a.substring(0,a.length-1));if(a.search(/s/i)===a.length-1)return parseFloat(a.substring(0,a.length-1));if(a.search(/m/i)===a.length-1)return parseFloat(60*a.substring(0,a.length-1));if(a.search(/h/i)===a.length-1)return parseFloat(3600*a.substring(0,a.length-1))}return a},this.urlToBlob=function(c){var d=b.defer();return a({url:c,method:"get",responseType:"arraybuffer"}).then(function(a){var b=new Uint8Array(a.data),c=a.headers("content-type")||"image/WebP",e=new window.Blob([b],{type:c});d.resolve(e)},function(a){d.reject(a)}),d.promise},this.setDefaults=function(a){this.defaults=a||{}},this.defaults={},this.version=ngFileUpload.version}]),ngFileUpload.service("Upload",["$parse","$timeout","$compile","$q","UploadExif",function(a,b,c,d,e){function f(a,b,c){var e=[i.emptyPromise()];return angular.forEach(a,function(d,f){0===d.type.indexOf("image/jpeg")&&i.attrGetter("ngfFixOrientation",b,c,{$file:d})&&e.push(i.happyPromise(i.applyExifRotation(d),d).then(function(b){a.splice(f,1,b)}))}),d.all(e)}function g(a,b,c){var e=i.attrGetter("ngfResize",b,c);if(!e||!i.isResizeSupported()||!a.length)return i.emptyPromise();if(!(e instanceof Function))return h(e,a,b,c);var f=d.defer();e(a).then(function(d){h(d,a,b,c).then(function(a){f.resolve(a)},function(a){f.reject(a)})},function(a){f.reject(a)})}function h(a,b,c,e){function f(d,f){if(0===d.type.indexOf("image")){if(a.pattern&&!i.validatePattern(d,a.pattern))return;var h=i.resize(d,a.width,a.height,a.quality,a.type,a.ratio,a.centerCrop,function(a,b){return i.attrGetter("ngfResizeIf",c,e,{$width:a,$height:b,$file:d})},a.restoreExif!==!1);g.push(h),h.then(function(a){b.splice(f,1,a)},function(a){d.$error="resize",d.$errorParam=(a?(a.message?a.message:a)+": ":"")+(d&&d.name)})}}for(var g=[i.emptyPromise()],h=0;h-1},i.emptyPromise=function(){var a=d.defer(),c=arguments;return b(function(){a.resolve.apply(a,c)}),a.promise},i.rejectPromise=function(){var a=d.defer(),c=arguments;return b(function(){a.reject.apply(a,c)}),a.promise},i.happyPromise=function(a,c){var e=d.defer();return a.then(function(a){e.resolve(a)},function(a){b(function(){throw a}),e.resolve(c)}),e.promise},i.updateModel=function(c,d,e,h,j,k,l){function m(f,g,j,l,m){d.$$ngfPrevValidFiles=f,d.$$ngfPrevInvalidFiles=g;var n=f&&f.length?f[0]:null,o=g&&g.length?g[0]:null;c&&(i.applyModelValidation(c,f),c.$setViewValue(m?n:f)),h&&a(h)(e,{$files:f,$file:n,$newFiles:j,$duplicateFiles:l,$invalidFiles:g,$invalidFile:o,$event:k});var p=i.attrGetter("ngfModelInvalid",d);p&&b(function(){a(p).assign(e,m?o:g)}),b(function(){})}function n(){function a(a,b){return a.name===b.name&&(a.$ngfOrigSize||a.size)===(b.$ngfOrigSize||b.size)&&a.type===b.type}function b(b){var c;for(c=0;c2){var c=d.defaults.androidFixMinorVersion||4;return parseInt(b[1])<4||parseInt(b[1])===c&&parseInt(b[2])');n(a);var c=angular.element("");return c.css("visibility","hidden").css("position","absolute").css("overflow","hidden").css("width","0px").css("height","0px").css("border","none").css("margin","0px").css("padding","0px").attr("tabindex","-1"),g.push({el:b,ref:c}),document.body.appendChild(c.append(a)[0]),a}function p(c){if(b.attr("disabled"))return!1;if(!t("ngfSelectDisabled",a)){var d=q(c);if(null!=d)return d;r(c);try{k()||document.body.contains(w[0])||(g.push({el:b,ref:w.parent()}),document.body.appendChild(w.parent()[0]),w.bind("change",m))}catch(f){}return e(navigator.userAgent)?setTimeout(function(){w[0].click()},0):w[0].click(),!1}}function q(a){var b=a.changedTouches||a.originalEvent&&a.originalEvent.changedTouches;if("touchstart"===a.type)return v=b?b[0].clientY:0,!0;if(a.stopPropagation(),a.preventDefault(),"touchend"===a.type){var c=b?b[0].clientY:0;if(Math.abs(c-v)>20)return!1}}function r(b){j.shouldUpdateOn("click",c,a)&&w.val()&&(w.val(null),j.updateModel(d,c,a,l(),null,b,!0))}function s(a){if(w&&!w.attr("__ngf_ie10_Fix_")){if(!w[0].parentNode)return void(w=null);a.preventDefault(),a.stopPropagation(),w.unbind("click");var b=w.clone();return w.replaceWith(b),w=b,w.attr("__ngf_ie10_Fix_","true"),w.bind("change",m),w.bind("click",s),w[0].click(),!1}w.removeAttr("__ngf_ie10_Fix_")}var t=function(a,b){return j.attrGetter(a,c,b)};j.registerModelChangeValidator(d,c,a);var u=[];u.push(a.$watch(t("ngfMultiple"),function(){w.attr("multiple",t("ngfMultiple",a))})),u.push(a.$watch(t("ngfCapture"),function(){w.attr("capture",t("ngfCapture",a))})),u.push(a.$watch(t("ngfAccept"),function(){w.attr("accept",t("ngfAccept",a))})),c.$observe("accept",function(){w.attr("accept",t("accept"))}),u.push(function(){c.$$observers&&delete c.$$observers.accept});var v=0,w=b;k()||(w=o()),w.bind("change",m),k()?b.bind("click",r):b.bind("click touchstart touchend",p),-1!==navigator.appVersion.indexOf("MSIE 10")&&w.bind("click",s),d&&d.$formatters.push(function(a){return(null==a||0===a.length)&&w.val()&&w.val(null),a}),a.$on("$destroy",function(){k()||w.parent().remove(),angular.forEach(u,function(a){a()})}),h(function(){for(var a=0;ab||d.blobUrls.length>e)&&d.blobUrls.length>1;){var h=d.blobUrls.splice(0,1)[0];c.revokeObjectURL(h.url),d.blobUrlsTotalSize-=h.size}}})}else{var i=new FileReader;i.onload=function(c){b(function(){a.$ngfDataUrl=c.target.result,g.resolve(c.target.result,a),b(function(){delete a.$ngfDataUrl},1e3)})},i.onerror=function(){b(function(){a.$ngfDataUrl="",g.reject()})},i.readAsDataURL(a)}}else b(function(){a[e?"$ngfDataUrl":"$ngfBlobUrl"]="",g.reject()})}),f=e?a.$$ngfDataUrlPromise=g.promise:a.$$ngfBlobUrlPromise=g.promise,f["finally"](function(){delete a[e?"$$ngfDataUrlPromise":"$$ngfBlobUrlPromise"]}),f},d}]),ngFileUpload.directive("ngfSrc",["Upload","$timeout",function(a,c){return{restrict:"AE",link:function(d,e,f){b(a,c,d,e,f,"ngfSrc",a.attrGetter("ngfResize",f,d),!1)}}}]),ngFileUpload.directive("ngfBackground",["Upload","$timeout",function(a,c){return{restrict:"AE",link:function(d,e,f){b(a,c,d,e,f,"ngfBackground",a.attrGetter("ngfResize",f,d),!0)}}}]),ngFileUpload.directive("ngfThumbnail",["Upload","$timeout",function(a,c){return{restrict:"AE",link:function(d,e,f){var g=a.attrGetter("ngfSize",f,d);b(a,c,d,e,f,"ngfThumbnail",g,a.attrGetter("ngfAsBackground",f,d))}}}]),ngFileUpload.config(["$compileProvider",function(a){a.imgSrcSanitizationWhitelist&&a.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|local|file|data|blob):/),a.aHrefSanitizationWhitelist&&a.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|local|file|data|blob):/)}]),ngFileUpload.filter("ngfDataUrl",["UploadDataUrl","$sce",function(a,b){return function(c,d,e){if(angular.isString(c))return b.trustAsResourceUrl(c);var f=c&&((d?c.$ngfDataUrl:c.$ngfBlobUrl)||c.$ngfDataUrl);return c&&!f?(!c.$ngfDataUrlFilterInProgress&&angular.isObject(c)&&(c.$ngfDataUrlFilterInProgress=!0,a.dataUrl(c,d)),""):(c&&delete c.$ngfDataUrlFilterInProgress,(c&&f?e?b.trustAsResourceUrl(f):f:c)||"")}}])}(),ngFileUpload.service("UploadValidate",["UploadDataUrl","$q","$timeout",function(a,b,c){function d(a){var b="",c=[];if(a.length>2&&"/"===a[0]&&"/"===a[a.length-1])b=a.substring(1,a.length-1);else{var e=a.split(",");if(e.length>1)for(var f=0;f|:\\-]","g"),"\\$&")+"$",b=b.replace(/\\\*/g,".*").replace(/\\\?/g,"."))}return{regexp:b,excludes:c}}function e(a,b){null==b||a.$dirty||(a.$setDirty?a.$setDirty():a.$dirty=!0)}var f=a;return f.validatePattern=function(a,b){if(!b)return!0;var c=d(b),e=!0;if(c.regexp&&c.regexp.length){var f=new RegExp(c.regexp,"i");e=null!=a.type&&f.test(a.type)||null!=a.name&&f.test(a.name)}for(var g=c.excludes.length;g--;){var h=new RegExp(c.excludes[g],"i");e=e&&(null==a.type||h.test(a.type))&&(null==a.name||h.test(a.name))}return e},f.ratioToFloat=function(a){var b=a.toString(),c=b.search(/[x:]/i);return b=c>-1?parseFloat(b.substring(0,c))/parseFloat(b.substring(c+1)):parseFloat(b)},f.registerModelChangeValidator=function(a,b,c){a&&a.$formatters.push(function(d){a.$dirty&&(d&&!angular.isArray(d)&&(d=[d]),f.validate(d,0,a,b,c).then(function(){f.applyModelValidation(a,d)}))})},f.applyModelValidation=function(a,b){e(a,b),angular.forEach(a.$ngfValidations,function(b){a.$setValidity(b.name,b.valid)})},f.getValidationAttr=function(a,b,c,d,e){var g="ngf"+c[0].toUpperCase()+c.substr(1),h=f.attrGetter(g,a,b,{$file:e});if(null==h&&(h=f.attrGetter("ngfValidate",a,b,{$file:e}))){var i=(d||c).split(".");h=h[i[0]],i.length>1&&(h=h&&h[i[1]])}return h},f.validate=function(a,c,d,e,g){function h(b,c,h){if(a){for(var i=a.length,j=null;i--;){var k=a[i];if(k){var l=f.getValidationAttr(e,g,b,c,k);null!=l&&(h(k,l,i)||(k.$error=b,(k.$errorMessages=k.$errorMessages||{})[b]=!0,k.$errorParam=l,a.splice(i,1),j=!1))}}null!==j&&d.$ngfValidations.push({name:b,valid:j})}}function i(c,h,i,k,l){function m(a,b,d){null!=d?k(b,d).then(function(e){l(e,d)?a.resolve():(b.$error=c,(b.$errorMessages=b.$errorMessages||{})[c]=!0,b.$errorParam=d,a.reject())},function(){j("ngfValidateForce",{$file:b})?(b.$error=c,(b.$errorMessages=b.$errorMessages||{})[c]=!0,b.$errorParam=d,a.reject()):a.resolve()}):a.resolve()}var n=[f.emptyPromise()];return a?(a=void 0===a.length?[a]:a,angular.forEach(a,function(a){var d=b.defer();return n.push(d.promise),!i||null!=a.type&&0===a.type.search(i)?void("dimensions"===c&&null!=f.attrGetter("ngfDimensions",e)?f.imageDimensions(a).then(function(b){m(d,a,j("ngfDimensions",{$file:a,$width:b.width,$height:b.height}))},function(){d.reject()}):"duration"===c&&null!=f.attrGetter("ngfDuration",e)?f.mediaDuration(a).then(function(b){m(d,a,j("ngfDuration",{$file:a,$duration:b}))},function(){d.reject()}):m(d,a,f.getValidationAttr(e,g,c,h,a))):void d.resolve()}),b.all(n).then(function(){d.$ngfValidations.push({name:c,valid:!0})},function(){d.$ngfValidations.push({name:c,valid:!1})})):void 0}d=d||{},d.$ngfValidations=d.$ngfValidations||[],angular.forEach(d.$ngfValidations,function(a){a.valid=!0});var j=function(a,b){return f.attrGetter(a,e,g,b)};if(null==a||0===a.length)return f.emptyPromise(d);a=void 0===a.length?[a]:a.slice(0),h("maxFiles",null,function(a,b,d){return b>c+d}),h("pattern",null,f.validatePattern),h("minSize","size.min",function(a,b){return a.size+.1>=f.translateScalars(b)}),h("maxSize","size.max",function(a,b){return a.size-.1<=f.translateScalars(b)});var k=0;if(h("maxTotalSize",null,function(b,c){return k+=b.size,!(k>f.translateScalars(c))||(a.splice(0,a.length),!1)}),h("validateFn",null,function(a,b){return b===!0||null===b||""===b}),!a.length)return f.emptyPromise(d,d.$ngfValidations);var l=b.defer(),m=[];return m.push(f.happyPromise(i("maxHeight","height.max",/image/,this.imageDimensions,function(a,b){return a.height<=b}))),m.push(f.happyPromise(i("minHeight","height.min",/image/,this.imageDimensions,function(a,b){return a.height>=b}))),m.push(f.happyPromise(i("maxWidth","width.max",/image/,this.imageDimensions,function(a,b){return a.width<=b}))),m.push(f.happyPromise(i("minWidth","width.min",/image/,this.imageDimensions,function(a,b){return a.width>=b}))),m.push(f.happyPromise(i("dimensions",null,/image/,function(a,b){return f.emptyPromise(b)},function(a){return a}))),m.push(f.happyPromise(i("ratio",null,/image/,this.imageDimensions,function(a,b){for(var c=b.toString().split(","),d=!1,e=0;e-1e-4}))),m.push(f.happyPromise(i("maxDuration","duration.max",/audio|video/,this.mediaDuration,function(a,b){return a<=f.translateScalars(b)}))),m.push(f.happyPromise(i("minDuration","duration.min",/audio|video/,this.mediaDuration,function(a,b){return a>=f.translateScalars(b)}))),m.push(f.happyPromise(i("duration",null,/audio|video/,function(a,b){return f.emptyPromise(b)},function(a){return a}))),m.push(f.happyPromise(i("validateAsyncFn",null,null,function(a,b){return b},function(a){return a===!0||null===a||""===a}))),b.all(m).then(function(){l.resolve(d,d.$ngfValidations)})},f.imageDimensions=function(a){if(a.$ngfWidth&&a.$ngfHeight){var d=b.defer();return c(function(){d.resolve({width:a.$ngfWidth,height:a.$ngfHeight})}),d.promise}if(a.$ngfDimensionPromise)return a.$ngfDimensionPromise;var e=b.defer();return c(function(){return 0!==a.type.indexOf("image")?void e.reject("not image"):void f.dataUrl(a).then(function(b){function d(){var b=h[0].clientWidth,c=h[0].clientHeight;h.remove(),a.$ngfWidth=b,a.$ngfHeight=c,e.resolve({width:b,height:c})}function f(){h.remove(),e.reject("load error")}function g(){c(function(){h[0].parentNode&&(h[0].clientWidth?d():i>10?f():g())},1e3)}var h=angular.element("").attr("src",b).css("visibility","hidden").css("position","fixed").css("max-width","none !important").css("max-height","none !important");h.on("load",d),h.on("error",f);var i=0;g(),angular.element(document.getElementsByTagName("body")[0]).append(h)},function(){e.reject("load error")})}),a.$ngfDimensionPromise=e.promise,a.$ngfDimensionPromise["finally"](function(){delete a.$ngfDimensionPromise}),a.$ngfDimensionPromise},f.mediaDuration=function(a){if(a.$ngfDuration){var d=b.defer();return c(function(){d.resolve(a.$ngfDuration)}),d.promise}if(a.$ngfDurationPromise)return a.$ngfDurationPromise;var e=b.defer();return c(function(){return 0!==a.type.indexOf("audio")&&0!==a.type.indexOf("video")?void e.reject("not media"):void f.dataUrl(a).then(function(b){function d(){var b=h[0].duration;a.$ngfDuration=b,h.remove(),e.resolve(b)}function f(){h.remove(),e.reject("load error")}function g(){c(function(){h[0].parentNode&&(h[0].duration?d():i>10?f():g())},1e3)}var h=angular.element(0===a.type.indexOf("audio")?"