1
0
mirror of https://github.com/ansible/awx.git synced 2024-11-02 01:21:21 +03:00

Show warning on wfjt form when the workflow contains deleted job templates

This commit is contained in:
mabashian 2018-04-17 16:57:28 -04:00
parent 1fc6a34e62
commit b37ee2f611
7 changed files with 210 additions and 146 deletions

View File

@ -126,6 +126,7 @@
@import '../../src/templates/survey-maker/survey-maker.block.less';
@import '../../src/templates/survey-maker/shared/survey-controls.block.less';
@import '../../src/templates/survey-maker/survey-maker.block.less';
@import '../../src/templates/workflows/workflow.block.less';
@import '../../src/templates/workflows/workflow-chart/workflow-chart.block.less';
@import '../../src/templates/workflows/workflow-controls/workflow-controls.block.less';
@import '../../src/templates/workflows/workflow-maker/workflow-maker.block.less';

View File

@ -545,6 +545,8 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
html += "' ";
html += (field.ngDisabled) ? `ng-disabled="${field.ngDisabled}" ` : "";
html += " class='ScheduleToggle-switch' ng-click='" + field.ngClick + "' translate>" + i18n._("OFF") + "</button></div></div>";
} else if (field.type === 'html') {
html += field.html;
}
return html;
},

View File

@ -377,6 +377,15 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
response.status
});
});
}],
workflowLaunch: ['$stateParams', 'WorkflowJobTemplateModel',
function($stateParams, WorkflowJobTemplate) {
let workflowJobTemplate = new WorkflowJobTemplate();
return workflowJobTemplate.getLaunch($stateParams.workflow_job_template_id)
.then(({data}) => {
return data;
});
}]
}
}

View File

