diff --git a/awx/ui/client/src/app.js b/awx/ui/client/src/app.js
index 2804ca7f09..362e89770a 100644
--- a/awx/ui/client/src/app.js
+++ b/awx/ui/client/src/app.js
@@ -177,14 +177,12 @@ var tower = angular.module('Tower', [
'LogViewerOptionsDefinition',
'EventViewerHelper',
'HostEventsViewerHelper',
- 'SurveyHelper',
'JobDetailHelper',
'SocketIO',
'lrInfiniteScroll',
'LoadConfigHelper',
'SocketHelper',
'AboutAnsibleHelpModal',
- 'SurveyQuestionFormDefinition',
'PortalJobsListDefinition',
diff --git a/awx/ui/client/src/controllers/JobTemplates.js b/awx/ui/client/src/controllers/JobTemplates.js
index 9b579bf00b..93fbc9175a 100644
--- a/awx/ui/client/src/controllers/JobTemplates.js
+++ b/awx/ui/client/src/controllers/JobTemplates.js
@@ -654,7 +654,7 @@ export function JobTemplatesAdd($filter, $scope, $rootScope, $compile, $location
JobTemplatesAdd.$inject = ['$filter', '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobTemplateForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope',
'GetBasePath', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit',
- 'md5Setup', 'ParseTypeChange', 'Wait', 'Empty', 'ToJSON', 'CallbackHelpInit', 'SurveyControllerInit', 'Prompt', 'GetChoices'
+ 'md5Setup', 'ParseTypeChange', 'Wait', 'Empty', 'ToJSON', 'CallbackHelpInit', 'initSurvey', 'Prompt', 'GetChoices'
];
@@ -1231,5 +1231,5 @@ JobTemplatesEdit.$inject = ['$filter', '$scope', '$rootScope', '$compile', '$loc
'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit',
'GetBasePath', 'md5Setup', 'ParseTypeChange', 'JobStatusToolTip', 'FormatDate', 'Wait', 'Stream', 'Empty', 'Prompt',
'ParseVariableString', 'ToJSON', 'SchedulesControllerInit', 'JobsControllerInit', 'JobsListUpdate', 'GetChoices',
- 'SchedulesListInit', 'SchedulesList', 'CallbackHelpInit', 'PlaybookRun' , 'SurveyControllerInit'
+ 'SchedulesListInit', 'SchedulesList', 'CallbackHelpInit', 'PlaybookRun' , 'initSurvey'
];
diff --git a/awx/ui/client/src/forms.js b/awx/ui/client/src/forms.js
index 1620543189..5ac8de52d0 100644
--- a/awx/ui/client/src/forms.js
+++ b/awx/ui/client/src/forms.js
@@ -27,7 +27,6 @@ import Permissions from "./forms/Permissions";
import ProjectStatus from "./forms/ProjectStatus";
import Projects from "./forms/Projects";
import Source from "./forms/Source";
-import SurveyQuestion from "./forms/SurveyQuestion";
import Teams from "./forms/Teams";
import Users from "./forms/Users";
@@ -56,7 +55,6 @@ export
ProjectStatus,
Projects,
Source,
- SurveyQuestion,
Teams,
Users
};
diff --git a/awx/ui/client/src/forms/SurveyQuestion.js b/awx/ui/client/src/forms/SurveyQuestion.js
deleted file mode 100644
index 4d575799b0..0000000000
--- a/awx/ui/client/src/forms/SurveyQuestion.js
+++ /dev/null
@@ -1,304 +0,0 @@
-/*************************************************
- * Copyright (c) 2015 Ansible, Inc.
- *
- * All Rights Reserved
- *************************************************/
-
- /**
- * @ngdoc function
- * @name forms.function:Questions
- * @description This form is for adding a question
-*/
-
-export default
- angular.module('SurveyQuestionFormDefinition', [])
- .value('SurveyQuestionForm', {
-
- addTitle: 'Add Question',
- editTitle: 'Edit Question',
- base: 'survey_question',
- name: 'survey_question',
- well: true,
- twoColumns: true,
- breadcrumbs: false,
-
- fields: {
- question_name: {
- realName: 'question_text',
- label: 'Name',
- type: 'text',
- addRequired: true,
- editRequired: true,
- column: 1,
- awSurveyQuestion: true
- },
- question_description: {
- realName: 'question_description',
- label: 'Description',
- type: 'text',
- addRequired: false,
- editRequired: false,
- column: 1
- },
- variable: {
- ealName: 'variable',
- type: 'custom',
- control:''+
- '
'+
- '
Please enter an answer variable name.
'+
- '
Please remove the illegal character from the survey question variable name.
'+
- '
This question variable is already in use. Please enter a different variable name.
' +
- '
'+
- '
',
- addRequired: true,
- editRequired: true,
- column: 1
- },
- type: {
- realName: 'answer_type',
- label: 'Answer Type',
- type: 'select',
- defaultText: 'Choose an answer type',
- ngOptions: 'answer_types.name for answer_types in answer_types track by answer_types.type',
- addRequired: true,
- editRequired: true,
- column: 2,
- ngChange: 'typeChange()'
- },
- choices: {
- realName: 'answer_options',
- label: 'Multiple Choice Options',
- type: 'textarea',
- rows: 3,
- addRequired: true,
- editRequired: true,
- ngRequired: "type.type=== 'multiselect' || type.type=== 'multiplechoice' " ,
- ngShow: 'type.type=== "multiselect" || type.type=== "multiplechoice" ',
- awPopOver: 'Type an option on each line.
'+
- 'For example the following input:
Apple
\n Banana
\n Cherry
would be displayed as:
\n'+
- '- Apple
- Banana
- Cherry
',
- dataTitle: 'Multiple Choice Options',
- dataPlacement: 'right',
- dataContainer: "body",
- column: 2
- },
- text_options: {
- realName: 'answer_options',
- type: 'custom',
- control:''+
- '
'+
- '
'+
- '
The minimum length you entered is not a valid number. Please enter a whole number.
'+
- '
The minimium length is too high. Please enter a lower number.
'+
- '
The minimum length is too low. Please enter a positive number.
'+
- '
'+
- '
'+
- '
'+
- '
The maximum length you entered is not a valid number. Please enter a whole nnumber.
'+
- '
The maximum length is too low. Please enter a number larger than the minimum length you set.
'+
- '
'+
- '
',
- ngShow: 'type.type==="text" ',
- addRequired: true,
- editRequired: true,
- column: 2
- },
- textarea_options: {
- realName: 'answer_options',
- type: 'custom',
- control:''+
- '
'+
- '
'+
- '
The minimum length you entered is not a valid number. Please enter a whole number.
'+
- '
The minimium length is too high. Please enter a lower number.
'+
- '
The minimum length is too low. Please enter a positive number.
'+
- '
'+
- '
'+
- '
'+
- '
The maximum length you entered is not a valid number. Please enter a whole number.
'+
- '
The maximum length is too low. Please enter a number larger than the minimum length you set.
'+
- '
'+
- '
',
- ngShow: 'type.type==="textarea" ',
- addRequired: true,
- editRequired: true,
- column: 2
- },
- password_options: {
- realName: 'answer_options',
- type: 'custom',
- control:''+
- '
'+
- '
'+
- '
The minimum length you entered is not a valid number. Please enter a whole number.
'+
- '
The minimium length is too high. Please enter a lower number.
'+
- '
The minimum length is too low. Please enter a positive number.
'+
- '
'+
- '
'+
- '
'+
- '
The maximum length you entered is not a valid number. Please enter a whole number.
'+
- '
The maximum length is too low. Please enter a number larger than the minimum length you set.
'+
- '
'+
- '
',
- ngShow: 'type.type==="password" ',
- addRequired: true,
- editRequired: true,
- column: 2
- },
- int_options: {
- realName: 'answer_options',
- type: 'custom',
- control:''+
- '
'+
- '
'+
- '
Please enter a valid integer.
'+
- '
Please enter a smaller integer.
'+
- '
'+
- '
'+
- '
'+
- '
Please enter a valid integer.
'+
- '
Please enter a larger integer.
'+
- '
'+
- '
',
- ngShow: 'type.type==="integer" ',
- addRequired: true,
- editRequired: true,
- column: 2
- },
- float_options: {
- realName: 'answer_options',
- type: 'custom',
- control: ''+
- '
'+
- '
'+
- '
Please enter a valid float.
'+
- '
Please enter a smaller float.
'+
- '
'+
- '
'+
- '
'+
- '
Please enter a valid float.
'+
- '
Please enter a larger float.
'+
-
- '
'+
- '
',
- ngShow: 'type.type==="float" ',
- addRequired: true,
- editRequired: true,
- column: 2
- },
- default:{
- realName: 'default_answer',
- type: 'custom' ,
- control: '',
- column: 2,
- ngShow: 'type.type === "text" || type.type === "multiplechoice" '
- },
- default_multiselect: {
- realName: 'default_answer' ,
- type: 'custom',
- control: '',
- column: 2,
- ngShow: 'type.type==="multiselect" '
- },
- default_int: {
- realName: 'default_answer',
- type: 'custom',
- control: ''+
- '
'+
- '
'+
- '
Please enter a valid integer.
'+
- '
Please enter a value in the range of {{int_min}} to {{int_max}}.
'+
- '
',
- column: 2,
- ngShow: 'type.type === "integer" '
- },
- default_float: {
- realName: 'default_answer',
- type: 'custom',
- control: ''+
- '
'+
- '
'+
- '
Please enter a valid float.
'+
- '
Please enter a value in the range of {{float_min}} to {{float_max}}!
'+
- '
',
- column: 2,
- ngShow: 'type.type=== "float" '
- },
- default_textarea: {
- realName: "default_answer" ,
- type: 'custom',
- control: '',
- column : 2,
- ngShow: 'type.type === "textarea" '
- },
- default_password: {
- realName: 'default_answer' ,
- type: 'custom' ,
- control: '',
- column: 2,
- ngShow: 'type.type === "password" '
- },
- required: {
- realName: 'required_answer',
- label: 'Required',
- type: 'checkbox',
- addRequired: false,
- editRequired: false,
- column: 2
- }
- },
- buttons: {
- question_cancel : {
- label: 'Cancel',
- 'class' : 'btn btn-default',
- ngClick: 'cancelQuestion($event)'
- },
- submit_question: {
- ngClick: 'submitQuestion($event)',
- ngDisabled: true,
- 'class': 'btn btn-sm btn-primary',
- label: 'Add Question'
- }
- }
-
- });
diff --git a/awx/ui/client/src/helpers.js b/awx/ui/client/src/helpers.js
index 05a3f5b12f..be783b45a9 100644
--- a/awx/ui/client/src/helpers.js
+++ b/awx/ui/client/src/helpers.js
@@ -32,7 +32,6 @@ import Projects from "./helpers/Projects";
import Schedules from "./helpers/Schedules";
import Selection from "./helpers/Selection";
import SocketHelper from "./helpers/SocketHelper";
-import Survey from "./helpers/Survey";
import Users from "./helpers/Users";
import Variables from "./helpers/Variables";
import ApiDefaults from "./helpers/api-defaults";
@@ -71,7 +70,6 @@ export
Schedules,
Selection,
SocketHelper,
- Survey,
Users,
Variables,
ApiDefaults,
diff --git a/awx/ui/client/src/helpers/JobSubmission.js b/awx/ui/client/src/helpers/JobSubmission.js
index 473848b3cc..345183ab82 100644
--- a/awx/ui/client/src/helpers/JobSubmission.js
+++ b/awx/ui/client/src/helpers/JobSubmission.js
@@ -497,10 +497,10 @@ function($compile, Rest, GetBasePath, TextareaResize,CreateDialog, GenerateForm,
};
}])
- .factory('PromptForSurvey', ['$filter', '$compile', 'Wait', 'Alert', 'CredentialForm', 'CreateLaunchDialog', 'SurveyControllerInit' , 'GetBasePath', 'Rest' , 'Empty',
- 'GenerateForm', 'ShowSurveyModal', 'ProcessErrors', '$routeParams' ,
- function($filter, $compile, Wait, Alert, CredentialForm, CreateLaunchDialog, SurveyControllerInit, GetBasePath, Rest, Empty,
- GenerateForm, ShowSurveyModal, ProcessErrors, $routeParams) {
+ .factory('PromptForSurvey', ['$filter', '$compile', 'Wait', 'Alert', 'CredentialForm', 'CreateLaunchDialog', 'GetBasePath', 'Rest' , 'Empty',
+ 'GenerateForm', 'ProcessErrors', '$routeParams' ,
+ function($filter, $compile, Wait, Alert, CredentialForm, CreateLaunchDialog, GetBasePath, Rest, Empty,
+ GenerateForm, ProcessErrors, $routeParams) {
return function(params) {
var html = params.html || "",
id= params.id,
diff --git a/awx/ui/client/src/job-templates/main.js b/awx/ui/client/src/job-templates/main.js
index f38fce2023..f69679e350 100644
--- a/awx/ui/client/src/job-templates/main.js
+++ b/awx/ui/client/src/job-templates/main.js
@@ -5,7 +5,10 @@
*************************************************/
import deleteJobTemplate from './delete-job-template.service';
+import surveyMaker from './survey-maker/main';
export default
- angular.module('jobTemplates', [])
+ angular.module('jobTemplates',
+ [ surveyMaker.name
+ ])
.service('deleteJobTemplate', deleteJobTemplate);
diff --git a/awx/ui/client/src/job-templates/survey-maker/main.js b/awx/ui/client/src/job-templates/survey-maker/main.js
new file mode 100644
index 0000000000..38d30679d9
--- /dev/null
+++ b/awx/ui/client/src/job-templates/survey-maker/main.js
@@ -0,0 +1,12 @@
+import listGenerator from '../../shared/list-generator/main';
+import questions from './questions/main';
+import surveys from './surveys/main';
+import shared from './shared/main';
+
+export default
+ angular.module('jobTemplates.surveyMaker',
+ [ listGenerator.name,
+ questions.name,
+ surveys.name,
+ shared.name
+ ]);
diff --git a/awx/ui/client/src/job-templates/survey-maker/questions/edit.factory.js b/awx/ui/client/src/job-templates/survey-maker/questions/edit.factory.js
new file mode 100644
index 0000000000..6a4ab46eea
--- /dev/null
+++ b/awx/ui/client/src/job-templates/survey-maker/questions/edit.factory.js
@@ -0,0 +1,99 @@
+export default
+ function EditQuestion(GetBasePath, Rest, Wait, ProcessErrors, $compile, GenerateForm, SurveyQuestionForm) {
+ return function(params) {
+
+ var scope = params.scope,
+ index = params.index,
+ element,
+ tmpVar,
+ i,
+ question = params.question, //scope.survey_questions[index],
+ form = SurveyQuestionForm;
+
+ $('#survey-save-button').attr('disabled', 'disabled');
+ angular.element('#survey_question_question_cancel_btn').trigger('click');
+ $('#add_question_btn').hide();
+ // $('#new_question .aw-form-well').remove();
+ element = $('.question_final:eq('+index+')');
+ element.css('opacity', 1.0);
+ element.empty();
+ scope.text_min = null;
+ scope.text_max = null;
+ scope.int_min = null;
+ scope.int_max = null;
+ scope.float_min = null;
+ scope.float_max = null;
+ scope.password_min = null;
+ scope.password_max = null;
+ scope.pwcheckbox = false;
+
+ if (scope.removeFillQuestionForm) {
+ scope.removeFillQuestionForm();
+ }
+ scope.removeFillQuestionForm = scope.$on('FillQuestionForm', function() {
+ for( var fld in form.fields){
+ scope[fld] = question[fld];
+ if(form.fields[fld].type === 'select'){
+ for (i = 0; i < scope.answer_types.length; i++) {
+ if (question[fld] === scope.answer_types[i].type) {
+ scope[fld] = scope.answer_types[i];
+ }
+ }
+ }
+ }
+ if( question.type === 'text'){
+ scope.text_min = question.min;
+ scope.text_max = question.max;
+ scope.default_text = question.default;
+ }
+ if( question.type === 'textarea'){
+ scope.textarea_min = question.min;
+ scope.textarea_max = question.max;
+ scope.default_textarea= question.default;
+ }
+ if(question.type === 'password'){
+ scope.password_min = question.min;
+ scope.password_max = question.max;
+ scope.default_password = question.default;
+ }
+ if( question.type === 'integer'){
+ scope.int_min = question.min;
+ scope.int_max = question.max;
+ scope.default_int = question.default;
+ }
+ else if( question.type === 'float' ) {
+ scope.float_min = question.min;
+ scope.float_max = question.max;
+ scope.default_float = question.default;
+
+ }
+ else if ( question.type === 'multiselect'){
+ scope.default_multiselect = question.default;
+ }
+ });
+
+ if (scope.removeGenerateForm) {
+ scope.removeGenerateForm();
+ }
+ scope.removeGenerateForm = scope.$on('GenerateForm', function() {
+ tmpVar = scope.mode;
+ GenerateForm.inject(form, { id: 'question_'+index, mode: 'edit' , related: false, scope:scope, breadCrumbs: false});
+ scope.mode = tmpVar;
+ scope.$emit('FillQuestionForm');
+ });
+
+
+ scope.$emit('GenerateForm');
+
+ };
+ }
+
+EditQuestion.$inject =
+ [ 'GetBasePath',
+ 'Rest',
+ 'Wait',
+ 'ProcessErrors',
+ '$compile',
+ 'GenerateForm',
+ 'questionDefinitionForm'
+ ];
diff --git a/awx/ui/client/src/job-templates/survey-maker/questions/finalize.factory.js b/awx/ui/client/src/job-templates/survey-maker/questions/finalize.factory.js
new file mode 100644
index 0000000000..9c81ec8d37
--- /dev/null
+++ b/awx/ui/client/src/job-templates/survey-maker/questions/finalize.factory.js
@@ -0,0 +1,185 @@
+/**
+ * Takes a finalized question and displays it on the survey maker page
+ *
+ * FinalizeQuestion({
+ * scope: $scope containing list of survey form fields
+ * question: question object that was submitted by the question form
+ * id: id of job template that survey is attached to
+ * callback: $scope.$emit label to call when delete is completed
+ * })
+ *
+ */
+export default
+ function FinalizeQuestion(GetBasePath, Rest, Wait, ProcessErrors, $compile, Empty, $filter) {
+ return function(params) {
+
+ var scope = params.scope,
+ question = params.question,
+ index = params.index,
+ required,
+ element,
+ choices,
+ i,
+ checked,
+ max,
+ min,
+ defaultValue,
+ answers,
+ html = "";
+
+ question.index = index;
+ question.question_name = $filter('sanitize')(question.question_name);
+ question.question_description = (question.question_description) ? $filter('sanitize')(question.question_description) : undefined;
+
+
+ if(!$('#question_'+question.index+':eq(0)').is('div')){
+ html+='';
+ $('#finalized_questions').append(html);
+ }
+
+ required = (question.required===true) ? "prepend-asterisk" : "";
+ html = '';
+ html += '';
+ html += '
';
+
+ if(!Empty(question.question_description)){
+ html += ''+question.question_description+'
\n';
+ }
+
+ if(question.type === 'text' ){
+ defaultValue = (question.default) ? question.default : "";
+ defaultValue = $filter('sanitize')(defaultValue);
+ defaultValue = scope.serialize(defaultValue);
+ html+='';
+ }
+ if(question.type === "textarea"){
+ defaultValue = (question.default) ? question.default : (question.default_textarea) ? question.default_textarea: "" ;
+ defaultValue = $filter('sanitize')(defaultValue);
+ defaultValue = scope.serialize(defaultValue);
+ html+='';
+ }
+ if(question.type === 'multiplechoice' || question.type === "multiselect"){
+ choices = question.choices.split(/\n/);
+ element = (question.type==="multiselect") ? "checkbox" : 'radio';
+ question.default = (question.default) ? question.default : (question.default_multiselect) ? question.default_multiselect : "" ;
+ answers = question.default.split(/\n/);
+ html += '';
+ for( i = 0; i' +
+ ''+choices[i] +'
' ;
+ }
+ html += '
';
+ }
+
+ if(question.type === 'password'){
+ defaultValue = (question.default) ? question.default : "";
+ defaultValue = $filter('sanitize')(defaultValue);
+ defaultValue = scope.serialize(defaultValue);
+ html+=''+
+ '
'+
+ ''+
+ ''+
+ ''+
+ ''+
+ '
'+
+ '
';
+ }
+
+ if(question.type === 'integer'){
+ min = (!Empty(question.min)) ? question.min : "";
+ max = (!Empty(question.max)) ? question.max : "" ;
+ defaultValue = (!Empty(question.default)) ? question.default : (!Empty(question.default_int)) ? question.default_int : "" ;
+ html+='';
+
+ }
+ if(question.type === "float"){
+ min = (!Empty(question.min)) ? question.min : "";
+ max = (!Empty(question.max)) ? question.max : "" ;
+ defaultValue = (!Empty(question.default)) ? question.default : (!Empty(question.default_float)) ? question.default_float : "" ;
+ html+='';
+
+ }
+ html += '';
+ html += '
';
+ html += '
';
+ html += '
';
+ html += '
';
+ html+='
';
+
+ $('#question_'+question.index).append(html);
+
+ element = angular.element(document.getElementById('question_'+question.index));
+ // // element.html(html);
+ //element.css('opacity', 0.7);
+ $compile(element)(scope);
+ // var questionScope = scope.$new;
+
+ $('#add_question_btn').show();
+ $('#add_question_btn').removeAttr('disabled');
+ $('#add_question_btn').focus();
+ $('#survey_maker_save_btn').removeAttr('disabled');
+
+ // Sometimes the $event.target returns the anchor element that wraps the icon, and sometimes the icon itself
+ // is returned. So for each icon click event we check to see which target the user clicked, and depending no which one
+ // they clicked, we move up the dom hierarchy to get the index on the question. Ultimatley the object that is passed to
+ // each one of these functions should be the index of the question that the user is trying to perform an action on.
+ $('#delete-question_'+question.index+'').on('click', function($event){
+ if($event.target.nodeName==="A"){
+ scope.deleteQuestion($event.target.parentElement.parentElement.id.split('_')[1]);
+ }
+ else if($event.target.nodeName === "I"){
+ scope.deleteQuestion($event.target.parentElement.parentElement.parentElement.id.split('_')[1]);
+ }
+ });
+ $('#edit-question_'+question.index+'').on('click', function($event){
+ if($event.target.nodeName==="A"){
+ scope.editQuestion($event.target.parentElement.parentElement.id.split('_')[1]);
+ }
+ else if($event.target.nodeName === "I"){
+ scope.editQuestion($event.target.parentElement.parentElement.parentElement.id.split('_')[1]);
+ }
+ });
+ $('#question-up_'+question.index+'').on('click', function($event){
+ if($event.target.nodeName==="A"){
+ scope.questionUp($event.target.parentElement.parentElement.id.split('_')[1]);
+ }
+ else if($event.target.nodeName === "I"){
+ scope.questionUp($event.target.parentElement.parentElement.parentElement.id.split('_')[1]);
+ }
+ });
+ $('#question-down_'+question.index+'').on('click', function($event){
+ if($event.target.nodeName==="A"){
+ scope.questionDown($event.target.parentElement.parentElement.id.split('_')[1]);
+ }
+ else if($event.target.nodeName === "I"){
+ scope.questionDown($event.target.parentElement.parentElement.parentElement.id.split('_')[1]);
+ }
+
+ });
+ };
+ }
+
+FinalizeQuestion.$inject =
+ [ 'GetBasePath',
+ 'Rest',
+ 'Wait',
+ 'ProcessErrors',
+ '$compile',
+ 'Empty',
+ '$filter'
+ ];
diff --git a/awx/ui/client/src/job-templates/survey-maker/questions/main.js b/awx/ui/client/src/job-templates/survey-maker/questions/main.js
new file mode 100644
index 0000000000..f1bbd8bc7c
--- /dev/null
+++ b/awx/ui/client/src/job-templates/survey-maker/questions/main.js
@@ -0,0 +1,7 @@
+import finalize from './finalize.factory';
+import edit from './edit.factory';
+
+export default
+ angular.module('jobTemplates.surveyMaker.questions', [])
+ .factory('finalizeQuestion', finalize)
+ .factory('editQuestion', edit);
diff --git a/awx/ui/client/src/job-templates/survey-maker/shared/main.js b/awx/ui/client/src/job-templates/survey-maker/shared/main.js
new file mode 100644
index 0000000000..8ee46b0bcf
--- /dev/null
+++ b/awx/ui/client/src/job-templates/survey-maker/shared/main.js
@@ -0,0 +1,5 @@
+import form from './question-definition.form';
+
+export default
+ angular.module('jobTemplates.surveyMaker.shared', [])
+ .value('questionDefinitionForm', form);
diff --git a/awx/ui/client/src/job-templates/survey-maker/shared/question-definition.form.js b/awx/ui/client/src/job-templates/survey-maker/shared/question-definition.form.js
new file mode 100644
index 0000000000..01bfff1f5f
--- /dev/null
+++ b/awx/ui/client/src/job-templates/survey-maker/shared/question-definition.form.js
@@ -0,0 +1,303 @@
+/*************************************************
+ * Copyright (c) 2015 Ansible, Inc.
+ *
+ * All Rights Reserved
+ *************************************************/
+
+ /**
+ * @ngdoc function
+ * @name forms.function:Questions
+ * @description This form is for adding a question
+*/
+
+export default
+ {
+
+ addTitle: 'Add Question',
+ editTitle: 'Edit Question',
+ base: 'survey_question',
+ name: 'survey_question',
+ well: true,
+ twoColumns: true,
+ breadcrumbs: false,
+
+ fields: {
+ question_name: {
+ realName: 'question_text',
+ label: 'Name',
+ type: 'text',
+ addRequired: true,
+ editRequired: true,
+ column: 1,
+ awSurveyQuestion: true
+ },
+ question_description: {
+ realName: 'question_description',
+ label: 'Description',
+ type: 'text',
+ addRequired: false,
+ editRequired: false,
+ column: 1
+ },
+ variable: {
+ ealName: 'variable',
+ type: 'custom',
+ control:''+
+ ''+
+ '
Please enter an answer variable name.
'+
+ '
Please remove the illegal character from the survey question variable name.
'+
+ '
This question variable is already in use. Please enter a different variable name.
' +
+ '
'+
+ '
',
+ addRequired: true,
+ editRequired: true,
+ column: 1
+ },
+ type: {
+ realName: 'answer_type',
+ label: 'Answer Type',
+ type: 'select',
+ defaultText: 'Choose an answer type',
+ ngOptions: 'answer_types.name for answer_types in answer_types track by answer_types.type',
+ addRequired: true,
+ editRequired: true,
+ column: 2,
+ ngChange: 'typeChange()'
+ },
+ choices: {
+ realName: 'answer_options',
+ label: 'Multiple Choice Options',
+ type: 'textarea',
+ rows: 3,
+ addRequired: true,
+ editRequired: true,
+ ngRequired: "type.type=== 'multiselect' || type.type=== 'multiplechoice' " ,
+ ngShow: 'type.type=== "multiselect" || type.type=== "multiplechoice" ',
+ awPopOver: 'Type an option on each line.
'+
+ 'For example the following input:
Apple
\n Banana
\n Cherry
would be displayed as:
\n'+
+ '- Apple
- Banana
- Cherry
',
+ dataTitle: 'Multiple Choice Options',
+ dataPlacement: 'right',
+ dataContainer: "body",
+ column: 2
+ },
+ text_options: {
+ realName: 'answer_options',
+ type: 'custom',
+ control:''+
+ '
'+
+ '
'+
+ '
The minimum length you entered is not a valid number. Please enter a whole number.
'+
+ '
The minimium length is too high. Please enter a lower number.
'+
+ '
The minimum length is too low. Please enter a positive number.
'+
+ '
'+
+ '
'+
+ '
'+
+ '
The maximum length you entered is not a valid number. Please enter a whole nnumber.
'+
+ '
The maximum length is too low. Please enter a number larger than the minimum length you set.
'+
+ '
'+
+ '
',
+ ngShow: 'type.type==="text" ',
+ addRequired: true,
+ editRequired: true,
+ column: 2
+ },
+ textarea_options: {
+ realName: 'answer_options',
+ type: 'custom',
+ control:''+
+ '
'+
+ '
'+
+ '
The minimum length you entered is not a valid number. Please enter a whole number.
'+
+ '
The minimium length is too high. Please enter a lower number.
'+
+ '
The minimum length is too low. Please enter a positive number.
'+
+ '
'+
+ '
'+
+ '
'+
+ '
The maximum length you entered is not a valid number. Please enter a whole number.
'+
+ '
The maximum length is too low. Please enter a number larger than the minimum length you set.
'+
+ '
'+
+ '
',
+ ngShow: 'type.type==="textarea" ',
+ addRequired: true,
+ editRequired: true,
+ column: 2
+ },
+ password_options: {
+ realName: 'answer_options',
+ type: 'custom',
+ control:''+
+ '
'+
+ '
'+
+ '
The minimum length you entered is not a valid number. Please enter a whole number.
'+
+ '
The minimium length is too high. Please enter a lower number.
'+
+ '
The minimum length is too low. Please enter a positive number.
'+
+ '
'+
+ '
'+
+ '
'+
+ '
The maximum length you entered is not a valid number. Please enter a whole number.
'+
+ '
The maximum length is too low. Please enter a number larger than the minimum length you set.
'+
+ '
'+
+ '
',
+ ngShow: 'type.type==="password" ',
+ addRequired: true,
+ editRequired: true,
+ column: 2
+ },
+ int_options: {
+ realName: 'answer_options',
+ type: 'custom',
+ control:''+
+ '
'+
+ '
'+
+ '
Please enter a valid integer.
'+
+ '
Please enter a smaller integer.
'+
+ '
'+
+ '
'+
+ '
'+
+ '
Please enter a valid integer.
'+
+ '
Please enter a larger integer.
'+
+ '
'+
+ '
',
+ ngShow: 'type.type==="integer" ',
+ addRequired: true,
+ editRequired: true,
+ column: 2
+ },
+ float_options: {
+ realName: 'answer_options',
+ type: 'custom',
+ control: ''+
+ '
'+
+ '
'+
+ '
Please enter a valid float.
'+
+ '
Please enter a smaller float.
'+
+ '
'+
+ '
'+
+ '
'+
+ '
Please enter a valid float.
'+
+ '
Please enter a larger float.
'+
+
+ '
'+
+ '
',
+ ngShow: 'type.type==="float" ',
+ addRequired: true,
+ editRequired: true,
+ column: 2
+ },
+ default:{
+ realName: 'default_answer',
+ type: 'custom' ,
+ control: '',
+ column: 2,
+ ngShow: 'type.type === "text" || type.type === "multiplechoice" '
+ },
+ default_multiselect: {
+ realName: 'default_answer' ,
+ type: 'custom',
+ control: '',
+ column: 2,
+ ngShow: 'type.type==="multiselect" '
+ },
+ default_int: {
+ realName: 'default_answer',
+ type: 'custom',
+ control: ''+
+ '
'+
+ '
'+
+ '
Please enter a valid integer.
'+
+ '
Please enter a value in the range of {{int_min}} to {{int_max}}.
'+
+ '
',
+ column: 2,
+ ngShow: 'type.type === "integer" '
+ },
+ default_float: {
+ realName: 'default_answer',
+ type: 'custom',
+ control: ''+
+ '
'+
+ '
'+
+ '
Please enter a valid float.
'+
+ '
Please enter a value in the range of {{float_min}} to {{float_max}}!
'+
+ '
',
+ column: 2,
+ ngShow: 'type.type=== "float" '
+ },
+ default_textarea: {
+ realName: "default_answer" ,
+ type: 'custom',
+ control: '',
+ column : 2,
+ ngShow: 'type.type === "textarea" '
+ },
+ default_password: {
+ realName: 'default_answer' ,
+ type: 'custom' ,
+ control: '',
+ column: 2,
+ ngShow: 'type.type === "password" '
+ },
+ required: {
+ realName: 'required_answer',
+ label: 'Required',
+ type: 'checkbox',
+ addRequired: false,
+ editRequired: false,
+ column: 2
+ }
+ },
+ buttons: {
+ question_cancel : {
+ label: 'Cancel',
+ 'class' : 'btn btn-default',
+ ngClick: 'cancelQuestion($event)'
+ },
+ submit_question: {
+ ngClick: 'submitQuestion($event)',
+ ngDisabled: true,
+ 'class': 'btn btn-sm btn-primary',
+ label: 'Add Question'
+ }
+ }
+
+ };
diff --git a/awx/ui/client/src/job-templates/survey-maker/surveys/add.factory.js b/awx/ui/client/src/job-templates/survey-maker/surveys/add.factory.js
new file mode 100644
index 0000000000..62b8576d06
--- /dev/null
+++ b/awx/ui/client/src/job-templates/survey-maker/surveys/add.factory.js
@@ -0,0 +1,25 @@
+export default
+ function AddFactory($location, $routeParams, ShowSurveyModal, Wait) {
+ return function(params) {
+ var scope = params.scope;
+
+ if (scope.removeDialogReady) {
+ scope.removeDialogReady();
+ }
+ scope.removeDialogReady = scope.$on('DialogReady', function() {
+ $('#survey-modal-dialog').dialog('open');
+ scope.addQuestion();
+ });
+ Wait('start');
+ $('#form-container').empty();
+ scope.resetForm();
+ ShowSurveyModal({ title: "Add Survey", scope: scope, callback: 'DialogReady' });
+ };
+ }
+
+AddFactory.$inject =
+ [ '$location',
+ '$routeParams',
+ 'showSurvey',
+ 'Wait'
+ ];
diff --git a/awx/ui/client/src/job-templates/survey-maker/surveys/delete.factory.js b/awx/ui/client/src/job-templates/survey-maker/surveys/delete.factory.js
new file mode 100644
index 0000000000..4c753816c6
--- /dev/null
+++ b/awx/ui/client/src/job-templates/survey-maker/surveys/delete.factory.js
@@ -0,0 +1,63 @@
+/**
+ * Delete a survey. Prompts user to confirm delete
+ *
+ * DeleteSurvey({
+ * scope: $scope containing list of survey form fields
+ * id: id of job template that survey is attached to
+ * callback: $scope.$emit label to call when delete is completed
+ * })
+ *
+ */
+export default
+ function DeleteSurvey(GetBasePath, Rest, Wait, ProcessErrors) {
+ return function(params) {
+
+ var scope = params.scope,
+ id = params.id,
+ // callback = params.callback,
+ url;
+
+
+ if (scope.removeSurveyDeleted) {
+ scope.removeSurveyDeleted();
+ }
+ scope.$on('SurveyDeleted', function(){
+ scope.survey_name = "";
+ scope.survey_description = "";
+ scope.survey_questions = [];
+ Wait('stop');
+ scope.survey_exists = false;
+ $('#job_templates_delete_survey_btn').hide();
+ $('#job_templates_edit_survey_btn').hide();
+ $('#job_templates_create_survey_btn').show();
+ });
+
+
+ Wait('start');
+
+ if(scope.mode==="add"){
+ scope.$emit("SurveyDeleted");
+
+ } else {
+ url = GetBasePath('job_templates')+ id + '/survey_spec/';
+
+ Rest.setUrl(url);
+ Rest.destroy()
+ .success(function () {
+ scope.$emit("SurveyDeleted");
+
+ })
+ .error(function (data, status) {
+ ProcessErrors(scope, data, status, { hdr: 'Error!',
+ msg: 'Failed to delete survey. DELETE returned status: ' + status });
+ });
+ }
+ };
+ }
+
+DeleteSurvey.$inject =
+ [ 'GetBasePath',
+ 'Rest',
+ 'Wait',
+ 'ProcessErrors'
+ ];
diff --git a/awx/ui/client/src/job-templates/survey-maker/surveys/edit.factory.js b/awx/ui/client/src/job-templates/survey-maker/surveys/edit.factory.js
new file mode 100644
index 0000000000..857136096f
--- /dev/null
+++ b/awx/ui/client/src/job-templates/survey-maker/surveys/edit.factory.js
@@ -0,0 +1,80 @@
+export default
+ function EditFactory($routeParams, SchedulerInit, ShowSurveyModal, Wait, Rest, ProcessErrors, GetBasePath, GenerateForm,
+ Empty, AddSurvey) {
+ return function(params) {
+ var scope = params.scope,
+ id = params.id,
+ tempSurv = {},
+ url = GetBasePath('job_templates') + id + '/survey_spec/', i;
+
+ if (scope.removeDialogReady) {
+ scope.removeDialogReady();
+ }
+ scope.removeDialogReady = scope.$on('DialogReady', function() {
+ $('#survey-modal-dialog').dialog('open');
+ });
+
+ scope.resetForm();
+ Wait('start');
+ //for adding a job template:
+ if(scope.mode === 'add'){
+ tempSurv.survey_name = scope.survey_name;
+ tempSurv.survey_description = scope.survey_description;
+ tempSurv.survey_questions = scope.survey_questions;
+
+ ShowSurveyModal({ title: "Edit Survey", scope: scope, callback: 'DialogReady' });
+
+ // scope.survey_name = tempSurv.survey_name;
+ // scope.survey_description = tempSurv.survey_description;
+
+ for(i=0; i';
- $('#finalized_questions').append(html);
- }
-
- required = (question.required===true) ? "prepend-asterisk" : "";
- html = '';
- html += '';
- html += '
';
-
- if(!Empty(question.question_description)){
- html += ''+question.question_description+'
\n';
- }
-
- if(question.type === 'text' ){
- defaultValue = (question.default) ? question.default : "";
- defaultValue = $filter('sanitize')(defaultValue);
- defaultValue = scope.serialize(defaultValue);
- html+='';
- }
- if(question.type === "textarea"){
- defaultValue = (question.default) ? question.default : (question.default_textarea) ? question.default_textarea: "" ;
- defaultValue = $filter('sanitize')(defaultValue);
- defaultValue = scope.serialize(defaultValue);
- html+='';
- }
- if(question.type === 'multiplechoice' || question.type === "multiselect"){
- choices = question.choices.split(/\n/);
- element = (question.type==="multiselect") ? "checkbox" : 'radio';
- question.default = (question.default) ? question.default : (question.default_multiselect) ? question.default_multiselect : "" ;
- answers = question.default.split(/\n/);
- html += '';
- for( i = 0; i' +
- ''+choices[i] +'
' ;
- }
- html += '
';
- }
-
- if(question.type === 'password'){
- defaultValue = (question.default) ? question.default : "";
- defaultValue = $filter('sanitize')(defaultValue);
- defaultValue = scope.serialize(defaultValue);
- html+=''+
- '
'+
- ''+
- ''+
- ''+
- ''+
- '
'+
- '
';
- }
-
- if(question.type === 'integer'){
- min = (!Empty(question.min)) ? question.min : "";
- max = (!Empty(question.max)) ? question.max : "" ;
- defaultValue = (!Empty(question.default)) ? question.default : (!Empty(question.default_int)) ? question.default_int : "" ;
- html+='';
-
- }
- if(question.type === "float"){
- min = (!Empty(question.min)) ? question.min : "";
- max = (!Empty(question.max)) ? question.max : "" ;
- defaultValue = (!Empty(question.default)) ? question.default : (!Empty(question.default_float)) ? question.default_float : "" ;
- html+='';
-
- }
- html += '';
- html += '
';
- html += '
';
- html += '
';
- html += '
';
- html+='
';
-
- $('#question_'+question.index).append(html);
-
- element = angular.element(document.getElementById('question_'+question.index));
- // // element.html(html);
- //element.css('opacity', 0.7);
- $compile(element)(scope);
- // var questionScope = scope.$new;
-
- $('#add_question_btn').show();
- $('#add_question_btn').removeAttr('disabled');
- $('#add_question_btn').focus();
- $('#survey_maker_save_btn').removeAttr('disabled');
-
- // Sometimes the $event.target returns the anchor element that wraps the icon, and sometimes the icon itself
- // is returned. So for each icon click event we check to see which target the user clicked, and depending no which one
- // they clicked, we move up the dom hierarchy to get the index on the question. Ultimatley the object that is passed to
- // each one of these functions should be the index of the question that the user is trying to perform an action on.
- $('#delete-question_'+question.index+'').on('click', function($event){
- if($event.target.nodeName==="A"){
- scope.deleteQuestion($event.target.parentElement.parentElement.id.split('_')[1]);
- }
- else if($event.target.nodeName === "I"){
- scope.deleteQuestion($event.target.parentElement.parentElement.parentElement.id.split('_')[1]);
- }
- });
- $('#edit-question_'+question.index+'').on('click', function($event){
- if($event.target.nodeName==="A"){
- scope.editQuestion($event.target.parentElement.parentElement.id.split('_')[1]);
- }
- else if($event.target.nodeName === "I"){
- scope.editQuestion($event.target.parentElement.parentElement.parentElement.id.split('_')[1]);
- }
- });
- $('#question-up_'+question.index+'').on('click', function($event){
- if($event.target.nodeName==="A"){
- scope.questionUp($event.target.parentElement.parentElement.id.split('_')[1]);
- }
- else if($event.target.nodeName === "I"){
- scope.questionUp($event.target.parentElement.parentElement.parentElement.id.split('_')[1]);
- }
- });
- $('#question-down_'+question.index+'').on('click', function($event){
- if($event.target.nodeName==="A"){
- scope.questionDown($event.target.parentElement.parentElement.id.split('_')[1]);
- }
- else if($event.target.nodeName === "I"){
- scope.questionDown($event.target.parentElement.parentElement.parentElement.id.split('_')[1]);
- }
-
- });
- };
- }])
-
-
- .factory('EditQuestion', ['GetBasePath','Rest', 'Wait', 'ProcessErrors', '$compile', 'GenerateForm', 'SurveyQuestionForm',
- function(GetBasePath, Rest, Wait, ProcessErrors, $compile, GenerateForm, SurveyQuestionForm) {
- return function(params) {
-
- var scope = params.scope,
- index = params.index,
- element,
- tmpVar,
- i,
- question = params.question, //scope.survey_questions[index],
- form = SurveyQuestionForm;
-
- $('#survey-save-button').attr('disabled', 'disabled');
- angular.element('#survey_question_question_cancel_btn').trigger('click');
- $('#add_question_btn').hide();
- // $('#new_question .aw-form-well').remove();
- element = $('.question_final:eq('+index+')');
- element.css('opacity', 1.0);
- element.empty();
- scope.text_min = null;
- scope.text_max = null;
- scope.int_min = null;
- scope.int_max = null;
- scope.float_min = null;
- scope.float_max = null;
- scope.password_min = null;
- scope.password_max = null;
- scope.pwcheckbox = false;
-
- if (scope.removeFillQuestionForm) {
- scope.removeFillQuestionForm();
- }
- scope.removeFillQuestionForm = scope.$on('FillQuestionForm', function() {
- for( var fld in form.fields){
- scope[fld] = question[fld];
- if(form.fields[fld].type === 'select'){
- for (i = 0; i < scope.answer_types.length; i++) {
- if (question[fld] === scope.answer_types[i].type) {
- scope[fld] = scope.answer_types[i];
- }
- }
- }
- }
- if( question.type === 'text'){
- scope.text_min = question.min;
- scope.text_max = question.max;
- scope.default_text = question.default;
- }
- if( question.type === 'textarea'){
- scope.textarea_min = question.min;
- scope.textarea_max = question.max;
- scope.default_textarea= question.default;
- }
- if(question.type === 'password'){
- scope.password_min = question.min;
- scope.password_max = question.max;
- scope.default_password = question.default;
- }
- if( question.type === 'integer'){
- scope.int_min = question.min;
- scope.int_max = question.max;
- scope.default_int = question.default;
- }
- else if( question.type === 'float' ) {
- scope.float_min = question.min;
- scope.float_max = question.max;
- scope.default_float = question.default;
-
- }
- else if ( question.type === 'multiselect'){
- scope.default_multiselect = question.default;
- }
- });
-
- if (scope.removeGenerateForm) {
- scope.removeGenerateForm();
- }
- scope.removeGenerateForm = scope.$on('GenerateForm', function() {
- tmpVar = scope.mode;
- GenerateForm.inject(form, { id: 'question_'+index, mode: 'edit' , related: false, scope:scope, breadCrumbs: false});
- scope.mode = tmpVar;
- scope.$emit('FillQuestionForm');
- });
-
-
- scope.$emit('GenerateForm');
-
- };
- }])
-
- .factory('SurveyControllerInit', ['$location', 'DeleteSurvey', 'EditSurvey', 'AddSurvey', 'GenerateForm', 'SurveyQuestionForm', 'Wait', 'Alert',
- 'GetBasePath', 'Rest', 'ProcessErrors' , '$compile', 'FinalizeQuestion', 'EditQuestion', '$sce',
- function($location, DeleteSurvey, EditSurvey, AddSurvey, GenerateForm, SurveyQuestionForm, Wait, Alert,
+ function Init($location, DeleteSurvey, EditSurvey, AddSurvey, GenerateForm, SurveyQuestionForm, Wait, Alert,
GetBasePath, Rest, ProcessErrors, $compile, FinalizeQuestion, EditQuestion, $sce) {
return function(params) {
var scope = params.scope,
@@ -1049,4 +534,22 @@ angular.module('SurveyHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper',
};
};
- }]);
+ }
+
+Init.$inject =
+ [ '$location',
+ 'deleteSurvey',
+ 'editSurvey',
+ 'addSurvey',
+ 'GenerateForm',
+ 'questionDefinitionForm',
+ 'Wait',
+ 'Alert',
+ 'GetBasePath',
+ 'Rest',
+ 'ProcessErrors',
+ '$compile',
+ 'finalizeQuestion',
+ 'editQuestion',
+ '$sce'
+ ];
diff --git a/awx/ui/client/src/job-templates/survey-maker/surveys/main.js b/awx/ui/client/src/job-templates/survey-maker/surveys/main.js
new file mode 100644
index 0000000000..a16c10073c
--- /dev/null
+++ b/awx/ui/client/src/job-templates/survey-maker/surveys/main.js
@@ -0,0 +1,13 @@
+import add from './add.factory';
+import edit from './edit.factory';
+import _delete from './delete.factory';
+import init from './init.factory';
+import show from './show.factory';
+
+export default
+ angular.module('jobTemplates.surveyMaker.surveys', [])
+ .factory('showSurvey', show)
+ .factory('addSurvey', add)
+ .factory('editSurvey', edit)
+ .factory('deleteSurvey', _delete)
+ .factory('initSurvey', init);
diff --git a/awx/ui/client/src/job-templates/survey-maker/surveys/show.factory.js b/awx/ui/client/src/job-templates/survey-maker/surveys/show.factory.js
new file mode 100644
index 0000000000..74b0b7fd1c
--- /dev/null
+++ b/awx/ui/client/src/job-templates/survey-maker/surveys/show.factory.js
@@ -0,0 +1,84 @@
+export default
+ function ShowFactory(Wait, CreateDialog, Empty, $compile) {
+ return function(params) {
+ // Set modal dimensions based on viewport width
+
+ var scope = params.scope,
+ callback = params.callback,
+ mode = (params.mode) ? params.mode : "survey-maker",
+ title = params.title,
+ element,
+ target = (mode==='survey-taker') ? 'password-modal' : "survey-modal-dialog",
+ buttons = [{
+ "label": "Cancel",
+ "onClick": function() {
+ scope.cancelSurvey(this);
+ },
+ "icon": "fa-times",
+ "class": "btn btn-default",
+ "id": "survey-close-button"
+ },{
+ "label": (mode==='survey-taker') ? "Launch" : "Save" ,
+ "onClick": function() {
+ setTimeout(function(){
+ scope.$apply(function(){
+ if(mode==='survey-taker'){
+ scope.$emit('SurveyTakerCompleted');
+ } else{
+ scope.saveSurvey();
+ }
+ });
+ });
+ },
+ "icon": (mode==='survey-taker') ? "fa-rocket" : "fa-check",
+ "class": "btn btn-primary",
+ "id": "survey-save-button"
+ }];
+
+ CreateDialog({
+ id: target,
+ title: title,
+ scope: scope,
+ buttons: buttons,
+ width: 700,
+ height: 725,
+ minWidth: 400,
+ onClose: function() {
+ $('#'+target).empty();
+ },
+ onOpen: function() {
+ Wait('stop');
+ if(mode!=="survey-taker"){
+ // if(scope.mode === 'add'){
+ // $('#survey-save-button').attr('disabled' , true);
+ // } else
+ if(scope.can_edit === false){
+ $('#survey-save-button').attr('disabled', "disabled");
+ }
+ else {
+ $('#survey-save-button').attr('ng-disabled', "survey_questions.length<1 ");
+ }
+ element = angular.element(document.getElementById('survey-save-button'));
+ $compile(element)(scope);
+
+ }
+ if(mode==="survey-taker"){
+ $('#survey-save-button').attr('ng-disabled', "survey_taker_form.$invalid");
+ element = angular.element(document.getElementById('survey-save-button'));
+ $compile(element)(scope);
+
+ }
+
+ },
+ callback: callback
+ });
+ };
+ }
+
+ShowFactory.$inject =
+ [ 'Wait',
+ 'CreateDialog',
+ 'Empty',
+ '$compile'
+ ];
+