mirror of
https://github.com/ansible/awx.git
synced 2026-05-19 23:07:42 -02:30
Use select lists for multiple choice answers
This commit is contained in:
@@ -507,14 +507,14 @@ function($compile, Rest, GetBasePath, TextareaResize,CreateDialog, GenerateForm,
|
|||||||
url = params.url,
|
url = params.url,
|
||||||
callback=params.callback,
|
callback=params.callback,
|
||||||
scope = params.scope,
|
scope = params.scope,
|
||||||
i, j,
|
i,
|
||||||
requiredAsterisk,
|
requiredAsterisk,
|
||||||
requiredClasses,
|
requiredClasses,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
choices,
|
choices,
|
||||||
element,
|
element,
|
||||||
minlength, maxlength,
|
minlength, maxlength,
|
||||||
checked, min, max,
|
min, max,
|
||||||
survey_url = GetBasePath('job_templates') + id + '/survey_spec/' ;
|
survey_url = GetBasePath('job_templates') + id + '/survey_spec/' ;
|
||||||
|
|
||||||
//for toggling the input on password inputs
|
//for toggling the input on password inputs
|
||||||
@@ -605,41 +605,35 @@ function($compile, Rest, GetBasePath, TextareaResize,CreateDialog, GenerateForm,
|
|||||||
if(question.type === 'multiplechoice'){
|
if(question.type === 'multiplechoice'){
|
||||||
choices = question.choices.split(/\n/);
|
choices = question.choices.split(/\n/);
|
||||||
element = (question.type==="multiselect") ? "checkbox" : 'radio';
|
element = (question.type==="multiselect") ? "checkbox" : 'radio';
|
||||||
question.default = (question.default) ? question.default : (question.default_multiselect) ? question.default_multiselect : "" ;
|
|
||||||
html+='<div class="survey_taker_input" > ';
|
if (question.default) {
|
||||||
for( j = 0; j<choices.length; j++){
|
scope[question.variable] = question.default;
|
||||||
checked = (!Empty(question.default) && question.default.indexOf(choices[j])!==-1) ? "checked" : "";
|
} else {
|
||||||
choices[j] = $filter('sanitize')(choices[j]);
|
scope[question.variable] = '';
|
||||||
html+= '<input type="'+element+'" class="mc" ng-model="'+question.variable+'" ng-required="'+question.required+'" name="'+question.variable+ ' " id="'+question.variable+'" value=" '+choices[j]+' " '+checked+' >' +
|
|
||||||
'<span>'+choices[j] +'</span><br>' ;
|
|
||||||
}
|
}
|
||||||
html+= '<div class="error survey_error" ng-show="job_launch_form.'+ question.variable + '.$dirty && ' +
|
|
||||||
'job_launch_form.'+question.variable+'.$error.required\">Please select an answer.</div>'+
|
html+='<div class="survey_taker_input" > ';
|
||||||
'<div class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></div>';
|
html += '<survey-question type="' + question.type + '" index="' + question.index + '" survey-questions="survey_questions" ng-model="' + question.variable + '" ng-required="' + question.required + '"></survey-question>';
|
||||||
|
// html+= '<div class="error survey_error" ng-show="job_launch_form.'+ question.variable + '.$dirty && ' +
|
||||||
|
// 'job_launch_form.'+question.variable+'.$error.required\">Please select an answer.</div>'+
|
||||||
|
// '<div class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></div>';
|
||||||
html+= '</div>'; //end survey_taker_input
|
html+= '</div>'; //end survey_taker_input
|
||||||
}
|
}
|
||||||
|
|
||||||
if(question.type === "multiselect"){
|
if(question.type === "multiselect"){
|
||||||
//seperate the choices out into an array
|
//seperate the choices out into an array
|
||||||
choices = question.choices.split(/\n/);
|
choices = question.choices.split(/\n/);
|
||||||
question.default = (question.default) ? question.default : (question.default_multiselect) ? question.default_multiselect : "" ;
|
|
||||||
//ensure that the default answers are in an array
|
//ensure that the default answers are in an array
|
||||||
scope[question.variable] = question.default.split(/\n/);
|
if (question.default) {
|
||||||
//create a new object to be used by the surveyCheckboxes directive
|
scope[question.variable] = question.default.split(/\n/);
|
||||||
scope[question.variable + '_object'] = {
|
} else {
|
||||||
name: question.variable,
|
scope[question.variable] = '';
|
||||||
value: (question.default.split(/\n/)[0]==="") ? [] : question.default.split(/\n/) ,
|
|
||||||
required: question.required,
|
|
||||||
options:[]
|
|
||||||
};
|
|
||||||
//load the options into the 'options' key of the new object
|
|
||||||
for(j=0; j<choices.length; j++){
|
|
||||||
scope[question.variable+'_object'].options.push( {value:choices[j]} );
|
|
||||||
}
|
}
|
||||||
//surveyCheckboxes takes a list of checkboxes and connects them to one scope variable
|
//create a new object to be used by the surveyCheckboxes directive
|
||||||
html += '<survey-checkboxes name="'+question.variable+'" ng-model=" '+question.variable + '_object " ng-required="'+question.required+'">'+
|
html += '<survey-question type="' + question.type + '" index="' + question.index + '" survey-questions="survey_questions" ng-model="' + question.variable + '" ng-required="' + question.required + '"></survey-question>';
|
||||||
'</survey-checkboxes>{{job_launch_form.'+question.variable+'_object.$error.checkbox}}'+
|
// html += '<survey-checkboxes name="'+question.variable+'" ng-model=" '+question.variable + '_object " ng-required="'+question.required+'">'+
|
||||||
'<div class="error survey_error" ng-show="job_launch_form.'+question.variable+'.$error.checkbox">Please select at least one answer.</div>';
|
// '</survey-checkboxes>{{job_launch_form.'+question.variable+'_object.$error.checkbox}}'+
|
||||||
|
// '<div class="error survey_error" ng-show="job_launch_form.'+question.variable+'.$error.checkbox">Please select at least one answer.</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
if(question.type === 'integer'){
|
if(question.type === 'integer'){
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import listGenerator from '../../shared/list-generator/main';
|
import listGenerator from '../../shared/list-generator/main';
|
||||||
import questions from './questions/main';
|
import questions from './questions/main';
|
||||||
import surveys from './surveys/main';
|
import surveys from './surveys/main';
|
||||||
|
import render from './render/main';
|
||||||
import shared from './shared/main';
|
import shared from './shared/main';
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@@ -8,5 +9,6 @@ export default
|
|||||||
[ listGenerator.name,
|
[ listGenerator.name,
|
||||||
questions.name,
|
questions.name,
|
||||||
surveys.name,
|
surveys.name,
|
||||||
|
render.name,
|
||||||
shared.name
|
shared.name
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -18,13 +18,9 @@ export default
|
|||||||
index = params.index,
|
index = params.index,
|
||||||
required,
|
required,
|
||||||
element,
|
element,
|
||||||
choices,
|
|
||||||
i,
|
|
||||||
checked,
|
|
||||||
max,
|
max,
|
||||||
min,
|
min,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
answers,
|
|
||||||
html = "";
|
html = "";
|
||||||
|
|
||||||
question.index = index;
|
question.index = index;
|
||||||
@@ -65,18 +61,28 @@ export default
|
|||||||
'</div></div>';
|
'</div></div>';
|
||||||
}
|
}
|
||||||
if(question.type === 'multiplechoice' || question.type === "multiselect"){
|
if(question.type === 'multiplechoice' || question.type === "multiselect"){
|
||||||
choices = question.choices.split(/\n/);
|
|
||||||
element = (question.type==="multiselect") ? "checkbox" : 'radio';
|
question.default = question.default_multiselect || question.default;
|
||||||
question.default = (question.default) ? question.default : (question.default_multiselect) ? question.default_multiselect : "" ;
|
|
||||||
answers = question.default.split(/\n/);
|
var defaultScopePropertyName =
|
||||||
html += '<div class="input_area">';
|
question.variable + '_default';
|
||||||
for( i = 0; i<choices.length; i++){
|
|
||||||
checked = (!Empty(question.default) && $.inArray(choices[i], answers) !== -1) ? "checked" : "";
|
if (question.default) {
|
||||||
choices[i] = $filter('sanitize')(choices[i]);
|
if (question.type === 'multiselect' && typeof question.default.split === 'function') {
|
||||||
choices[i] = scope.serialize(choices[i]);
|
scope[defaultScopePropertyName] = question.default.split('\n');
|
||||||
html+= '<input type="'+element+'" class="mc" ng-required="!'+question.variable+'" name="'+question.variable+ ' " id="'+question.variable+'" value=" '+choices[i]+' " '+checked+' disabled>' +
|
} else if (question.type !== 'multiselect') {
|
||||||
'<span>'+choices[i] +'</span><br>' ;
|
scope[defaultScopePropertyName] = question.default;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scope[defaultScopePropertyName] = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html += '<div class="row">';
|
||||||
|
html += '<div class="col-xs-8">';
|
||||||
|
html += '<div class="SurveyControls-selectWrapper">';
|
||||||
|
html += '<survey-question type="' + question.type + '" index="' + question.index + '" survey-questions="survey_questions" ng-required="' + question.required + '" ng-model="' + defaultScopePropertyName + '"></survey-question>';
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import surveyQuestion from './survey-question.directive';
|
||||||
|
import multipleChoice from './multiple-choice.directive';
|
||||||
|
import multiSelect from './multiselect.directive';
|
||||||
|
|
||||||
|
export default
|
||||||
|
angular.module('jobTemplates.surveyMaker.render', [])
|
||||||
|
.directive('surveyQuestion', surveyQuestion)
|
||||||
|
.directive('multipleChoice', multipleChoice)
|
||||||
|
.directive('multiSelect', multiSelect);
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/* jshint unused: vars */
|
||||||
|
import {templateUrl} from '../../../shared/template-url/template-url.factory';
|
||||||
|
|
||||||
|
function link($timeout, scope, element, attrs, ngModel) {
|
||||||
|
attrs.width = attrs.width || '100%';
|
||||||
|
|
||||||
|
$timeout(function() {
|
||||||
|
|
||||||
|
$.fn.select2.amd.require(
|
||||||
|
[ 'select2/utils',
|
||||||
|
'select2/dropdown',
|
||||||
|
'select2/dropdown/search',
|
||||||
|
'select2/dropdown/attachContainer',
|
||||||
|
'select2/dropdown/closeOnSelect',
|
||||||
|
'select2/dropdown/minimumResultsForSearch'
|
||||||
|
],
|
||||||
|
function(Utils, Dropdown, Search, AttachContainer, CloseOnSelect, MinimumResultsForSearch) {
|
||||||
|
|
||||||
|
var CustomAdapter =
|
||||||
|
_.reduce([Search, AttachContainer, CloseOnSelect, MinimumResultsForSearch],
|
||||||
|
function(Adapter, Decorator) {
|
||||||
|
return Utils.Decorate(Adapter, Decorator);
|
||||||
|
}, Dropdown);
|
||||||
|
|
||||||
|
element.find('select').select2(
|
||||||
|
{ multiple: scope.isMultipleSelect(),
|
||||||
|
minimumResultsForSearch: Infinity,
|
||||||
|
theme: 'bootstrap',
|
||||||
|
width: attrs.width,
|
||||||
|
dropdownAdapter: CustomAdapter
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default
|
||||||
|
[ '$timeout',
|
||||||
|
function($timeout) {
|
||||||
|
var directive =
|
||||||
|
{ restrict: 'E',
|
||||||
|
require: 'ngModel',
|
||||||
|
scope: {
|
||||||
|
isMultipleSelect: '&multiSelect',
|
||||||
|
choices: '=',
|
||||||
|
question: '=',
|
||||||
|
isRequired: '=ngRequired',
|
||||||
|
selectedValue: '=ngModel'
|
||||||
|
},
|
||||||
|
templateUrl: templateUrl('job-templates/survey-maker/render/multiple-choice'),
|
||||||
|
link: _.partial(link, $timeout)
|
||||||
|
};
|
||||||
|
return directive;
|
||||||
|
}
|
||||||
|
];
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<div>
|
||||||
|
<select class="form-control" ng-model="selectedValue" multi-select ng-required="isRequired">
|
||||||
|
<option ng-repeat="choice in choices" value="{{choice}}" ng-selected="selectedValue.indexOf(choice) !== -1">{{choice}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/* jshint unused: vars */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc
|
||||||
|
*
|
||||||
|
* @name jobTemplates.surveyMaker.render.multiSelect
|
||||||
|
* @description
|
||||||
|
* Angular provides no method of binding to "multiple" for
|
||||||
|
* select lists. This is because under normal circumstances,
|
||||||
|
* the structure of `ng-model` changes based on whether `multiple`
|
||||||
|
* is true or false. We're not needing to "bind" to "multiple",
|
||||||
|
* but we do need to pass in the value dynamically. This allows
|
||||||
|
* us to do that.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var directive =
|
||||||
|
{ require: 'ngModel',
|
||||||
|
compile: function() {
|
||||||
|
return {
|
||||||
|
pre: function(scope, element, attrs, ngModel) {
|
||||||
|
if (_.isUndefined(scope.isMultipleSelect)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scope.isMultipleSelect()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.attr('multiple', true);
|
||||||
|
attrs.multiple = true;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
priority: 1000
|
||||||
|
};
|
||||||
|
|
||||||
|
export default
|
||||||
|
function() {
|
||||||
|
return directive;
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/* jshint unused: vars */
|
||||||
|
import {templateUrl} from '../../../shared/template-url/template-url.factory';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc
|
||||||
|
* @name jobTemplates.surveyMaker.render.surveyQuestion
|
||||||
|
* @description
|
||||||
|
* Directive that will eventually hold all logic
|
||||||
|
* for rendering different form controls based on
|
||||||
|
* the question type for a survey.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Since we're generating HTML for the entire survey, and _then_
|
||||||
|
// calling $compile, this directive never actually gets compiled
|
||||||
|
// with the question object we need. Therefore, we give it the index
|
||||||
|
// of the question as an attribute (not scope) and then look it up
|
||||||
|
// in the `survey_questions` by that index when it the directive gets
|
||||||
|
// compiled.
|
||||||
|
//
|
||||||
|
function findQuestionByIndex(questions, index) {
|
||||||
|
return _.find(questions, function(question) {
|
||||||
|
return question.index === index;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function link(scope, element, attrs) {
|
||||||
|
var question = findQuestionByIndex(scope.surveyQuestions, Number(attrs.index));
|
||||||
|
|
||||||
|
scope.question = question;
|
||||||
|
|
||||||
|
if (!_.isUndefined(question.choices)) {
|
||||||
|
scope.choices = question.choices.split('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default
|
||||||
|
function() {
|
||||||
|
var directive =
|
||||||
|
{ restrict: 'E',
|
||||||
|
scope:
|
||||||
|
{ surveyQuestions: '=',
|
||||||
|
selectedValue: '=ngModel',
|
||||||
|
isRequired: '@ngRequired'
|
||||||
|
},
|
||||||
|
templateUrl: templateUrl('job-templates/survey-maker/render/survey-question'),
|
||||||
|
link: link
|
||||||
|
};
|
||||||
|
|
||||||
|
return directive;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<multiple-choice
|
||||||
|
multi-select="question.type === 'multiselect'"
|
||||||
|
question="question"
|
||||||
|
choices="choices"
|
||||||
|
ng-required="isRequired === 'true'"
|
||||||
|
ng-model="selectedValue">
|
||||||
|
</multiple-choice>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/** @define SurveyControls */
|
||||||
|
|
||||||
|
.SurveyControls {
|
||||||
|
&-selectWrapper {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
&--dropdown {
|
||||||
|
z-index: 10000;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -136,13 +136,13 @@ export default
|
|||||||
if(questions.length>0){
|
if(questions.length>0){
|
||||||
$('#survey-save-button').removeAttr('disabled');
|
$('#survey-save-button').removeAttr('disabled');
|
||||||
}
|
}
|
||||||
scope.finalizeQuestion(questions[key], key);
|
scope.finalizeQuestion(questions[key], Number(key));
|
||||||
}
|
}
|
||||||
else if(scope.mode=== 'edit' ){
|
else if(scope.mode=== 'edit' ){
|
||||||
if(scope.survey_questions.length>0 && scope.can_edit === true){
|
if(scope.survey_questions.length>0 && scope.can_edit === true){
|
||||||
$('#survey-save-button').removeAttr('disabled');
|
$('#survey-save-button').removeAttr('disabled');
|
||||||
}
|
}
|
||||||
scope.finalizeQuestion(scope.survey_questions[key] , key);
|
scope.finalizeQuestion(scope.survey_questions[key] , Number(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -464,7 +464,7 @@ export default
|
|||||||
scope.survey_questions[key] = data;
|
scope.survey_questions[key] = data;
|
||||||
}
|
}
|
||||||
$('#'+elementID).empty();
|
$('#'+elementID).empty();
|
||||||
scope.finalizeQuestion(data , key);
|
scope.finalizeQuestion(data , Number(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ export default
|
|||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
_allowInteraction: function(e) {
|
||||||
|
return !!$(e.target).is('.select2-input') || this._super(e);
|
||||||
|
},
|
||||||
callback: callback
|
callback: callback
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper'])
|
|||||||
onResizeStop = params.onResizeStop,
|
onResizeStop = params.onResizeStop,
|
||||||
onClose = params.onClose,
|
onClose = params.onClose,
|
||||||
onOpen = params.onOpen,
|
onOpen = params.onOpen,
|
||||||
|
_allowInteraction = params._allowInteraction,
|
||||||
callback = params.callback,
|
callback = params.callback,
|
||||||
beforeDestroy = params.beforeDestroy,
|
beforeDestroy = params.beforeDestroy,
|
||||||
closeOnEscape = (params.closeOnEscape === undefined) ? false : params.closeOnEscape,
|
closeOnEscape = (params.closeOnEscape === undefined) ? false : params.closeOnEscape,
|
||||||
@@ -177,7 +178,8 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper'])
|
|||||||
if (onOpen) {
|
if (onOpen) {
|
||||||
onOpen();
|
onOpen();
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
_allowInteraction: _allowInteraction
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}])
|
}])
|
||||||
|
|||||||
Reference in New Issue
Block a user