@ -27,6 +27,16 @@ export default ['NotificationsList', 'i18n', function(NotificationsList, i18n) {
detailsClick: "$state.go('templates.editWorkflowJobTemplate')",
include: ['/static/partials/survey-maker-modal.html'],
headerFields: {
missingTemplates: {
type: 'html',
html: `<div ng-show="missingTemplates" class="Workflow-warning">
<span class="Workflow-warningIcon fa fa-warning"></span>` +
i18n._("Missing Job Templates found in the <span class='Workflow-warningLink' ng-click='openWorkflowMaker()'>Workflow Editor</span>") +
`</div>`
}
},
fields: {
name: {
label: i18n._('Name'),

View File

@ -10,10 +10,15 @@ export default [
'Wait', 'Empty', 'ToJSON', 'initSurvey', '$state', 'CreateSelect2',
'ParseVariableString', 'TemplatesService', 'Rest', 'ToggleNotification',
'OrgAdminLookup', 'availableLabels', 'selectedLabels', 'workflowJobTemplateData', 'i18n',
'workflowLaunch', '$transitions', 'WorkflowJobTemplateModel',
function($scope, $stateParams, WorkflowForm, GenerateForm, Alert,
ProcessErrors, GetBasePath, $q, ParseTypeChange, Wait, Empty,
ToJSON, SurveyControllerInit, $state, CreateSelect2, ParseVariableString,
TemplatesService, Rest, ToggleNotification, OrgAdminLookup, availableLabels, selectedLabels, workflowJobTemplateData, i18n) {
ProcessErrors, GetBasePath, $q, ParseTypeChange, Wait, Empty,
ToJSON, SurveyControllerInit, $state, CreateSelect2, ParseVariableString,
TemplatesService, Rest, ToggleNotification, OrgAdminLookup, availableLabels, selectedLabels, workflowJobTemplateData, i18n,
workflowLaunch, $transitions, WorkflowJobTemplate
) {
$scope.missingTemplates = _.has(workflowLaunch, 'node_templates_missing') && workflowLaunch.node_templates_missing.length > 0 ? true : false;
$scope.$watch('workflow_job_template_obj.summary_fields.user_capabilities.edit', function(val) {
if (val === false) {
@ -21,6 +26,25 @@ export default [
}
});
const criteriaObj = {
from: (state) => state.name === 'templates.editWorkflowJobTemplate.workflowMaker',
to: (state) => state.name === 'templates.editWorkflowJobTemplate'
};
$transitions.onSuccess(criteriaObj, function() {
if ($scope.missingTemplates) {
// Go out and check the new launch response to see if the user has fixed the
// missing node templates
let workflowJobTemplate = new WorkflowJobTemplate();
workflowJobTemplate.getLaunch($stateParams.workflow_job_template_id)
.then(({data}) => {
$scope.missingTemplates = _.has(data, 'node_templates_missing') && data.node_templates_missing.length > 0 ? true : false;
});
}
});
// Inject dynamic view
let form = WorkflowForm(),
generator = GenerateForm,
@ -30,119 +54,24 @@ export default [
$scope.parseType = 'yaml';
$scope.includeWorkflowMaker = false;
function init() {
$scope.openWorkflowMaker = function() {
$state.go('.workflowMaker');
};
// Select2-ify the lables input
CreateSelect2({
element:'#workflow_job_template_labels',
multiple: true,
addNew: true
});
$scope.formSave = function () {
let fld, data = {};
$scope.invalid_survey = false;
SurveyControllerInit({
scope: $scope,
parent_scope: $scope,
id: id,
templateType: 'workflow_job_template'
});
$scope.labelOptions = availableLabels
.map((i) => ({label: i.name, value: i.id}));
var opts = selectedLabels
.map(i => ({id: i.id + "",
test: i.name}));
CreateSelect2({
element:'#workflow_job_template_labels',
multiple: true,
addNew: true,
opts: opts
});
$scope.workflowEditorTooltip = i18n._("Click here to open the workflow graph editor.");
$scope.surveyTooltip = i18n._('Surveys allow users to be prompted at job launch with a series of questions related to the job. This allows for variables to be defined that affect the playbook run at time of launch.');
$scope.workflow_job_template_obj = workflowJobTemplateData;
$scope.name = workflowJobTemplateData.name;
$scope.can_edit = workflowJobTemplateData.summary_fields.user_capabilities.edit;
let fld, i;
for (fld in form.fields) {
if (fld !== 'variables' && fld !== 'survey' && workflowJobTemplateData[fld] !== null && workflowJobTemplateData[fld] !== undefined) {
if (form.fields[fld].type === 'select') {
if ($scope[fld + '_options'] && $scope[fld + '_options'].length > 0) {
for (i = 0; i < $scope[fld + '_options'].length; i++) {
if (workflowJobTemplateData[fld] === $scope[fld + '_options'][i].value) {
$scope[fld] = $scope[fld + '_options'][i];
}
}
} else {
$scope[fld] = workflowJobTemplateData[fld];
}
} else {
$scope[fld] = workflowJobTemplateData[fld];
if(!Empty(workflowJobTemplateData.summary_fields.survey)) {
$scope.survey_exists = true;
}
}
}
if (fld === 'variables') {
// Parse extra_vars, converting to YAML.
$scope.variables = ParseVariableString(workflowJobTemplateData.extra_vars);
ParseTypeChange({ scope: $scope, field_id: 'workflow_job_template_variables' });
}
if (form.fields[fld].type === 'lookup' && workflowJobTemplateData.summary_fields[form.fields[fld].sourceModel]) {
$scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
workflowJobTemplateData.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
}
if (form.fields[fld].type === 'checkbox_group') {
for(var j=0; j<form.fields[fld].fields.length; j++) {
$scope[form.fields[fld].fields[j].name] = workflowJobTemplateData[form.fields[fld].fields[j].name];
}
}
// Can't have a survey enabled without a survey
if($scope.survey_enabled === true && $scope.survey_exists!==true){
$scope.survey_enabled = false;
}
if(workflowJobTemplateData.organization) {
OrgAdminLookup.checkForRoleLevelAdminAccess(workflowJobTemplateData.organization, 'workflow_admin_role')
.then(function(canEditOrg){
$scope.canEditOrg = canEditOrg;
});
}
else {
$scope.canEditOrg = true;
}
generator.clearApiErrors($scope);
$scope.url = workflowJobTemplateData.url;
$scope.survey_enabled = workflowJobTemplateData.survey_enabled;
Wait('start');
$scope.includeWorkflowMaker = true;
$scope.$on('SurveySaved', function() {
Wait('stop');
$scope.survey_exists = true;
$scope.invalid_survey = false;
});
}
$scope.openWorkflowMaker = function() {
$state.go('.workflowMaker');
};
$scope.formSave = function () {
let fld, data = {};
$scope.invalid_survey = false;
// Can't have a survey enabled without a survey
if($scope.survey_enabled === true && $scope.survey_exists!==true){
$scope.survey_enabled = false;
}
generator.clearApiErrors($scope);
Wait('start');
try {
try {
for (fld in form.fields) {
if(form.fields[fld].type === 'checkbox_group') {
// Loop across the checkboxes
@ -301,6 +230,91 @@ export default [
});
};
init();
// Select2-ify the lables input
CreateSelect2({
element:'#workflow_job_template_labels',
multiple: true,
addNew: true
});
SurveyControllerInit({
scope: $scope,
parent_scope: $scope,
id: id,
templateType: 'workflow_job_template'
});
$scope.labelOptions = availableLabels
.map((i) => ({label: i.name, value: i.id}));
var opts = selectedLabels
.map(i => ({id: i.id + "",
test: i.name}));
CreateSelect2({
element:'#workflow_job_template_labels',
multiple: true,
addNew: true,
opts: opts
});
$scope.workflowEditorTooltip = i18n._("Click here to open the workflow graph editor.");
$scope.surveyTooltip = i18n._('Surveys allow users to be prompted at job launch with a series of questions related to the job. This allows for variables to be defined that affect the playbook run at time of launch.');
$scope.workflow_job_template_obj = workflowJobTemplateData;
$scope.name = workflowJobTemplateData.name;
$scope.can_edit = workflowJobTemplateData.summary_fields.user_capabilities.edit;
let fld, i;
for (fld in form.fields) {
if (fld !== 'variables' && fld !== 'survey' && workflowJobTemplateData[fld] !== null && workflowJobTemplateData[fld] !== undefined) {
if (form.fields[fld].type === 'select') {
if ($scope[fld + '_options'] && $scope[fld + '_options'].length > 0) {
for (i = 0; i < $scope[fld + '_options'].length; i++) {
if (workflowJobTemplateData[fld] === $scope[fld + '_options'][i].value) {
$scope[fld] = $scope[fld + '_options'][i];
}
}
} else {
$scope[fld] = workflowJobTemplateData[fld];
}
} else {
$scope[fld] = workflowJobTemplateData[fld];
if(!Empty(workflowJobTemplateData.summary_fields.survey)) {
$scope.survey_exists = true;
}
}
}
if (fld === 'variables') {
// Parse extra_vars, converting to YAML.
$scope.variables = ParseVariableString(workflowJobTemplateData.extra_vars);
ParseTypeChange({ scope: $scope, field_id: 'workflow_job_template_variables' });
}
if (form.fields[fld].type === 'lookup' && workflowJobTemplateData.summary_fields[form.fields[fld].sourceModel]) {
$scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
workflowJobTemplateData.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
}
}
if(workflowJobTemplateData.organization) {
OrgAdminLookup.checkForRoleLevelAdminAccess(workflowJobTemplateData.organization, 'workflow_admin_role')
.then(function(canEditOrg){
$scope.canEditOrg = canEditOrg;
});
}
else {
$scope.canEditOrg = true;
}
$scope.url = workflowJobTemplateData.url;
$scope.survey_enabled = workflowJobTemplateData.survey_enabled;
$scope.includeWorkflowMaker = true;
$scope.$on('SurveySaved', function() {
Wait('stop');
$scope.survey_exists = true;
$scope.invalid_survey = false;
});
}
];

View File

@ -76,15 +76,19 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
// Create the node
let sendableNodeData = {
unified_job_template: params.node.unifiedJobTemplate.id,
credential: _.get(params, 'node.originalNodeObj.credential') || null
extra_data: {},
inventory: null,
job_type: null,
job_tags: null,
skip_tags: null,
limit: null,
diff_mode: null,
verbosity: null,
credential: null
};
if (_.has(params, 'node.promptData.extraVars')) {
if (_.get(params, 'node.promptData.launchConf.defaults.extra_vars')) {
if (!sendableNodeData.extra_data) {
sendableNodeData.extra_data = {};
}
const defaultVars = jsyaml.safeLoad(params.node.promptData.launchConf.defaults.extra_vars);
// Only include extra vars that differ from the template default vars
@ -674,11 +678,14 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
launchConf.passwords_needed_to_start.length === 0 &&
launchConf.variables_needed_to_start.length === 0) {
$scope.showPromptButton = false;
$scope.promptModalMissingReqFields = false;
} else {
$scope.showPromptButton = true;
if (launchConf.ask_inventory_on_launch && !_.has(launchConf, 'defaults.inventory') && !_.has($scope, 'nodeBeingEdited.originalNodeObj.summary_fields.inventory')) {
$scope.promptModalMissingReqFields = true;
} else {
$scope.promptModalMissingReqFields = false;
}
if (responses[1].data.survey_enabled) {
@ -728,38 +735,42 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
});
}
if ($scope.nodeBeingEdited.unifiedJobTemplate.type === "job_template") {
if (_.get($scope, 'nodeBeingEdited.unifiedJobTemplate')) {
if (_.get($scope, 'nodeBeingEdited.unifiedJobTemplate.type') === "job_template") {
$scope.workflowMakerFormConfig.activeTab = "jobs";
}
$scope.selectedTemplate = $scope.nodeBeingEdited.unifiedJobTemplate;
if ($scope.selectedTemplate.unified_job_type) {
switch ($scope.selectedTemplate.unified_job_type) {
case "job":
$scope.workflowMakerFormConfig.activeTab = "jobs";
break;
case "project_update":
$scope.workflowMakerFormConfig.activeTab = "project_sync";
break;
case "inventory_update":
$scope.workflowMakerFormConfig.activeTab = "inventory_sync";
break;
}
} else if ($scope.selectedTemplate.type) {
switch ($scope.selectedTemplate.type) {
case "job_template":
$scope.workflowMakerFormConfig.activeTab = "jobs";
break;
case "project":
$scope.workflowMakerFormConfig.activeTab = "project_sync";
break;
case "inventory_source":
$scope.workflowMakerFormConfig.activeTab = "inventory_sync";
break;
}
}
} else {
$scope.workflowMakerFormConfig.activeTab = "jobs";
}
$scope.selectedTemplate = $scope.nodeBeingEdited.unifiedJobTemplate;
if ($scope.selectedTemplate.unified_job_type) {
switch ($scope.selectedTemplate.unified_job_type) {
case "job":
$scope.workflowMakerFormConfig.activeTab = "jobs";
break;
case "project_update":
$scope.workflowMakerFormConfig.activeTab = "project_sync";
break;
case "inventory_update":
$scope.workflowMakerFormConfig.activeTab = "inventory_sync";
break;
}
} else if ($scope.selectedTemplate.type) {
switch ($scope.selectedTemplate.type) {
case "job_template":
$scope.workflowMakerFormConfig.activeTab = "jobs";
break;
case "project":
$scope.workflowMakerFormConfig.activeTab = "project_sync";
break;
case "inventory_source":
$scope.workflowMakerFormConfig.activeTab = "inventory_sync";
break;
}
}
let siblingConnectionTypes = WorkflowService.getSiblingConnectionTypes({
tree: $scope.treeData.data,
parentId: parent.id,
@ -771,7 +782,7 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
switch($scope.nodeBeingEdited.edgeType) {
case "always":
$scope.edgeType = {label: "Always", value: "always"};
if (siblingConnectionTypes.length === 1 && _.includes(siblingConnectionTypes, "always")) {
if (siblingConnectionTypes.length === 1 && _.includes(siblingConnectionTypes, "always") || $scope.nodeBeingEdited.isRoot) {
edgeDropdownOptions = ["always"];
}
break;
@ -987,11 +998,14 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
launchConf.passwords_needed_to_start.length === 0 &&
launchConf.variables_needed_to_start.length === 0) {
$scope.showPromptButton = false;
$scope.promptModalMissingReqFields = false;
} else {
$scope.showPromptButton = true;
if (launchConf.ask_inventory_on_launch && !_.has(launchConf, 'defaults.inventory')) {
$scope.promptModalMissingReqFields = true;
} else {
$scope.promptModalMissingReqFields = false;
}
if (launchConf.survey_enabled) {
@ -1048,6 +1062,7 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
$scope.selectedTemplate = angular.copy(selectedTemplate);
$scope.selectedTemplateInvalid = false;
$scope.showPromptButton = false;
$scope.promptModalMissingReqFields = false;
}
};

View File

@ -0,0 +1,13 @@
.Workflow-warning {
float: right;
margin-right: 20px;
color: @default-interface-txt;
}
.Workflow-warningIcon {
color: @default-warning;
margin-right: 5px;
}
.Workflow-warningLink {
color: @default-link;
cursor: pointer;
}