diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js index 90cff95d24..cfa6a528a2 100644 --- a/awx/ui/static/js/app.js +++ b/awx/ui/static/js/app.js @@ -117,7 +117,8 @@ angular.module('Tower', [ 'SocketHelper', 'AboutAnsibleHelpModal', 'SurveyMakerFormDefinition', - 'SurveyQuestionFormDefinition' + 'SurveyQuestionFormDefinition', + ]) .constant('AngularScheduler.partials', urlPrefix + 'lib/angular-scheduler/lib/') diff --git a/awx/ui/static/js/controllers/JobTemplates.js b/awx/ui/static/js/controllers/JobTemplates.js index 274be543eb..55dc8fbc27 100644 --- a/awx/ui/static/js/controllers/JobTemplates.js +++ b/awx/ui/static/js/controllers/JobTemplates.js @@ -864,7 +864,7 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP if(fld ==='survey_enabled'){ // $scope.$emit('EnableSurvey', fld); $('#job_templates_survey_enabled_chbox').attr('checked', $scope[fld]); - if(Empty(data.related.survey_spec)){ + if(Empty(data.summary_fields.survey)) { $('#job_templates_delete_survey_btn').hide(); $('#job_templates_edit_survey_btn').hide(); $('#job_templates_create_survey_btn').show(); @@ -1084,7 +1084,7 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP Rest.patch({"survey_enabled": $scope.survey_enabled}) .success(function (data) { - if(Empty(data.related.survey_spec)){ + if(Empty(data.summary_fields.survey)){ $('#job_templates_delete_survey_btn').hide(); $('#job_templates_edit_survey_btn').hide(); $('#job_templates_create_survey_btn').show(); @@ -1103,67 +1103,7 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP }); }; - //navigate to the survey maker - // $scope.addSurvey = function() { - // $location.path($location.path() + '/survey/add'); - // }; - //navigate to the survey maker - // $scope.editSurvey = function() { - // $scope.Store("survey_for_new_job_template", false); - // $location.path($location.path() + '/survey/edit'); - // }; - - // //delete a survey by posting a blank survey - // $scope.deleteSurvey = function() { - // // $location.path($location.path() + '/survey/add'); - // Wait('start'); - // var url = defaultUrl+ id + '/survey_spec/'; - - // Rest.setUrl(url); - // Rest.post({}) - // .success(function () { - // Wait('stop'); - // $('#job_templates_delete_survey_btn').hide(); - // $('#job_templates_edit_survey_btn').hide(); - // $('#job_templates_create_survey_btn').show(); - - // }) - // .error(function (data, status) { - // ProcessErrors($scope, data, status, form, { hdr: 'Error!', - // msg: 'Failed to add new survey. Post returned status: ' + status }); - // }); - // }; - - // // Related set: Delete button - // $scope['delete'] = function (set, itm_id, name, title) { - // $rootScope.flashMessage = null; - - // var action = function () { - // var url = defaultUrl + id + '/' + set + '/'; - // Rest.setUrl(url); - // Rest.post({ - // id: itm_id, - // disassociate: 1 - // }) - // .success(function () { - // $('#prompt-modal').modal('hide'); - // $scope.search(form.related[set].iterator); - // }) - // .error(function (data, status) { - // $('#prompt-modal').modal('hide'); - // ProcessErrors($scope, data, status, null, { hdr: 'Error!', - // msg: 'Call to ' + url + ' failed. POST returned status: ' + status }); - // }); - // }; - - // Prompt({ - // hdr: 'Delete', - // body: 'Are you sure you want to remove ' + name + ' from ' + $scope.name + ' ' + title + '?', - // action: action - // }); - - // }; } JobTemplatesEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobTemplateForm', diff --git a/awx/ui/static/js/forms/SurveyMaker.js b/awx/ui/static/js/forms/SurveyMaker.js index 1f1f67ba2d..d7f30d7cf2 100644 --- a/awx/ui/static/js/forms/SurveyMaker.js +++ b/awx/ui/static/js/forms/SurveyMaker.js @@ -54,7 +54,7 @@ angular.module('SurveyMakerFormDefinition', []) '
'+ '
'+ ''+ - '
' + '
' // label: 'Survey Name', // type: 'text', // addRequired: true, diff --git a/awx/ui/static/js/forms/SurveyQuestion.js b/awx/ui/static/js/forms/SurveyQuestion.js index e5f64f25f0..ac7a579b76 100644 --- a/awx/ui/static/js/forms/SurveyQuestion.js +++ b/awx/ui/static/js/forms/SurveyQuestion.js @@ -35,27 +35,28 @@ angular.module('SurveyQuestionFormDefinition', []) fields: { question_name: { realName: 'question_text', - label: 'Question Text', + label: 'Text', type: 'text', addRequired: true, editRequired: true, - column: 1 + column: 1, + awSurveyQuestion: true }, question_description: { realName: 'question_description', - label: 'Question Description', - type: 'textarea', - rows: 2, - addRequired: true, - editRequired: true, - column: 2 + label: 'Description', + type: 'text', + // rows: 2, + addRequired: false, + editRequired: false, + column: 1 }, variable: { label: 'Answer Variable Name', type: 'text', addRequired: true, editRequired: true, - column: 2 + column: 1 // sourceModel: 'organization', // sourceField: 'name', // ngClick: 'lookUpOrganization()', @@ -71,7 +72,7 @@ angular.module('SurveyQuestionFormDefinition', []) ngOptions: 'answer_types.name for answer_types in answer_types track by answer_types.type', addRequired: true, editRequired: true, - column: 1 + column: 2 }, // answer_options_text: { @@ -97,7 +98,7 @@ angular.module('SurveyQuestionFormDefinition', []) dataTitle: 'Multiple Choice Options', dataPlacement: 'right', dataContainer: "body", - column: 1 + column: 2 }, answer_options_number: { realName: 'answer_options', @@ -109,7 +110,7 @@ angular.module('SurveyQuestionFormDefinition', []) ngShow: 'type.type==="integer" || type.type==="float" ', addRequired: true, editRequired: true, - column: 1 + column: 2 }, // answer_options_json: { // realName: 'answer_options', @@ -131,16 +132,17 @@ angular.module('SurveyQuestionFormDefinition', []) type: 'text', addRequired: false, editRequired: false, - column: 1 + column: 2 }, required: { - realName: 'default_answer', + realName: 'required_answer', label: 'Required', type: 'checkbox', // checked: true, addRequired: false, editRequired: false, column: 2 + // trueValue: true // label: 'Answer required or optional', // type: 'custom', // column: 2, @@ -174,11 +176,7 @@ angular.module('SurveyQuestionFormDefinition', []) ngClick: 'submitQuestion()', ngDisabled: true, 'class': 'btn btn-sm btn-primary', - label: 'Submit Question' - }, - reset: { - ngClick: 'questionReset()', - ngDisabled: true + label: 'Add Question' } }, diff --git a/awx/ui/static/js/helpers/Survey.js b/awx/ui/static/js/helpers/Survey.js index 557f3384b5..5dc24008a5 100644 --- a/awx/ui/static/js/helpers/Survey.js +++ b/awx/ui/static/js/helpers/Survey.js @@ -60,7 +60,6 @@ angular.module('SurveyHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', }, onOpen: function() { Wait('stop'); - $('#survey-tabs a:first').tab('show'); // $('#surveyName').focus(); // $('#rrule_nlp_description').dblclick(function() { // setTimeout(function() { scope.$apply(function() { scope.showRRule = (scope.showRRule) ? false : true; }); }, 100); @@ -99,39 +98,10 @@ angular.module('SurveyHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', scope.removeDialogReady(); } scope.removeDialogReady = scope.$on('DialogReady', function() { - $('#survey-modal-dialog').dialog('open'); - // $('#schedulerName').focus(); - // setTimeout(function() { - // scope.$apply(function() { - // scheduler.setRRule(schedule.rrule); - // scheduler.setName(schedule.name); - // }); - // }, 300); - }); + $('#survey-modal-dialog').dialog('open'); + }); - // scope.saveSurvey = function() { - // Wait('start'); - // if(scope.mode==="add"){ - // $('#survey-modal-dialog').dialog('close'); - // scope.$emit('SurveySaved'); - // } - // else{ - // // var url = data.url+ 'survey_spec/'; - // Rest.setUrl(url); - // Rest.post({ name: scope.survey_name, description: scope.survey_description, spec: scope.survey_questions }) - // .success(function () { - // // Wait('stop'); - // $('#survey-modal-dialog').dialog('close'); - // scope.$emit('SurveySaved'); - // }) - // .error(function (data, status) { - // ProcessErrors(scope, data, status, form, { hdr: 'Error!', - // msg: 'Failed to add new survey. Post returned status: ' + status }); - // }); - // } - // }; - Wait('start'); if(scope.mode === 'add'){ tempSurv.survey_name = scope.survey_name; @@ -162,7 +132,7 @@ angular.module('SurveyHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', for(i=0; i\n'; + if(!Empty(question.question_description)){ + html += '
'+question.question_description+'
\n'; + } + defaultValue = (question.default) ? question.default : ""; + + if(question.type === 'text' ){ + + html+='
'+ + '
'+ + ''+ + '
'; + } + if(question.type === "textarea"){ + html+='
'+ + '
'+ + ''+ + '
'; + } + if(question.type === 'multiplechoice' || question.type === "multiselect"){ + choices = question.choices.split(/\n/); + element = (question.type==="multiselect") ? "checkbox" : 'radio'; + + for( i = 0; i'+ + '' +choices[i]+ + ''; + } + + } + if(question.type === 'integer' || question.type === "float"){ + min = (question.min) ? question.min : ""; + max = (question.max) ? question.max : "" ; + html+='
'+ + '
'+ + ''+ + '
'; + + } + if(question.type === "json"){ + + } + html += '
'; + html += ' '; + html += ' '; + html += ' '; + html += ' '; + html+='
'; + + $('#finalized_questions').append(html); + + element = angular.element(document.getElementById('finalized_questions')); + // element.html(html); + $compile(element)(scope); + // var questionScope = scope.$new; + + $('#add_question_btn').show(); + $('#add_question_btn').removeAttr('disabled'); + $('#survey_maker_save_btn').removeAttr('disabled'); }; }]) .factory('SurveyControllerInit', ['$location', 'DeleteSurvey', 'EditSurvey', 'AddSurvey', 'GenerateForm', 'SurveyQuestionForm', 'Wait', 'Alert', - 'GetBasePath', 'Rest', 'ProcessErrors' , - function($location, DeleteSurvey, EditSurvey, AddSurvey, GenerateForm, SurveyQuestionForm, Wait, Alert, GetBasePath, Rest, ProcessErrors) { + 'GetBasePath', 'Rest', 'ProcessErrors' , '$compile', 'FinalizeQuestion', + function($location, DeleteSurvey, EditSurvey, AddSurvey, GenerateForm, SurveyQuestionForm, Wait, Alert, + GetBasePath, Rest, ProcessErrors, $compile, FinalizeQuestion) { return function(params) { var scope = params.scope, // parent_scope = params.parent_scope, @@ -456,7 +355,7 @@ angular.module('SurveyHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', {name: 'Multiple Choice (multiple select)', type: 'multiselect'}, {name: 'JSON', type: 'json'}, {name: 'Integer', type: 'integer'}, - {name: 'Float', type: 'number'} + {name: 'Float', type: 'float'} ]; scope.deleteSurvey = function() { @@ -482,29 +381,27 @@ angular.module('SurveyHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', }); }; scope.addQuestion = function(){ - GenerateForm.inject(SurveyQuestionForm, { id:'new_question', scope:scope, breadCrumbs: false}); + GenerateForm.inject(SurveyQuestionForm, { id:'new_question', mode: 'add' , scope:scope, breadCrumbs: false}); + scope.required = true; //set the required checkbox to true via the ngmodel attached to scope.required. + }; + scope.editQuestion = function(question){ + alert('success : ' + question); }; - scope.finalizeQuestion= function(data, labels){ - var key, - html = '
'; - - for (key in data) { - html+='
'+data[key]+'
\n'; - } - - html+='
'; - - $('#finalized_questions').before(html); - $('#add_question_btn').show(); - $('#add_question_btn').removeAttr('disabled'); - $('#survey_maker_save_btn').removeAttr('disabled'); + scope.finalizeQuestion= function(data){ + FinalizeQuestion({ + scope: scope, + question: data, + id: id, + //callback? + }); }; scope.addNewQuestion = function(){ // $('#add_question_btn').on("click" , function(){ scope.addQuestion(); $('#add_question_btn').attr('disabled', 'disabled'); + $('#add_question_btn').hide(); // }); }; scope.submitQuestion = function(){ @@ -538,6 +435,8 @@ angular.module('SurveyHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', Wait('stop'); scope.survey_questions.push(data); $('#new_question .aw-form-well').remove(); + // scope.addQuestion() + $('#add_question_btn').show(); // for(fld in form.fields){ // $scope[fld] = ''; // } @@ -571,137 +470,6 @@ angular.module('SurveyHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', } }; }; - }]) - - .factory('SchedulesListInit', [ function() { - return function(params) { - var scope = params.scope, - list = params.list, - choices = params.choices; - scope[list.name].forEach(function(item, item_idx) { - var fld, field, - itm = scope[list.name][item_idx]; - itm.enabled = (itm.enabled) ? true : false; - if (itm.enabled) { - itm.play_tip = 'Schedule is active. Click to stop.'; - itm.status = 'active'; - itm.status_tip = 'Schedule is active. Click to stop.'; - } - else { - itm.play_tip = 'Schedule is stopped. Click to activate.'; - itm.status = 'stopped'; - itm.status_tip = 'Schedule is stopped. Click to activate.'; - } - itm.nameTip = item.name + " schedule. Click to edit."; - // Copy summary_field values - for (field in list.fields) { - fld = list.fields[field]; - if (fld.sourceModel) { - if (itm.summary_fields[fld.sourceModel]) { - itm[field] = itm.summary_fields[fld.sourceModel][fld.sourceField]; - } - } - } - // Set the item type label - if (list.fields.type) { - choices.every(function(choice) { - if (choice.value === item.type) { - itm.type_label = choice.label; - return false; - } - return true; - }); - } - }); - }; - }]) - - /** - * - * Called from a controller to setup the scope for a schedules list - * - */ - .factory('LoadSchedulesScope', ['$compile', '$location', '$routeParams','SearchInit', 'PaginateInit', 'GenerateList', 'SchedulesControllerInit', - 'SchedulesListInit', 'SearchWidget', - function($compile, $location, $routeParams, SearchInit, PaginateInit, GenerateList, SchedulesControllerInit, SchedulesListInit, SearchWidget) { - return function(params) { - var parent_scope = params.parent_scope, - scope = params.scope, - list = params.list, - id = params.id, - url = params.url, - pageSize = params.pageSize || 5, - spinner = (params.spinner === undefined) ? true : params.spinner, - base = $location.path().replace(/^\//, '').split('/')[0], - e, html; - - if (base === 'jobs') { - // on jobs page the search widget appears on the right - html = SearchWidget({ - iterator: list.iterator, - template: params.list, - includeSize: false - }); - e = angular.element(document.getElementById(id + '-search-container')).append(html); - $compile(e)(scope); - GenerateList.inject(list, { - mode: 'edit', - id: id, - breadCrumbs: false, - scope: scope, - showSearch: false - }); - } - else { - GenerateList.inject(list, { - mode: 'edit', - id: id, - breadCrumbs: false, - scope: scope, - searchSize: 'col-lg-6 col-md-6 col-sm-6 col-xs-12', - showSearch: true - }); - } - - SearchInit({ - scope: scope, - set: list.name, - list: list, - url: url - }); - - PaginateInit({ - scope: scope, - list: list, - url: url, - pageSize: pageSize - }); - - scope.iterator = list.iterator; - - if (scope.removePostRefresh) { - scope.removePostRefresh(); - } - scope.$on('PostRefresh', function(){ - SchedulesControllerInit({ - scope: scope, - parent_scope: parent_scope, - list: list - }); - SchedulesListInit({ - scope: scope, - list: list, - choices: parent_scope.type_choices - }); - parent_scope.$emit('listLoaded'); - }); - - if ($routeParams.id__int) { - scope[list.iterator + 'SearchField'] = 'id'; - scope[list.iterator + 'SearchValue'] = $routeParams.id__int; - scope[list.iterator + 'SearchFieldLabel'] = 'ID'; - } - - scope.search(list.iterator, null, null, null, null, spinner); - }; }]); + + diff --git a/awx/ui/static/less/survey-maker.less b/awx/ui/static/less/survey-maker.less index 4d8876b88c..20a6a0ac8b 100644 --- a/awx/ui/static/less/survey-maker.less +++ b/awx/ui/static/less/survey-maker.less @@ -34,13 +34,31 @@ } .question_final{ - border: 1px dashed; - border-color: rgb(204,204,204); - border-radius: 4px; + /*border: 1px dashed; + *border-color: rgb(204,204,204); + *border-radius: 4px; + */ padding: 5px; - margin-top: 15px; - height: 130px; - opacity: 0.4; + opacity: 0.7; + + + textarea{ + margin-left: 15px; + } + + input{ + margin-left: 15px; + } + + label{ + margin-left: 15px; + } +} +#new_question{ + margin-top: 5px; +} +question_actions{ + opacity: 1.0; } #add_question_btn{ diff --git a/awx/ui/static/lib/ansible/directives.js b/awx/ui/static/lib/ansible/directives.js index 52d6080912..4a5b536289 100644 --- a/awx/ui/static/lib/ansible/directives.js +++ b/awx/ui/static/lib/ansible/directives.js @@ -63,6 +63,32 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Job }; }) + // caplitalize Add to any input field where the first letter of each + // word should be capitalized. Use in place of css test-transform. + // For some reason "text-transform: capitalize" in breadcrumbs + // causes a break at each blank space. And of course, + // "autocapitalize='word'" only works in iOS. Use this as a fix. + .directive('awSurveyQuestion', function() { + return { + require: 'ngModel', + link: function(scope, elm, attrs, ctrl) { + ctrl.$parsers.unshift( function(viewValue) { + var values = viewValue.split(" "), + result = "", i; + result += values[0].charAt(0).toUpperCase() + values[0].substr(1) + ' '; + for (i = 1; i < values.length; i++){ + result += values[i] + ' '; + } + result = result.trim(); + if (result !== viewValue) { + ctrl.$setViewValue(result); + ctrl.$render(); + } + return result; + }); + } + }; + }) // integer Validate that input is of type integer. Taken from Angular developer // guide, form examples. Add min and max directives, and this will check // entered values is within the range. diff --git a/awx/ui/static/lib/ansible/form-generator.js b/awx/ui/static/lib/ansible/form-generator.js index 741e15263a..357d6b57de 100644 --- a/awx/ui/static/lib/ansible/form-generator.js +++ b/awx/ui/static/lib/ansible/form-generator.js @@ -735,6 +735,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator html += (field.readonly || field.showonly) ? "readonly " : ""; html += (field.awPassMatch) ? "awpassmatch=\"" + field.associated + "\" " : ""; html += (field.capitalize) ? "capitalize " : ""; + html += (field.awSurveyQuestion) ? "aw-survey-question" : "" ; html += (field.ask) ? "ng-disabled=\"" + fld + "_ask\" " : ""; html += (field.autocomplete !== undefined) ? this.attr(field, 'autocomplete') : ""; html += (field.awRequiredWhen) ? "data-awrequired-init=\"" + field.awRequiredWhen.init + "\" aw-required-when=\"" + @@ -905,7 +906,12 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator field.awRequiredWhen.variable + "\" " : ""; html += ">\n"; html += "\n"; html += "\n"; // Add error messages