mirror of
https://github.com/ansible/awx.git
synced 2026-01-13 02:50:02 -03:30
Cleanup and changes to the way approval templates are created
This commit is contained in:
parent
294d6551b9
commit
4a801c60b9
@ -110,9 +110,12 @@ function TemplatesStrings (BaseString) {
|
||||
ON_SUCCESS: t.s('On Success'),
|
||||
ON_FAILURE: t.s('On Failure'),
|
||||
ALWAYS: t.s('Always'),
|
||||
PAUSE: t.s('Wait For Approval'),
|
||||
JOB_TEMPLATE: t.s('Job Template'),
|
||||
PROJECT_SYNC: t.s('Project Sync'),
|
||||
INVENTORY_SYNC: t.s('Inventory Sync'),
|
||||
WORKFLOW: t.s('Workflow'),
|
||||
TEMPLATE: t.s('Template'),
|
||||
WARNING: t.s('Warning'),
|
||||
TOTAL_NODES: t.s('TOTAL NODES'),
|
||||
ADD_A_NODE: t.s('ADD A NODE'),
|
||||
@ -145,7 +148,7 @@ function TemplatesStrings (BaseString) {
|
||||
EXIT: t.s('EXIT'),
|
||||
CANCEL: t.s('CANCEL'),
|
||||
SAVE_AND_EXIT: t.s('SAVE & EXIT'),
|
||||
PAUSE_NODE: t.s('Pause Node')
|
||||
APPROVAL: t.s('Approval')
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ import workflowEdit from './workflows/edit-workflow/main';
|
||||
import labels from './labels/main';
|
||||
import prompt from './prompt/main';
|
||||
import workflowChart from './workflows/workflow-chart/main';
|
||||
import workflowKey from './workflows/workflow-key/main';
|
||||
import workflowMaker from './workflows/workflow-maker/main';
|
||||
import workflowControls from './workflows/workflow-controls/main';
|
||||
import WorkflowForm from './workflows.form';
|
||||
@ -31,7 +32,7 @@ import {
|
||||
|
||||
export default
|
||||
angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, prompt.name, workflowAdd.name, workflowEdit.name,
|
||||
workflowChart.name, workflowMaker.name, workflowControls.name
|
||||
workflowChart.name, workflowKey.name, workflowMaker.name, workflowControls.name
|
||||
])
|
||||
.service('TemplatesService', templatesService)
|
||||
.factory('WorkflowForm', WorkflowForm)
|
||||
@ -499,320 +500,7 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
|
||||
views: {
|
||||
'modal': {
|
||||
template: `<workflow-maker ng-if="includeWorkflowMaker" workflow-job-template-obj="workflow_job_template_obj" can-add-or-edit="canAddOrEdit"></workflow-maker>`
|
||||
},
|
||||
'jobTemplateList@templates.editWorkflowJobTemplate.workflowMaker': {
|
||||
templateProvider: function(WorkflowMakerJobTemplateList, generateList) {
|
||||
|
||||
let html = generateList.build({
|
||||
list: WorkflowMakerJobTemplateList,
|
||||
input_type: 'radio',
|
||||
mode: 'lookup'
|
||||
});
|
||||
return html;
|
||||
},
|
||||
// $scope encapsulated in this controller will be a initialized as child of 'modal' $scope, because of element hierarchy
|
||||
controller: ['$scope', 'WorkflowMakerJobTemplateList', 'JobTemplateDataset',
|
||||
function($scope, list, Dataset) {
|
||||
|
||||
init();
|
||||
|
||||
function init() {
|
||||
$scope.list = list;
|
||||
$scope[`${list.iterator}_dataset`] = Dataset.data;
|
||||
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
||||
|
||||
$scope.$watch('wf_maker_templates', function(){
|
||||
if($scope.selectedTemplate){
|
||||
$scope.wf_maker_templates.forEach(function(row, i) {
|
||||
if(row.id === $scope.selectedTemplate.id) {
|
||||
$scope.wf_maker_templates[i].checked = 1;
|
||||
}
|
||||
else {
|
||||
$scope.wf_maker_templates[i].checked = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.toggle_row = function(selectedRow) {
|
||||
if ($scope.workflowJobTemplateObj.summary_fields.user_capabilities.edit) {
|
||||
$scope.wf_maker_templates.forEach(function(row, i) {
|
||||
if (row.id === selectedRow.id) {
|
||||
$scope.wf_maker_templates[i].checked = 1;
|
||||
$scope.selection[list.iterator] = {
|
||||
id: row.id,
|
||||
name: row.name
|
||||
};
|
||||
|
||||
$scope.templateManuallySelected(row);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$watch('selectedTemplate', () => {
|
||||
$scope.wf_maker_templates.forEach(function(row, i) {
|
||||
if(_.has($scope, 'selectedTemplate.id') && row.id === $scope.selectedTemplate.id) {
|
||||
$scope.wf_maker_templates[i].checked = 1;
|
||||
}
|
||||
else {
|
||||
$scope.wf_maker_templates[i].checked = 0;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$scope.$watch('activeTab', () => {
|
||||
if(!$scope.activeTab || $scope.activeTab !== "jobs") {
|
||||
$scope.wf_maker_templates.forEach(function(row, i) {
|
||||
$scope.wf_maker_templates[i].checked = 0;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on('clearWorkflowLists', function() {
|
||||
$scope.wf_maker_templates.forEach(function(row, i) {
|
||||
$scope.wf_maker_templates[i].checked = 0;
|
||||
});
|
||||
});
|
||||
}
|
||||
]
|
||||
},
|
||||
'inventorySyncList@templates.editWorkflowJobTemplate.workflowMaker': {
|
||||
templateProvider: function(WorkflowInventorySourcesList, generateList) {
|
||||
let html = generateList.build({
|
||||
list: WorkflowInventorySourcesList,
|
||||
input_type: 'radio',
|
||||
mode: 'lookup'
|
||||
});
|
||||
return html;
|
||||
},
|
||||
// encapsulated $scope in this controller will be a initialized as child of 'modal' $scope, because of element hierarchy
|
||||
controller: ['$scope', 'WorkflowInventorySourcesList', 'InventorySourcesDataset',
|
||||
function($scope, list, Dataset) {
|
||||
|
||||
init();
|
||||
|
||||
function init() {
|
||||
$scope.list = list;
|
||||
$scope[`${list.iterator}_dataset`] = Dataset.data;
|
||||
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
||||
|
||||
$scope.$watch('wf_maker_inventory_sources', function(){
|
||||
if($scope.selectedTemplate){
|
||||
$scope.wf_maker_inventory_sources.forEach(function(row, i) {
|
||||
if(row.id === $scope.selectedTemplate.id) {
|
||||
$scope.wf_maker_inventory_sources[i].checked = 1;
|
||||
}
|
||||
else {
|
||||
$scope.wf_maker_inventory_sources[i].checked = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.toggle_row = function(selectedRow) {
|
||||
if ($scope.workflowJobTemplateObj.summary_fields.user_capabilities.edit) {
|
||||
$scope.wf_maker_inventory_sources.forEach(function(row, i) {
|
||||
if (row.id === selectedRow.id) {
|
||||
$scope.wf_maker_inventory_sources[i].checked = 1;
|
||||
$scope.selection[list.iterator] = {
|
||||
id: row.id,
|
||||
name: row.name
|
||||
};
|
||||
|
||||
$scope.templateManuallySelected(row);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$watch('selectedTemplate', () => {
|
||||
$scope.wf_maker_inventory_sources.forEach(function(row, i) {
|
||||
if(_.hasIn($scope, 'selectedTemplate.id') && row.id === $scope.selectedTemplate.id) {
|
||||
$scope.wf_maker_inventory_sources[i].checked = 1;
|
||||
}
|
||||
else {
|
||||
$scope.wf_maker_inventory_sources[i].checked = 0;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$scope.$watch('activeTab', () => {
|
||||
if(!$scope.activeTab || $scope.activeTab !== "inventory_sync") {
|
||||
$scope.wf_maker_inventory_sources.forEach(function(row, i) {
|
||||
$scope.wf_maker_inventory_sources[i].checked = 0;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on('clearWorkflowLists', function() {
|
||||
$scope.wf_maker_inventory_sources.forEach(function(row, i) {
|
||||
$scope.wf_maker_inventory_sources[i].checked = 0;
|
||||
});
|
||||
});
|
||||
}
|
||||
]
|
||||
},
|
||||
'projectSyncList@templates.editWorkflowJobTemplate.workflowMaker': {
|
||||
templateProvider: function(WorkflowProjectList, generateList) {
|
||||
let html = generateList.build({
|
||||
list: WorkflowProjectList,
|
||||
input_type: 'radio',
|
||||
mode: 'lookup'
|
||||
});
|
||||
return html;
|
||||
},
|
||||
// encapsulated $scope in this controller will be a initialized as child of 'modal' $scope, because of element hierarchy
|
||||
controller: ['$scope', 'WorkflowProjectList', 'ProjectDataset',
|
||||
function($scope, list, Dataset) {
|
||||
|
||||
init();
|
||||
|
||||
function init() {
|
||||
$scope.list = list;
|
||||
$scope[`${list.iterator}_dataset`] = Dataset.data;
|
||||
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
||||
|
||||
$scope.$watch('wf_maker_projects', function(){
|
||||
if($scope.selectedTemplate){
|
||||
$scope.wf_maker_projects.forEach(function(row, i) {
|
||||
if(row.id === $scope.selectedTemplate.id) {
|
||||
$scope.wf_maker_projects[i].checked = 1;
|
||||
}
|
||||
else {
|
||||
$scope.wf_maker_projects[i].checked = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.toggle_row = function(selectedRow) {
|
||||
if ($scope.workflowJobTemplateObj.summary_fields.user_capabilities.edit) {
|
||||
$scope.wf_maker_projects.forEach(function(row, i) {
|
||||
if (row.id === selectedRow.id) {
|
||||
$scope.wf_maker_projects[i].checked = 1;
|
||||
$scope.selection[list.iterator] = {
|
||||
id: row.id,
|
||||
name: row.name
|
||||
};
|
||||
|
||||
$scope.templateManuallySelected(row);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$watch('selectedTemplate', () => {
|
||||
$scope.wf_maker_projects.forEach(function(row, i) {
|
||||
if(_.hasIn($scope, 'selectedTemplate.id') && row.id === $scope.selectedTemplate.id) {
|
||||
$scope.wf_maker_projects[i].checked = 1;
|
||||
}
|
||||
else {
|
||||
$scope.wf_maker_projects[i].checked = 0;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$scope.$watch('activeTab', () => {
|
||||
if(!$scope.activeTab || $scope.activeTab !== "project_sync") {
|
||||
$scope.wf_maker_projects.forEach(function(row, i) {
|
||||
$scope.wf_maker_projects[i].checked = 0;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on('clearWorkflowLists', function() {
|
||||
$scope.wf_maker_projects.forEach(function(row, i) {
|
||||
$scope.wf_maker_projects[i].checked = 0;
|
||||
});
|
||||
});
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
JobTemplateDataset: ['WorkflowMakerJobTemplateList', 'QuerySet', '$stateParams', 'GetBasePath',
|
||||
(list, qs, $stateParams, GetBasePath) => {
|
||||
let path = GetBasePath(list.basePath);
|
||||
return qs.search(path, $stateParams[`${list.iterator}_search`]);
|
||||
}
|
||||
],
|
||||
ProjectDataset: ['WorkflowProjectList', 'QuerySet', '$stateParams', 'GetBasePath',
|
||||
(list, qs, $stateParams, GetBasePath) => {
|
||||
let path = GetBasePath(list.basePath);
|
||||
return qs.search(path, $stateParams[`${list.iterator}_search`]);
|
||||
}
|
||||
],
|
||||
InventorySourcesDataset: ['InventorySourcesList', 'QuerySet', '$stateParams', 'GetBasePath',
|
||||
(list, qs, $stateParams, GetBasePath) => {
|
||||
let path = GetBasePath(list.basePath);
|
||||
return qs.search(path, $stateParams[`${list.iterator}_search`]);
|
||||
}
|
||||
],
|
||||
WorkflowMakerJobTemplateList: ['TemplateList', 'i18n',
|
||||
(TemplateList, i18n) => {
|
||||
let list = _.cloneDeep(TemplateList);
|
||||
delete list.actions;
|
||||
delete list.fields.type;
|
||||
delete list.fields.description;
|
||||
delete list.fields.smart_status;
|
||||
delete list.fields.labels;
|
||||
delete list.fieldActions;
|
||||
list.name = 'wf_maker_templates';
|
||||
list.iterator = 'wf_maker_template';
|
||||
list.fields.name.columnClass = "col-md-8";
|
||||
list.fields.name.tag = i18n._('WORKFLOW');
|
||||
list.fields.name.showTag = "{{wf_maker_template.type === 'workflow_job_template'}}";
|
||||
list.disableRow = "{{ !workflowJobTemplateObj.summary_fields.user_capabilities.edit }}";
|
||||
list.disableRowValue = '!workflowJobTemplateObj.summary_fields.user_capabilities.edit';
|
||||
list.basePath = 'unified_job_templates';
|
||||
list.fields.info = {
|
||||
ngInclude: "'/static/partials/job-template-details.html'",
|
||||
type: 'template',
|
||||
columnClass: 'col-md-3',
|
||||
infoHeaderClass: 'col-md-3',
|
||||
label: '',
|
||||
nosort: true
|
||||
};
|
||||
list.maxVisiblePages = 5;
|
||||
list.searchBarFullWidth = true;
|
||||
|
||||
return list;
|
||||
}
|
||||
],
|
||||
WorkflowProjectList: ['ProjectList',
|
||||
(ProjectList) => {
|
||||
let list = _.cloneDeep(ProjectList);
|
||||
delete list.fields.status;
|
||||
delete list.fields.scm_type;
|
||||
delete list.fields.last_updated;
|
||||
list.name = 'wf_maker_projects';
|
||||
list.iterator = 'wf_maker_project';
|
||||
list.fields.name.columnClass = "col-md-11";
|
||||
list.maxVisiblePages = 5;
|
||||
list.searchBarFullWidth = true;
|
||||
list.disableRow = "{{ !workflowJobTemplateObj.summary_fields.user_capabilities.edit }}";
|
||||
list.disableRowValue = '!workflowJobTemplateObj.summary_fields.user_capabilities.edit';
|
||||
|
||||
return list;
|
||||
}
|
||||
],
|
||||
WorkflowInventorySourcesList: ['InventorySourcesList',
|
||||
(InventorySourcesList) => {
|
||||
let list = _.cloneDeep(InventorySourcesList);
|
||||
list.name = 'wf_maker_inventory_sources';
|
||||
list.iterator = 'wf_maker_inventory_source';
|
||||
list.maxVisiblePages = 5;
|
||||
list.searchBarFullWidth = true;
|
||||
list.disableRow = "{{ !workflowJobTemplateObj.summary_fields.user_capabilities.edit }}";
|
||||
list.disableRowValue = '!workflowJobTemplateObj.summary_fields.user_capabilities.edit';
|
||||
|
||||
return list;
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -291,13 +291,13 @@ export default ['Rest', 'GetBasePath', '$q', 'NextPage', function(Rest, GetBaseP
|
||||
Rest.setUrl(url);
|
||||
return Rest.post(params.data);
|
||||
},
|
||||
createApprovalTemplate: (params) => {
|
||||
params = params || {};
|
||||
Rest.setUrl(GetBasePath('workflow_approval_templates'));
|
||||
return Rest.post(params);
|
||||
createApprovalTemplate: ({url, data}) => {
|
||||
data = data || {};
|
||||
Rest.setUrl(url);
|
||||
return Rest.post(data);
|
||||
},
|
||||
patchApprovalTemplate: ({id, data}) => {
|
||||
Rest.setUrl(`${GetBasePath('workflow_approval_templates')}/${id}`);
|
||||
Rest.setUrl(`/api/v2/workflow_approval_templates/${id}`);
|
||||
return Rest.patch(data);
|
||||
}
|
||||
};
|
||||
|
||||
@ -117,6 +117,7 @@
|
||||
|
||||
.WorkflowChart-nodeTypeLetter {
|
||||
fill: @default-bg;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.WorkflowChart-nodeStatus--running {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
11
awx/ui/client/src/templates/workflows/workflow-key/main.js
Normal file
11
awx/ui/client/src/templates/workflows/workflow-key/main.js
Normal file
@ -0,0 +1,11 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2019 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import workflowKey from './workflow-key.directive';
|
||||
|
||||
export default
|
||||
angular.module('workflowKey', [])
|
||||
.directive('workflowKey', workflowKey);
|
||||
@ -0,0 +1,18 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2016 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
export default ['templateUrl', 'TemplatesStrings',
|
||||
function(templateUrl, TemplatesStrings) {
|
||||
return {
|
||||
scope: {},
|
||||
templateUrl: templateUrl('templates/workflows/workflow-key/workflow-key'),
|
||||
restrict: 'E',
|
||||
link: function(scope) {
|
||||
scope.strings = TemplatesStrings;
|
||||
}
|
||||
};
|
||||
}
|
||||
];
|
||||
@ -0,0 +1,43 @@
|
||||
<ul class="Key-list noselect">
|
||||
<li class="Key-listItem">
|
||||
<p class="Key-heading">{{:: strings.get('workflow_maker.KEY')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--success"></div>
|
||||
<p class="Key-listItemContent">{{:: strings.get('workflow_maker.ON_SUCCESS')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--fail"></div>
|
||||
<p class="Key-listItemContent">{{:: strings.get('workflow_maker.ON_FAILURE')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--always"></div>
|
||||
<p class="Key-listItemContent">{{:: strings.get('workflow_maker.ALWAYS')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--default">JT</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{:: strings.get('workflow_maker.JOB_TEMPLATE')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--default">P</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{:: strings.get('workflow_maker.PROJECT_SYNC')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--default">I</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{:: strings.get('workflow_maker.INVENTORY_SYNC')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--default">W</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{:: strings.get('workflow_maker.WORKFLOW')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--default">
|
||||
<span class="fa fa-pause"></span>
|
||||
</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{:: strings.get('workflow_maker.PAUSE')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--warning">!</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{:: strings.get('workflow_maker.WARNING')}}</p>
|
||||
</li>
|
||||
</ul>
|
||||
@ -1,7 +1,9 @@
|
||||
import workflowLinkForm from './workflow-link-form.directive';
|
||||
import workflowNodeForm from './workflow-node-form.directive';
|
||||
import workflowNodeFormService from './workflow-node-form.service';
|
||||
|
||||
export default
|
||||
angular.module('templates.workflowMaker.forms', [])
|
||||
.directive('workflowLinkForm', workflowLinkForm)
|
||||
.directive('workflowNodeForm', workflowNodeForm);
|
||||
.directive('workflowNodeForm', workflowNodeForm)
|
||||
.service('WorkflowNodeFormService', workflowNodeFormService);
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
export default ['TemplateList', 'ProjectList', 'InventorySourcesList', 'i18n',
|
||||
function(TemplateList, ProjectList, InventorySourcesList, i18n){
|
||||
return {
|
||||
inventorySourceListDefinition: function() {
|
||||
const inventorySourceList = _.cloneDeep(InventorySourcesList);
|
||||
inventorySourceList.name = 'wf_maker_inventory_sources';
|
||||
inventorySourceList.iterator = 'wf_maker_inventory_source';
|
||||
inventorySourceList.maxVisiblePages = 5;
|
||||
inventorySourceList.searchBarFullWidth = true;
|
||||
inventorySourceList.disableRow = "{{ readOnly }}";
|
||||
inventorySourceList.disableRowValue = 'readOnly';
|
||||
|
||||
return inventorySourceList;
|
||||
},
|
||||
projectListDefinition: function(){
|
||||
const projectList = _.cloneDeep(ProjectList);
|
||||
delete projectList.fields.status;
|
||||
delete projectList.fields.scm_type;
|
||||
delete projectList.fields.last_updated;
|
||||
projectList.name = 'wf_maker_projects';
|
||||
projectList.iterator = 'wf_maker_project';
|
||||
projectList.fields.name.columnClass = "col-md-11";
|
||||
projectList.maxVisiblePages = 5;
|
||||
projectList.searchBarFullWidth = true;
|
||||
projectList.disableRow = "{{ readOnly }}";
|
||||
projectList.disableRowValue = 'readOnly';
|
||||
|
||||
return projectList;
|
||||
},
|
||||
templateListDefinition: function(){
|
||||
const templateList = _.cloneDeep(TemplateList);
|
||||
delete templateList.actions;
|
||||
delete templateList.fields.type;
|
||||
delete templateList.fields.description;
|
||||
delete templateList.fields.smart_status;
|
||||
delete templateList.fields.labels;
|
||||
delete templateList.fieldActions;
|
||||
templateList.name = 'wf_maker_templates';
|
||||
templateList.iterator = 'wf_maker_template';
|
||||
templateList.fields.name.columnClass = "col-md-8";
|
||||
templateList.fields.name.tag = i18n._('WORKFLOW');
|
||||
templateList.fields.name.showTag = "{{wf_maker_template.type === 'workflow_job_template'}}";
|
||||
templateList.disableRow = "{{ readOnly }}";
|
||||
templateList.disableRowValue = 'readOnly';
|
||||
templateList.basePath = 'unified_job_templates';
|
||||
templateList.fields.info = {
|
||||
ngInclude: "'/static/partials/job-template-details.html'",
|
||||
type: 'template',
|
||||
columnClass: 'col-md-3',
|
||||
infoHeaderClass: 'col-md-3',
|
||||
label: '',
|
||||
nosort: true
|
||||
};
|
||||
templateList.maxVisiblePages = 5;
|
||||
templateList.searchBarFullWidth = true;
|
||||
|
||||
return templateList;
|
||||
}
|
||||
};
|
||||
}
|
||||
];
|
||||
@ -7,6 +7,15 @@
|
||||
.ui-dialog-buttonpane, .ui-dialog-titlebar {
|
||||
display:none;
|
||||
}
|
||||
|
||||
input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
}
|
||||
|
||||
.WorkflowMaker-header {
|
||||
@ -380,11 +389,11 @@
|
||||
|
||||
.Key-icon--circle {
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
color: @default-bg;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
line-height: 24px;
|
||||
margin: 4px 5px 5px 0px;
|
||||
}
|
||||
|
||||
|
||||
@ -145,21 +145,24 @@ export default ['$scope', 'TemplatesService',
|
||||
let editPromises = [];
|
||||
let credentialRequests = [];
|
||||
|
||||
// TODO: clean up data generation of approval template requests
|
||||
Object.keys(nodeRef).map((workflowMakerNodeId) => {
|
||||
const node = nodeRef[workflowMakerNodeId];
|
||||
if (node.isNew) {
|
||||
if (node.unifiedJobTemplate && node.unifiedJobTemplate.unified_job_type === "workflow_approval") {
|
||||
approvalTemplatePromises.push(TemplatesService.createApprovalTemplate({
|
||||
name: node.unifiedJobTemplate.name
|
||||
}).then(({data: approvalTemplateData}) => {
|
||||
addPromises.push(TemplatesService.addWorkflowNode({
|
||||
url: $scope.workflowJobTemplateObj.related.workflow_nodes,
|
||||
addPromises.push(TemplatesService.addWorkflowNode({
|
||||
url: $scope.workflowJobTemplateObj.related.workflow_nodes,
|
||||
data: {}
|
||||
}).then(({data}) => {
|
||||
approvalTemplatePromises.push(TemplatesService.createApprovalTemplate({
|
||||
url: data.related.create_approval_template,
|
||||
data: {
|
||||
unified_job_template: approvalTemplateData.id
|
||||
name: node.unifiedJobTemplate.name,
|
||||
description: node.unifiedJobTemplate.description
|
||||
}
|
||||
}).then(({data: nodeData}) => {
|
||||
node.originalNodeObject = nodeData;
|
||||
nodeIdToChartNodeIdMapping[nodeData.id] = parseInt(workflowMakerNodeId);
|
||||
}).then(() => {
|
||||
node.originalNodeObject = data;
|
||||
nodeIdToChartNodeIdMapping[data.id] = parseInt(workflowMakerNodeId);
|
||||
}).catch(({ data, status }) => {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
@ -222,20 +225,11 @@ export default ['$scope', 'TemplatesService',
|
||||
}));
|
||||
} else {
|
||||
approvalTemplatePromises.push(TemplatesService.createApprovalTemplate({
|
||||
name: node.unifiedJobTemplate.name
|
||||
}).then(({data: approvalTemplateData}) => {
|
||||
// Make sure that this isn't overwriting everything on the node...
|
||||
editPromises.push(TemplatesService.editWorkflowNode({
|
||||
id: node.originalNodeObject.id,
|
||||
data: {
|
||||
unified_job_template: approvalTemplateData.id
|
||||
}
|
||||
}).catch(({ data, status }) => {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
hdr: $scope.strings.get('error.HEADER')
|
||||
});
|
||||
}));
|
||||
url: node.originalNodeObject.related.create_approval_template,
|
||||
data: {
|
||||
name: node.unifiedJobTemplate.name,
|
||||
description: node.unifiedJobTemplate.description
|
||||
}
|
||||
}).catch(({ data, status }) => {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
@ -302,176 +296,173 @@ export default ['$scope', 'TemplatesService',
|
||||
return TemplatesService.deleteWorkflowJobTemplateNode(nodeId);
|
||||
});
|
||||
|
||||
$q.all(approvalTemplatePromises)
|
||||
$q.all(addPromises.concat(editPromises, deletePromises))
|
||||
.then(() => {
|
||||
$q.all(addPromises.concat(editPromises, deletePromises))
|
||||
.then(() => {
|
||||
let disassociatePromises = [];
|
||||
let associatePromises = [];
|
||||
let linkMap = {};
|
||||
$q.all(approvalTemplatePromises)
|
||||
.then(() => {
|
||||
let disassociatePromises = [];
|
||||
let associatePromises = [];
|
||||
let linkMap = {};
|
||||
|
||||
// Build a link map for easy access
|
||||
$scope.graphState.arrayOfLinksForChart.forEach(link => {
|
||||
// link.source.id of 1 is our artificial start node
|
||||
if (link.source.id !== 1) {
|
||||
const sourceNodeId = nodeRef[link.source.id].originalNodeObject.id;
|
||||
const targetNodeId = nodeRef[link.target.id].originalNodeObject.id;
|
||||
if (!linkMap[sourceNodeId]) {
|
||||
linkMap[sourceNodeId] = {};
|
||||
// Build a link map for easy access
|
||||
$scope.graphState.arrayOfLinksForChart.forEach(link => {
|
||||
// link.source.id of 1 is our artificial start node
|
||||
if (link.source.id !== 1) {
|
||||
const sourceNodeId = nodeRef[link.source.id].originalNodeObject.id;
|
||||
const targetNodeId = nodeRef[link.target.id].originalNodeObject.id;
|
||||
if (!linkMap[sourceNodeId]) {
|
||||
linkMap[sourceNodeId] = {};
|
||||
}
|
||||
|
||||
linkMap[sourceNodeId][targetNodeId] = link.edgeType;
|
||||
}
|
||||
});
|
||||
|
||||
linkMap[sourceNodeId][targetNodeId] = link.edgeType;
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(nodeRef).map((workflowNodeId) => {
|
||||
let nodeId = nodeRef[workflowNodeId].originalNodeObject.id;
|
||||
if (nodeRef[workflowNodeId].originalNodeObject.success_nodes) {
|
||||
nodeRef[workflowNodeId].originalNodeObject.success_nodes.forEach((successNodeId) => {
|
||||
if (
|
||||
!deletedNodeIds.includes(successNodeId) &&
|
||||
(!linkMap[nodeId] ||
|
||||
!linkMap[nodeId][successNodeId] ||
|
||||
linkMap[nodeId][successNodeId] !== "success")
|
||||
) {
|
||||
disassociatePromises.push(
|
||||
TemplatesService.disassociateWorkflowNode({
|
||||
parentId: nodeId,
|
||||
nodeId: successNodeId,
|
||||
edge: "success"
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (nodeRef[workflowNodeId].originalNodeObject.failure_nodes) {
|
||||
nodeRef[workflowNodeId].originalNodeObject.failure_nodes.forEach((failureNodeId) => {
|
||||
if (
|
||||
!deletedNodeIds.includes(failureNodeId) &&
|
||||
(!linkMap[nodeId] ||
|
||||
!linkMap[nodeId][failureNodeId] ||
|
||||
linkMap[nodeId][failureNodeId] !== "failure")
|
||||
) {
|
||||
disassociatePromises.push(
|
||||
TemplatesService.disassociateWorkflowNode({
|
||||
parentId: nodeId,
|
||||
nodeId: failureNodeId,
|
||||
edge: "failure"
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (nodeRef[workflowNodeId].originalNodeObject.always_nodes) {
|
||||
nodeRef[workflowNodeId].originalNodeObject.always_nodes.forEach((alwaysNodeId) => {
|
||||
if (
|
||||
!deletedNodeIds.includes(alwaysNodeId) &&
|
||||
(!linkMap[nodeId] ||
|
||||
!linkMap[nodeId][alwaysNodeId] ||
|
||||
linkMap[nodeId][alwaysNodeId] !== "always")
|
||||
) {
|
||||
disassociatePromises.push(
|
||||
TemplatesService.disassociateWorkflowNode({
|
||||
parentId: nodeId,
|
||||
nodeId: alwaysNodeId,
|
||||
edge: "always"
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(linkMap).map((sourceNodeId) => {
|
||||
Object.keys(linkMap[sourceNodeId]).map((targetNodeId) => {
|
||||
const sourceChartNodeId = nodeIdToChartNodeIdMapping[sourceNodeId];
|
||||
const targetChartNodeId = nodeIdToChartNodeIdMapping[targetNodeId];
|
||||
switch(linkMap[sourceNodeId][targetNodeId]) {
|
||||
case "success":
|
||||
Object.keys(nodeRef).map((workflowNodeId) => {
|
||||
let nodeId = nodeRef[workflowNodeId].originalNodeObject.id;
|
||||
if (nodeRef[workflowNodeId].originalNodeObject.success_nodes) {
|
||||
nodeRef[workflowNodeId].originalNodeObject.success_nodes.forEach((successNodeId) => {
|
||||
if (
|
||||
!nodeRef[sourceChartNodeId].originalNodeObject.success_nodes ||
|
||||
!nodeRef[sourceChartNodeId].originalNodeObject.success_nodes.includes(nodeRef[targetChartNodeId].originalNodeObject.id)
|
||||
!deletedNodeIds.includes(successNodeId) &&
|
||||
(!linkMap[nodeId] ||
|
||||
!linkMap[nodeId][successNodeId] ||
|
||||
linkMap[nodeId][successNodeId] !== "success")
|
||||
) {
|
||||
associatePromises.push(
|
||||
TemplatesService.associateWorkflowNode({
|
||||
parentId: parseInt(sourceNodeId),
|
||||
nodeId: parseInt(targetNodeId),
|
||||
disassociatePromises.push(
|
||||
TemplatesService.disassociateWorkflowNode({
|
||||
parentId: nodeId,
|
||||
nodeId: successNodeId,
|
||||
edge: "success"
|
||||
})
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "failure":
|
||||
});
|
||||
}
|
||||
if (nodeRef[workflowNodeId].originalNodeObject.failure_nodes) {
|
||||
nodeRef[workflowNodeId].originalNodeObject.failure_nodes.forEach((failureNodeId) => {
|
||||
if (
|
||||
!nodeRef[sourceChartNodeId].originalNodeObject.failure_nodes ||
|
||||
!nodeRef[sourceChartNodeId].originalNodeObject.failure_nodes.includes(nodeRef[targetChartNodeId].originalNodeObject.id)
|
||||
!deletedNodeIds.includes(failureNodeId) &&
|
||||
(!linkMap[nodeId] ||
|
||||
!linkMap[nodeId][failureNodeId] ||
|
||||
linkMap[nodeId][failureNodeId] !== "failure")
|
||||
) {
|
||||
associatePromises.push(
|
||||
TemplatesService.associateWorkflowNode({
|
||||
parentId: parseInt(sourceNodeId),
|
||||
nodeId: parseInt(targetNodeId),
|
||||
disassociatePromises.push(
|
||||
TemplatesService.disassociateWorkflowNode({
|
||||
parentId: nodeId,
|
||||
nodeId: failureNodeId,
|
||||
edge: "failure"
|
||||
})
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "always":
|
||||
});
|
||||
}
|
||||
if (nodeRef[workflowNodeId].originalNodeObject.always_nodes) {
|
||||
nodeRef[workflowNodeId].originalNodeObject.always_nodes.forEach((alwaysNodeId) => {
|
||||
if (
|
||||
!nodeRef[sourceChartNodeId].originalNodeObject.always_nodes ||
|
||||
!nodeRef[sourceChartNodeId].originalNodeObject.always_nodes.includes(nodeRef[targetChartNodeId].originalNodeObject.id)
|
||||
!deletedNodeIds.includes(alwaysNodeId) &&
|
||||
(!linkMap[nodeId] ||
|
||||
!linkMap[nodeId][alwaysNodeId] ||
|
||||
linkMap[nodeId][alwaysNodeId] !== "always")
|
||||
) {
|
||||
associatePromises.push(
|
||||
TemplatesService.associateWorkflowNode({
|
||||
parentId: parseInt(sourceNodeId),
|
||||
nodeId: parseInt(targetNodeId),
|
||||
disassociatePromises.push(
|
||||
TemplatesService.disassociateWorkflowNode({
|
||||
parentId: nodeId,
|
||||
nodeId: alwaysNodeId,
|
||||
edge: "always"
|
||||
})
|
||||
);
|
||||
}
|
||||
break;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$q.all(disassociatePromises)
|
||||
.then(() => {
|
||||
let credentialPromises = credentialRequests.map((request) => {
|
||||
return TemplatesService.postWorkflowNodeCredential({
|
||||
id: request.id,
|
||||
data: request.data
|
||||
});
|
||||
});
|
||||
|
||||
return $q.all(associatePromises.concat(credentialPromises))
|
||||
.then(() => {
|
||||
Wait('stop');
|
||||
$scope.workflowChangesUnsaved = false;
|
||||
$scope.workflowChangesStarted = false;
|
||||
$scope.closeDialog();
|
||||
}).catch(({ data, status }) => {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
hdr: $scope.strings.get('error.HEADER')
|
||||
});
|
||||
});
|
||||
}).catch(({
|
||||
data,
|
||||
status
|
||||
}) => {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
hdr: $scope.strings.get('error.HEADER')
|
||||
Object.keys(linkMap).map((sourceNodeId) => {
|
||||
Object.keys(linkMap[sourceNodeId]).map((targetNodeId) => {
|
||||
const sourceChartNodeId = nodeIdToChartNodeIdMapping[sourceNodeId];
|
||||
const targetChartNodeId = nodeIdToChartNodeIdMapping[targetNodeId];
|
||||
switch(linkMap[sourceNodeId][targetNodeId]) {
|
||||
case "success":
|
||||
if (
|
||||
!nodeRef[sourceChartNodeId].originalNodeObject.success_nodes ||
|
||||
!nodeRef[sourceChartNodeId].originalNodeObject.success_nodes.includes(nodeRef[targetChartNodeId].originalNodeObject.id)
|
||||
) {
|
||||
associatePromises.push(
|
||||
TemplatesService.associateWorkflowNode({
|
||||
parentId: parseInt(sourceNodeId),
|
||||
nodeId: parseInt(targetNodeId),
|
||||
edge: "success"
|
||||
})
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "failure":
|
||||
if (
|
||||
!nodeRef[sourceChartNodeId].originalNodeObject.failure_nodes ||
|
||||
!nodeRef[sourceChartNodeId].originalNodeObject.failure_nodes.includes(nodeRef[targetChartNodeId].originalNodeObject.id)
|
||||
) {
|
||||
associatePromises.push(
|
||||
TemplatesService.associateWorkflowNode({
|
||||
parentId: parseInt(sourceNodeId),
|
||||
nodeId: parseInt(targetNodeId),
|
||||
edge: "failure"
|
||||
})
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "always":
|
||||
if (
|
||||
!nodeRef[sourceChartNodeId].originalNodeObject.always_nodes ||
|
||||
!nodeRef[sourceChartNodeId].originalNodeObject.always_nodes.includes(nodeRef[targetChartNodeId].originalNodeObject.id)
|
||||
) {
|
||||
associatePromises.push(
|
||||
TemplatesService.associateWorkflowNode({
|
||||
parentId: parseInt(sourceNodeId),
|
||||
nodeId: parseInt(targetNodeId),
|
||||
edge: "always"
|
||||
})
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}).catch(({ data, status }) => {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
hdr: $scope.strings.get('error.HEADER')
|
||||
|
||||
$q.all(disassociatePromises)
|
||||
.then(() => {
|
||||
let credentialPromises = credentialRequests.map((request) => {
|
||||
return TemplatesService.postWorkflowNodeCredential({
|
||||
id: request.id,
|
||||
data: request.data
|
||||
});
|
||||
});
|
||||
|
||||
return $q.all(associatePromises.concat(credentialPromises))
|
||||
.then(() => {
|
||||
Wait('stop');
|
||||
$scope.workflowChangesUnsaved = false;
|
||||
$scope.workflowChangesStarted = false;
|
||||
$scope.closeDialog();
|
||||
}).catch(({ data, status }) => {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
hdr: $scope.strings.get('error.HEADER')
|
||||
});
|
||||
});
|
||||
}).catch(({
|
||||
data,
|
||||
status
|
||||
}) => {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
hdr: $scope.strings.get('error.HEADER')
|
||||
});
|
||||
});
|
||||
});
|
||||
}).catch(({ data, status }) => {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
hdr: $scope.strings.get('error.HEADER')
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
// TODO: handle
|
||||
});
|
||||
} else {
|
||||
|
||||
|
||||
@ -68,39 +68,7 @@
|
||||
<div class="WorkflowLegend-maker">
|
||||
<div class="WorkflowLegend-maker--left">
|
||||
<i ng-class="{{ keyClassList }}" class="fa fa-compass Key-menuIcon" ng-click="toggleKey()"></i>
|
||||
<ul ng-show="showKey" class="Key-list noselect">
|
||||
<li class="Key-listItem">
|
||||
<p class="Key-heading">{{strings.get('workflow_maker.KEY')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--success"></div>
|
||||
<p class="Key-listItemContent">{{strings.get('workflow_maker.ON_SUCCESS')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--fail"></div>
|
||||
<p class="Key-listItemContent">{{strings.get('workflow_maker.ON_FAILURE')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--always"></div>
|
||||
<p class="Key-listItemContent">{{strings.get('workflow_maker.ALWAYS')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--default">P</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{strings.get('workflow_maker.PROJECT_SYNC')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--default">I</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{strings.get('workflow_maker.INVENTORY_SYNC')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--default">W</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{strings.get('workflow_maker.WORKFLOW')}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--warning">!</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{strings.get('workflow_maker.WARNING')}}</p>
|
||||
</li>
|
||||
</ul>
|
||||
<workflow-key ng-show="showKey"></workflow-key>
|
||||
</div>
|
||||
<div class="WorkflowLegend-maker--right">
|
||||
<span class="WorkflowMaker-totalJobs">{{strings.get('workflow_maker.TOTAL_NODES')}}</span>
|
||||
|
||||
@ -327,35 +327,7 @@
|
||||
<div class="WorkflowLegend-details">
|
||||
<div class="WorkflowLegend-details--left">
|
||||
<i ng-class="{{ keyClassList }}" class="fa fa-compass Key-menuIcon" ng-click="toggleKey()"></i>
|
||||
<ul ng-show="showKey" class="Key-list noselect">
|
||||
<li class="Key-listItem">
|
||||
<p class="Key-heading">{{strings.legend.KEY}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--success"></div>
|
||||
<p class="Key-listItemContent">{{strings.legend.ON_SUCCESS}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--fail"></div>
|
||||
<p class="Key-listItemContent">{{strings.legend.ON_FAILURE}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--always"></div>
|
||||
<p class="Key-listItemContent">{{strings.legend.ALWAYS}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--default">P</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{strings.legend.PROJECT_SYNC}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--default">I</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{strings.legend.INVENTORY_SYNC}}</p>
|
||||
</li>
|
||||
<li class="Key-listItem">
|
||||
<div class="Key-icon Key-icon--circle Key-icon--default">W</div>
|
||||
<p class="Key-listItemContent Key-listItemContent--circle">{{strings.legend.WORKFLOW}}</p>
|
||||
</li>
|
||||
</ul>
|
||||
<workflow-key ng-show="showKey"></workflow-key>
|
||||
</div>
|
||||
<div class="WorkflowLegend-details--right">
|
||||
<i ng-class="{'WorkflowMaker-manualControlsIcon--active': showManualControls}" class="fa fa-cog WorkflowMaker-manualControlsIcon" aria-hidden="true" alt="Controls" ng-click="toggleManualControls()"></i>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user