Added a lot of permissions related logic to the workflow form as well as the workflow maker. I know it's not perfect but its a step in the right direction.

This commit is contained in:
Michael Abashian 2016-11-10 16:43:23 -05:00
parent 59aeec5705
commit ca32c34036
13 changed files with 145 additions and 126 deletions

View File

@ -33,7 +33,7 @@ export default
name: {
label: i18n._('Name'),
type: 'text',
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)',
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)',
required: true,
column: 1
},
@ -41,7 +41,7 @@ export default
label: i18n._('Description'),
type: 'text',
column: 1,
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
job_type: {
label: i18n._('Job Type'),
@ -63,7 +63,7 @@ export default
ngShow: "!job_type.value || job_type.value !== 'scan'",
text: i18n._('Prompt on launch')
},
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
inventory: {
label: i18n._('Inventory'),
@ -87,7 +87,7 @@ export default
ngShow: "!job_type.value || job_type.value !== 'scan'",
text: i18n._('Prompt on launch')
},
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
project: {
label: i18n._('Project'),
@ -110,13 +110,13 @@ export default
dataTitle: i18n._('Project'),
dataPlacement: 'right',
dataContainer: "body",
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
playbook: {
label: i18n._('Playbook'),
type:'select',
ngOptions: 'book for book in playbook_options track by book',
ngDisabled: "(job_type.value === 'scan' && project_name === 'Default') || !(job_template_obj.summary_fields.user_capabilities.edit || canAdd)",
ngDisabled: "(job_type.value === 'scan' && project_name === 'Default') || !(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)",
id: 'playbook-select',
awRequiredWhen: {
reqExpression: "playbookrequired",
@ -154,7 +154,7 @@ export default
variable: 'ask_credential_on_launch',
text: i18n._('Prompt on launch')
},
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
cloud_credential: {
label: i18n._('Cloud Credential'),
@ -172,7 +172,7 @@ export default
dataTitle: i18n._('Cloud Credential'),
dataPlacement: 'right',
dataContainer: "body",
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
network_credential: {
label: i18n._('Network Credential'),
@ -189,7 +189,7 @@ export default
dataTitle: i18n._('Network Credential'),
dataPlacement: 'right',
dataContainer: "body",
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
forks: {
label: i18n._('Forks'),
@ -207,7 +207,7 @@ export default
dataTitle: i18n._('Forks'),
dataPlacement: 'right',
dataContainer: "body",
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)' // TODO: get working
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)' // TODO: get working
},
limit: {
label: i18n._('Limit'),
@ -223,7 +223,7 @@ export default
variable: 'ask_limit_on_launch',
text: i18n._('Prompt on launch')
},
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
verbosity: {
label: i18n._('Verbosity'),
@ -236,7 +236,7 @@ export default
dataTitle: i18n._('Verbosity'),
dataPlacement: 'right',
dataContainer: "body",
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
job_tags: {
label: i18n._('Job Tags'),
@ -254,7 +254,7 @@ export default
variable: 'ask_tags_on_launch',
text: i18n._('Prompt on launch')
},
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
skip_tags: {
label: i18n._('Skip Tags'),
@ -272,7 +272,7 @@ export default
variable: 'ask_skip_tags_on_launch',
text: i18n._('Prompt on launch')
},
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
checkbox_group: {
label: i18n._('Options'),
@ -287,7 +287,7 @@ export default
dataTitle: i18n._('Become Privilege Escalation'),
dataContainer: "body",
labelClass: 'stack-inline',
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
}, {
name: 'allow_callbacks',
label: i18n._('Allow Provisioning Callbacks'),
@ -300,7 +300,7 @@ export default
dataTitle: i18n._('Allow Provisioning Callbacks'),
dataContainer: "body",
labelClass: 'stack-inline',
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
}]
},
callback_url: {
@ -314,7 +314,7 @@ export default
dataPlacement: 'top',
dataTitle: i18n._('Provisioning Callback URL'),
dataContainer: "body",
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
host_config_key: {
label: i18n._('Host Config Key'),
@ -328,7 +328,7 @@ export default
dataPlacement: 'right',
dataTitle: i18n._("Host Config Key"),
dataContainer: "body",
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
labels: {
label: i18n._('Labels'),
@ -340,7 +340,7 @@ export default
dataPlacement: 'right',
awPopOver: i18n._("<p>Optional labels that describe this job template, such as 'dev' or 'test'. Labels can be used to group and filter job templates and completed jobs in the Tower display.</p>"),
dataContainer: 'body',
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
variables: {
label: i18n._('Extra Variables'),
@ -362,14 +362,14 @@ export default
variable: 'ask_variables_on_launch',
text: i18n._('Prompt on launch')
},
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)' // TODO: get working
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)' // TODO: get working
}
},
buttons: { //for now always generates <button> tags
add_survey: {
ngClick: 'addSurvey()',
ngShow: 'job_type.value !== "scan" && !survey_exists && (job_template_obj.summary_fields.user_capabilities.edit || canAdd)',
ngShow: 'job_type.value !== "scan" && !survey_exists && (job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)',
awFeature: 'surveys',
awToolTip: '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.',
dataPlacement: 'top'
@ -377,25 +377,25 @@ export default
edit_survey: {
ngClick: 'editSurvey()',
awFeature: 'surveys',
ngShow: 'job_type.value !== "scan" && survey_exists && (job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngShow: 'job_type.value !== "scan" && survey_exists && (job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
view_survey: {
ngClick: 'editSurvey()',
awFeature: 'surveys',
ngShow: 'job_type.value !== "scan" && survey_exists && !(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngShow: 'job_type.value !== "scan" && survey_exists && !(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
cancel: {
ngClick: 'formCancel()',
ngShow: '(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngShow: '(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
close: {
ngClick: 'formCancel()',
ngShow: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngShow: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
},
save: {
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: "job_templates_form.$invalid",//true //Disable when $pristine or $invalid, optional and when can_edit = false, for permission reasons
ngShow: '(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngShow: '(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
}
},
@ -422,7 +422,7 @@ export default
awToolTip: 'Add a permission',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD',
ngShow: '(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngShow: '(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
}
},

View File

@ -28,6 +28,7 @@ export default
label: 'Type',
type: 'radio_group',
ngShow: 'selectedTemplate && showTypeOptions',
ngDisabled: '!canAddWorkflowJobTemplate',
options: [
{
label: 'On&nbsp;Success',
@ -63,6 +64,7 @@ export default
dataPlacement: 'right',
dataContainer: "body",
ngShow: "selectedTemplate.ask_credential_on_launch",
ngDisabled: '!canAddWorkflowJobTemplate',
awRequiredWhen: {
reqExpression: 'selectedTemplate && selectedTemplate.ask_credential_on_launch'
}
@ -82,6 +84,7 @@ export default
dataPlacement: 'right',
dataContainer: "body",
ngShow: "selectedTemplate.ask_inventory_on_launch",
ngDisabled: '!canAddWorkflowJobTemplate',
awRequiredWhen: {
reqExpression: 'selectedTemplate && selectedTemplate.ask_inventory_on_launch'
}
@ -100,6 +103,7 @@ export default
dataPlacement: 'right',
dataContainer: "body",
ngShow: "selectedTemplate.ask_job_type_on_launch",
ngDisabled: '!canAddWorkflowJobTemplate',
awRequiredWhen: {
reqExpression: 'selectedTemplate && selectedTemplate.ask_job_type_on_launch'
}
@ -114,7 +118,8 @@ export default
dataTitle: 'Limit',
dataPlacement: 'right',
dataContainer: "body",
ngShow: "selectedTemplate.ask_limit_on_launch"
ngShow: "selectedTemplate.ask_limit_on_launch",
ngDisabled: '!canAddWorkflowJobTemplate'
},
job_tags: {
label: 'Job Tags',
@ -128,7 +133,8 @@ export default
dataTitle: "Job Tags",
dataPlacement: "right",
dataContainer: "body",
ngShow: "selectedTemplate.ask_tags_on_launch"
ngShow: "selectedTemplate.ask_tags_on_launch",
ngDisabled: '!canAddWorkflowJobTemplate'
},
skip_tags: {
label: 'Skip Tags',
@ -142,16 +148,23 @@ export default
dataTitle: "Skip Tags",
dataPlacement: "right",
dataContainer: "body",
ngShow: "selectedTemplate.ask_skip_tags_on_launch"
ngShow: "selectedTemplate.ask_skip_tags_on_launch",
ngDisabled: '!canAddWorkflowJobTemplate'
}
},
buttons: {
cancel: {
ngClick: 'cancelNodeForm()'
ngClick: 'cancelNodeForm()',
ngShow: 'canAddWorkflowJobTemplate'
},
close: {
ngClick: 'cancelNodeForm()',
ngShow: '!canAddWorkflowJobTemplate'
},
save: {
ngClick: 'saveNodeForm()',
ngDisabled: "workflow_maker_form.$invalid || !selectedTemplate"
ngDisabled: "workflow_maker_form.$invalid || !selectedTemplate",
ngShow: 'canAddWorkflowJobTemplate'
}
}
})

View File

@ -29,14 +29,15 @@ export default
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true,
required: true,
ngDisabled: '!(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)',
column: 1
},
description: {
label: 'Description',
type: 'text',
column: 1
column: 1,
ngDisabled: '!(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)'
},
organization: {
label: 'Organization',
@ -48,7 +49,8 @@ export default
dataTitle: 'Organization',
dataContainer: 'body',
dataPlacement: 'right',
column: 1
column: 1,
ngDisabled: '!(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)'
},
labels: {
label: 'Labels',
@ -59,7 +61,8 @@ export default
dataTitle: 'Labels',
dataPlacement: 'right',
awPopOver: "<p>Optional labels that describe this job template, such as 'dev' or 'test'. Labels can be used to group and filter job templates and completed jobs in the Tower display.</p>",
dataContainer: 'body'
dataContainer: 'body',
ngDisabled: '!(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)'
},
variables: {
label: 'Extra Variables',
@ -76,17 +79,24 @@ export default
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n",
dataTitle: 'Extra Variables',
dataPlacement: 'right',
dataContainer: "body"
dataContainer: "body",
ngDisabled: '!(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)' // TODO: get working
}
},
buttons: { //for now always generates <button> tags
cancel: {
ngClick: 'formCancel()'
ngClick: 'formCancel()',
ngShow: '(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)'
},
close: {
ngClick: 'formCancel()',
ngShow: '!(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)'
},
save: {
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: "workflow_form.$invalid || can_edit!==true"//true //Disable when $pristine or $invalid, optional and when can_edit = false, for permission reasons
ngDisabled: "workflow_form.$invalid || can_edit!==true", //Disable when $pristine or $invalid, optional and when can_edit = false, for permission reasons
ngShow: '(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)'
}
},
@ -108,7 +118,7 @@ export default
awToolTip: 'Add a permission',
actionClass: 'btn List-buttonSubmit',
buttonContent: '&#43; ADD',
ngShow: '(job_template_obj.summary_fields.user_capabilities.edit || canAdd)'
ngShow: '(workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)'
}
},

View File

@ -31,7 +31,7 @@ export default
$scope.$watch('job_template_obj.summary_fields.user_capabilities.edit', function(val) {
if (val === false) {
$scope.canAdd = false;
$scope.canAddJobTemplate = false;
}
});

View File

@ -20,7 +20,7 @@
$scope.$watch('workflow_job_template_obj.summary_fields.user_capabilities.edit', function(val) {
if (val === false) {
$scope.canAdd = false;
$scope.canAddWorkflowJobTemplate = false;
}
});
@ -125,13 +125,6 @@
}
function init() {
// // Inject the edit form
// generator.inject(form, {
// mode: 'edit' ,
// scope: $scope,
// related: false
// });
// generator.reset();
// Select2-ify the lables input
CreateSelect2({
@ -140,24 +133,6 @@
addNew: true
});
// // Make the variables textarea look nice
// ParseTypeChange({
// scope: $scope,
// field_id: 'workflow_job_template_variables',
// onChange: function() {
// $scope[form.name + '_form'].$setDirty();
// }
// });
// // Initialize the organization lookup
// LookUpInit({
// scope: $scope,
// form: form,
// list: OrganizationList,
// field: 'organization',
// input_type: 'radio'
// });
Rest.setUrl('api/v1/labels');
Wait("start");
Rest.get()

View File

@ -22,8 +22,13 @@ export default ['$scope', '$rootScope', '$location', '$stateParams', 'Rest', 'Al
$scope.canAdd = false;
rbacUiControlService.canAdd("job_templates")
.then(function(canAdd) {
$scope.canAdd = canAdd;
.then(function(canAddJobTemplate) {
$scope.canAddJobTemplate = canAddJobTemplate;
});
rbacUiControlService.canAdd("workflow_job_templates")
.then(function(canAddWorkflowJobTemplate) {
$scope.canAddWorkflowJobTemplate = canAddWorkflowJobTemplate;
});
// search init
$scope.list = list;

View File

@ -108,7 +108,7 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
},
views: {
'modal': {
template: ` <workflow-maker ng-if="includeWorkflowMaker" tree-data="workflowTree"></workflow-maker>`
template: ` <workflow-maker ng-if="includeWorkflowMaker" tree-data="workflowTree" can-add-workflow-job-template="canAddWorkflowJobTemplate"></workflow-maker>`
},
'jobTemplateList@templates.editWorkflowJobTemplate.workflowMaker': {
templateProvider: function(WorkflowMakerJobTemplateList, generateList) {
@ -260,8 +260,8 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
});
return html;
},
controller: ['$scope',
function($scope) {
controller: ['$scope', '$timeout', 'CreateSelect2',
function($scope, $timeout, CreateSelect2) {
function resetPromptFields() {
$scope.credential = null;
$scope.credential_name = null;
@ -296,6 +296,14 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
_.forOwn(options.presetValues, function(value, key) {
$scope[key] = value;
});
// The default needs to be in place before we can select2-ify the dropdown
$timeout(function() {
CreateSelect2({
element: '#workflow_maker_job_type',
multiple: false
});
});
});
$scope.$on('setEdgeType', function(e, edgeType) {

View File

@ -10,6 +10,7 @@ export default [
return {
scope: {
treeData: '=',
canAddWorkflowJobTemplate: '=',
addNode: '&',
editNode: '&',
deleteNode: '&'
@ -17,7 +18,12 @@ export default [
restrict: 'E',
link: function(scope, element) {
var margin = {top: 20, right: 20, bottom: 20, left: 20},
scope.$watch('canAddWorkflowJobTemplate', function() {
// Redraw the graph if permissions change
update();
});
let margin = {top: 20, right: 20, bottom: 20, left: 20},
width = 950,
height = 590 - margin.top - margin.bottom,
i = 0,
@ -26,21 +32,21 @@ export default [
rootW = 60,
rootH = 40;
var tree = d3.layout.tree()
let tree = d3.layout.tree()
.size([height, width]);
var line = d3.svg.line()
let line = d3.svg.line()
.x(function(d){return d.x;})
.y(function(d){return d.y;});
function lineData(d){
var sourceX = d.source.isStartNode ? d.source.y + rootW : d.source.y + rectW;
var sourceY = d.source.isStartNode ? d.source.x + 10 + rootH / 2 : d.source.x + rectH / 2;
var targetX = d.target.y;
var targetY = d.target.x + rectH / 2;
let sourceX = d.source.isStartNode ? d.source.y + rootW : d.source.y + rectW;
let sourceY = d.source.isStartNode ? d.source.x + 10 + rootH / 2 : d.source.x + rectH / 2;
let targetX = d.target.y;
let targetY = d.target.x + rectH / 2;
var points = [
let points = [
{
x: sourceX,
y: sourceY
@ -65,23 +71,23 @@ export default [
}
}
var svg = d3.select(element[0]).append("svg")
let svg = d3.select(element[0]).append("svg")
.attr("width", width)
.attr("height", height)
.attr("class", "WorkflowChart-svg")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var node = svg.selectAll(".node"),
let node = svg.selectAll(".node"),
link = svg.selectAll(".link");
function update() {
// Declare the nodes
var nodes = tree.nodes(scope.treeData);
let nodes = tree.nodes(scope.treeData);
node = node.data(nodes, function(d) { d.y = d.depth * 180; return d.id || (d.id = ++i); });
link = link.data(tree.links(nodes), function(d) { return d.source.id + "-" + d.target.id; });
var nodeEnter = node.enter().append("g")
let nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("id", function(d){return "node-" + d.id;})
.attr("parent", function(d){return d.parent ? d.parent.id : null;})
@ -89,7 +95,7 @@ export default [
.attr("fill", "red");
nodeEnter.each(function(d) {
var thisNode = d3.select(this);
let thisNode = d3.select(this);
if(d.isStartNode) {
thisNode.append("rect")
.attr("width", 60)
@ -174,7 +180,7 @@ export default [
.attr("cx", rectW)
.attr("r", 10)
.attr("class", "addCircle nodeCircle")
.style("display", function(d) { return d.placeholder ? "none" : null; })
.style("display", function(d) { return d.placeholder || scope.canAddWorkflowJobTemplate === false ? "none" : null; })
.call(add_node)
.on("mouseover", function(d) {
d3.select("#node-" + d.id)
@ -196,7 +202,7 @@ export default [
.size(60)
.type("cross")
)
.style("display", function(d) { return d.placeholder ? "none" : null; })
.style("display", function(d) { return d.placeholder || scope.canAddWorkflowJobTemplate === false ? "none" : null; })
.call(add_node)
.on("mouseover", function(d) {
d3.select("#node-" + d.id)
@ -216,7 +222,7 @@ export default [
.attr("cy", rectH)
.attr("r", 10)
.attr("class", "removeCircle")
.style("display", function(d) { return (d.canDelete === false || d.placeholder) ? "none" : null; })
.style("display", function(d) { return (d.canDelete === false || d.placeholder || scope.canAddWorkflowJobTemplate === false) ? "none" : null; })
.call(remove_node)
.on("mouseover", function(d) {
d3.select("#node-" + d.id)
@ -238,7 +244,7 @@ export default [
.size(60)
.type("cross")
)
.style("display", function(d) { return (d.canDelete === false || d.placeholder) ? "none" : null; })
.style("display", function(d) { return (d.canDelete === false || d.placeholder || scope.canAddWorkflowJobTemplate === false) ? "none" : null; })
.call(remove_node)
.on("mouseover", function(d) {
d3.select("#node-" + d.id)
@ -257,7 +263,7 @@ export default [
node.exit().remove();
var linkEnter = link.enter().append("g")
let linkEnter = link.enter().append("g")
.attr("class", "nodeConnector")
.attr("id", function(d){return "link-" + d.source.id + "-" + d.target.id;});
@ -294,7 +300,7 @@ export default [
})
.attr("r", 10)
.attr("class", "addCircle linkCircle")
.style("display", function(d) { return (d.source.placeholder || d.target.placeholder) ? "none" : null; })
.style("display", function(d) { return (d.source.placeholder || d.target.placeholder || scope.canAddWorkflowJobTemplate === false) ? "none" : null; })
.call(add_node_between)
.on("mouseover", function(d) {
d3.select("#link-" + d.source.id + "-" + d.target.id)
@ -317,7 +323,7 @@ export default [
.size(60)
.type("cross")
)
.style("display", function(d) { return (d.source.placeholder || d.target.placeholder) ? "none" : null; })
.style("display", function(d) { return (d.source.placeholder || d.target.placeholder || scope.canAddWorkflowJobTemplate === false) ? "none" : null; })
.call(add_node_between)
.on("mouseover", function(d) {
d3.select("#link-" + d.source.id + "-" + d.target.id)
@ -335,19 +341,19 @@ export default [
link.exit().remove();
// Transition nodes and links to their new positions.
var t = svg.transition();
let t = svg.transition();
t.selectAll(".nodeCircle")
.style("display", function(d) { return d.placeholder ? "none" : null; });
.style("display", function(d) { return d.placeholder || scope.canAddWorkflowJobTemplate === false ? "none" : null; });
t.selectAll(".nodeAddCross")
.style("display", function(d) { return d.placeholder ? "none" : null; });
.style("display", function(d) { return d.placeholder || scope.canAddWorkflowJobTemplate === false ? "none" : null; });
t.selectAll(".removeCircle")
.style("display", function(d) { return (d.canDelete === false || d.placeholder) ? "none" : null; });
.style("display", function(d) { return (d.canDelete === false || d.placeholder || scope.canAddWorkflowJobTemplate === false) ? "none" : null; });
t.selectAll(".nodeRemoveCross")
.style("display", function(d) { return (d.canDelete === false || d.placeholder) ? "none" : null; });
.style("display", function(d) { return (d.canDelete === false || d.placeholder || scope.canAddWorkflowJobTemplate === false) ? "none" : null; });
t.selectAll(".link")
.attr("class", function(d) {
@ -412,27 +418,33 @@ export default [
function add_node() {
this.on("click", function(d) {
scope.addNode({
parent: d,
betweenTwoNodes: false
});
if(scope.canAddWorkflowJobTemplate !== false) {
scope.addNode({
parent: d,
betweenTwoNodes: false
});
}
});
}
function add_node_between() {
this.on("click", function(d) {
scope.addNode({
parent: d,
betweenTwoNodes: true
});
if(scope.canAddWorkflowJobTemplate !== false) {
scope.addNode({
parent: d,
betweenTwoNodes: true
});
}
});
}
function remove_node() {
this.on("click", function(d) {
scope.deleteNode({
nodeToDelete: d
});
if(scope.canAddWorkflowJobTemplate !== false) {
scope.deleteNode({
nodeToDelete: d
});
}
});
}

View File

@ -7,11 +7,11 @@
export default ['$scope', 'WorkflowHelpService', 'generateList', 'JobTemplateList', 'ProjectList',
'GetBasePath', 'Wait', 'JobTemplateService', '$state',
'ProcessErrors', 'InventorySourcesList', 'CreateSelect2', 'WorkflowMakerForm',
'GenerateForm', 'InventoryList', 'CredentialList', '$q', '$timeout',
'GenerateForm', 'InventoryList', 'CredentialList', '$q',
function($scope, WorkflowHelpService, GenerateList, JobTemplateList, ProjectList,
GetBasePath, Wait, JobTemplateService, $state,
ProcessErrors, InventorySourcesList, CreateSelect2, WorkflowMakerForm,
GenerateForm, InventoryList, CredentialList, $q, $timeout) {
GenerateForm, InventoryList, CredentialList, $q) {
let form = WorkflowMakerForm();
@ -274,13 +274,6 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'JobTemplateLis
};
}
// The default needs to be in place before we can select2-ify the dropdown
$timeout(function() {
CreateSelect2({
element: '#workflow_maker_job_type',
multiple: false
});
});
}
if ($scope.nodeBeingEdited.unifiedJobTemplate.ask_limit_on_launch) {

View File

@ -10,7 +10,8 @@ export default ['templateUrl', 'CreateDialog', 'Wait',
function(templateUrl, CreateDialog, Wait) {
return {
scope: {
treeData: '='
treeData: '=',
canAddWorkflowJobTemplate: '='
},
restrict: 'E',
templateUrl: templateUrl('job-templates/workflow-maker/workflow-maker'),

View File

@ -60,7 +60,7 @@
<span class="badge List-titleBadge" ng-bind="treeData.data.totalNodes"></span>
</div>
</div>
<workflow-chart tree-data="treeData.data" add-node="startAddNode(parent, betweenTwoNodes)" edit-node="startEditNode(nodeToEdit)" delete-node="startDeleteNode(nodeToDelete)" class="WorkflowMaker-chart"></workflow-chart>
<workflow-chart tree-data="treeData.data" add-node="startAddNode(parent, betweenTwoNodes)" edit-node="startEditNode(nodeToEdit)" delete-node="startDeleteNode(nodeToDelete)" can-add-workflow-job-template="canAddWorkflowJobTemplate" class="WorkflowMaker-chart"></workflow-chart>
</div>
<div class="WorkflowMaker-contentRight">
<div class="WorkflowMaker-formTitle">{{(workflowMakerFormConfig.nodeMode === 'edit' && nodeBeingEdited && nodeBeingEdited.unifiedJobTemplate && nodeBeingEdited.unifiedJobTemplate.name) ? nodeBeingEdited.unifiedJobTemplate.name : "ADD A TEMPLATE"}}</div>
@ -82,6 +82,6 @@
</div>
<div class="WorkflowMaker-buttonHolder">
<button type="button" class="btn btn-sm WorkflowMaker-cancelButton" ng-click="closeWorkflowMaker()"> Close</button>
<button type="button" class="btn btn-sm WorkflowMaker-saveButton" ng-click="saveWorkflowMaker()"> Save</button>
<button type="button" class="btn btn-sm WorkflowMaker-saveButton" ng-click="saveWorkflowMaker()" ng-show="workflow_job_template_obj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate"> Save</button>
</div>
</div>

View File

@ -64,14 +64,16 @@ export default
options: [
{
optionContent: 'Job Template',
optionSref: 'templates.addJobTemplate'
optionSref: 'templates.addJobTemplate',
ngShow: 'canAddJobTemplate'
},
{
optionContent: 'Workflow Job Template',
optionSref: 'templates.addWorkflowJobTemplate'
optionSref: 'templates.addWorkflowJobTemplate',
ngShow: 'canAddWorkflowJobTemplate'
}
],
ngShow: 'canAdd'
ngShow: 'canAddJobTemplate || canAddWorkflowJobTemplate'
}
},

View File

@ -10,7 +10,7 @@
</button>
<ul class="dropdown-menu pull-right">
<li ng-repeat="option in options.options">
<a ui-sref="{{option.optionSref}}" ng-bind-html="option.optionContent"></a>
<a ui-sref="{{option.optionSref}}" ng-bind-html="option.optionContent" ng-show="{{option.ngShow}}"></a>
</li>
</ul>
</div>
@ -37,7 +37,7 @@
</button>
<ul class="dropdown-menu pull-right">
<li ng-repeat="option in options.options">
<a ui-sref="{{option.optionSref}}" ng-bind-html="option.optionContent"></a>
<a ui-sref="{{option.optionSref}}" ng-bind-html="option.optionContent" ng-show="{{option.ngShow}}"></a>
</li>
</ul>
</div>