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:
parent
1fc6a34e62
commit
b37ee2f611
@ -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';
|
||||
|
@ -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;
|
||||
},
|
||||
|
@ -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;
|
||||
});
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
@ -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'),
|
||||
|
@ -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;
|
||||
});
|
||||
}
|
||||
];
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
13
awx/ui/client/src/templates/workflows/workflow.block.less
Normal file
13
awx/ui/client/src/templates/workflows/workflow.block.less
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user