mirror of
https://github.com/ansible/awx.git
synced 2026-03-19 09:57:33 -02:30
Implements workflow convergence without proper layout
This commit is contained in:
@@ -119,9 +119,12 @@ function TemplatesStrings (BaseString) {
|
|||||||
START: t.s('START'),
|
START: t.s('START'),
|
||||||
DETAILS: t.s('DETAILS'),
|
DETAILS: t.s('DETAILS'),
|
||||||
TITLE: t.s('WORKFLOW VISUALIZER'),
|
TITLE: t.s('WORKFLOW VISUALIZER'),
|
||||||
EDIT_LINK: ({ parentName, childName }) => t.s('EDIT LINK | {{parentName}} to {{childName}}', { parentName, childName }),
|
ADD_LINK: t.s('ADD LINK'),
|
||||||
VIEW_LINK: ({ parentName, childName }) => t.s('VIEW LINK | {{parentName}} to {{childName}}', { parentName, childName })
|
EDIT_LINK: t.s('EDIT LINK'),
|
||||||
}
|
VIEW_LINK: t.s('VIEW LINK'),
|
||||||
|
NEW_LINK: t.s('Please click on an available node to form a new link.'),
|
||||||
|
UNLINK: t.s('UNLINK')
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import prompt from './prompt/main';
|
|||||||
import workflowChart from './workflows/workflow-chart/main';
|
import workflowChart from './workflows/workflow-chart/main';
|
||||||
import workflowMaker from './workflows/workflow-maker/main';
|
import workflowMaker from './workflows/workflow-maker/main';
|
||||||
import workflowControls from './workflows/workflow-controls/main';
|
import workflowControls from './workflows/workflow-controls/main';
|
||||||
import workflowService from './workflows/workflow.service';
|
|
||||||
import WorkflowForm from './workflows.form';
|
import WorkflowForm from './workflows.form';
|
||||||
import InventorySourcesList from './inventory-sources.list';
|
import InventorySourcesList from './inventory-sources.list';
|
||||||
import TemplateList from './templates.list';
|
import TemplateList from './templates.list';
|
||||||
@@ -35,7 +34,6 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
|
|||||||
workflowChart.name, workflowMaker.name, workflowControls.name
|
workflowChart.name, workflowMaker.name, workflowControls.name
|
||||||
])
|
])
|
||||||
.service('TemplatesService', templatesService)
|
.service('TemplatesService', templatesService)
|
||||||
.service('WorkflowService', workflowService)
|
|
||||||
.factory('WorkflowForm', WorkflowForm)
|
.factory('WorkflowForm', WorkflowForm)
|
||||||
// TODO: currently being kept arround for rbac selection, templates within projects and orgs, etc.
|
// TODO: currently being kept arround for rbac selection, templates within projects and orgs, etc.
|
||||||
.factory('TemplateList', TemplateList)
|
.factory('TemplateList', TemplateList)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
.WorkflowChart-linkHovering .WorkflowChart-linkOverlay {
|
.WorkflowChart-linkHovering .WorkflowChart-linkOverlay {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
fill: @cgrey;
|
fill: #E1E1E1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.WorkflowChart-linkHovering .WorkflowChart-linkPath {
|
.WorkflowChart-linkHovering .WorkflowChart-linkPath {
|
||||||
@@ -27,9 +27,11 @@
|
|||||||
.WorkflowChart-link polygon,
|
.WorkflowChart-link polygon,
|
||||||
.WorkflowChart-link .WorkflowChart-betweenNodesIcon,
|
.WorkflowChart-link .WorkflowChart-betweenNodesIcon,
|
||||||
.WorkflowChart-node .WorkflowChart-nodeAddCircle,
|
.WorkflowChart-node .WorkflowChart-nodeAddCircle,
|
||||||
|
.WorkflowChart-node .WorkflowChart-linkCircle,
|
||||||
.WorkflowChart-node .WorkflowChart-nodeRemoveCircle,
|
.WorkflowChart-node .WorkflowChart-nodeRemoveCircle,
|
||||||
.WorkflowChart-node .WorkflowChart-nodeAddIcon,
|
.WorkflowChart-node .WorkflowChart-nodeAddIcon,
|
||||||
.WorkflowChart-node .WorkflowChart-nodeRemoveIcon {
|
.WorkflowChart-node .WorkflowChart-nodeRemoveIcon,
|
||||||
|
.WorkflowChart-node .WorkflowChart-nodeLinkIcon {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,6 +43,14 @@
|
|||||||
fill: @default-succ-hov;
|
fill: @default-succ-hov;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.WorkflowChart-node .WorkflowChart-linkCircle {
|
||||||
|
fill: @default-link;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WorkflowChart-linkCircle.WorkflowChart-linkButtonHovering {
|
||||||
|
fill: @default-link-hov;
|
||||||
|
}
|
||||||
|
|
||||||
.WorkflowChart-node .WorkflowChart-nodeRemoveCircle {
|
.WorkflowChart-node .WorkflowChart-nodeRemoveCircle {
|
||||||
fill: @default-err;
|
fill: @default-err;
|
||||||
}
|
}
|
||||||
@@ -53,20 +63,27 @@
|
|||||||
fill: @default-secondary-bg;
|
fill: @default-secondary-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
.WorkflowChart-rect.WorkflowChart-placeholder {
|
.WorkflowChart-rect.WorkflowChart-isNodeBeingAdded {
|
||||||
stroke-dasharray: 3;
|
stroke-dasharray: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.WorkflowChart-node .WorkflowChart-transparentRect {
|
.WorkflowChart-node .WorkflowChart-nodeOverlay--transparent {
|
||||||
fill: @default-bg;
|
fill: @default-bg;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.WorkflowChart-node .WorkflowChart-nodeOverlay--disabled {
|
||||||
|
fill: @default-dark;
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
.WorkflowChart-alwaysShowAdd circle,
|
.WorkflowChart-alwaysShowAdd circle,
|
||||||
.WorkflowChart-alwaysShowAdd path,
|
.WorkflowChart-alwaysShowAdd path,
|
||||||
.WorkflowChart-alwaysShowAdd .WorkflowChart-betweenNodesIcon,
|
.WorkflowChart-alwaysShowAdd .WorkflowChart-betweenNodesIcon,
|
||||||
.WorkflowChart-nodeHovering .WorkflowChart-nodeAddCircle,
|
.WorkflowChart-nodeHovering .WorkflowChart-nodeAddCircle,
|
||||||
.WorkflowChart-nodeHovering .WorkflowChart-nodeAddIcon,
|
.WorkflowChart-nodeHovering .WorkflowChart-nodeAddIcon,
|
||||||
|
.WorkflowChart-nodeHovering .WorkflowChart-linkCircle,
|
||||||
|
.WorkflowChart-nodeHovering .WorkflowChart-nodeLinkIcon,
|
||||||
.WorkflowChart-nodeHovering .WorkflowChart-nodeRemoveCircle,
|
.WorkflowChart-nodeHovering .WorkflowChart-nodeRemoveCircle,
|
||||||
.WorkflowChart-nodeHovering .WorkflowChart-nodeRemoveIcon,
|
.WorkflowChart-nodeHovering .WorkflowChart-nodeRemoveIcon,
|
||||||
.WorkflowChart-addHovering circle,
|
.WorkflowChart-addHovering circle,
|
||||||
@@ -76,7 +93,7 @@
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.WorkflowChart-link.WorkflowChart-placeholder {
|
.WorkflowChart-link.WorkflowChart-isNodeBeingAdded {
|
||||||
stroke-dasharray: 3;
|
stroke-dasharray: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,3 +201,11 @@
|
|||||||
.WorkflowChart-dashedNode {
|
.WorkflowChart-dashedNode {
|
||||||
stroke-dasharray: 5,5;
|
stroke-dasharray: 5,5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.WorkflowChart-nodeLinkIcon {
|
||||||
|
color: @default-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WorkflowChart-nodeHovering .WorkflowChart-addLinkCircle {
|
||||||
|
fill: @default-link;
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,8 @@
|
|||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
export default ['$scope', 'TemplatesStrings', 'CreateSelect2', '$timeout',
|
export default ['$scope', 'TemplatesStrings', 'CreateSelect2',
|
||||||
function($scope, TemplatesStrings, CreateSelect2, $timeout) {
|
function($scope, TemplatesStrings, CreateSelect2) {
|
||||||
$scope.strings = TemplatesStrings;
|
$scope.strings = TemplatesStrings;
|
||||||
|
|
||||||
$scope.edgeTypeOptions = [
|
$scope.edgeTypeOptions = [
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ export default ['templateUrl',
|
|||||||
linkConfig: '<',
|
linkConfig: '<',
|
||||||
readOnly: '<',
|
readOnly: '<',
|
||||||
cancel: '&',
|
cancel: '&',
|
||||||
select: '&'
|
select: '&',
|
||||||
|
unlink: '&'
|
||||||
},
|
},
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
templateUrl: templateUrl('templates/workflows/workflow-maker/forms/workflow-link-form'),
|
templateUrl: templateUrl('templates/workflows/workflow-maker/forms/workflow-link-form'),
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<div class="WorkflowMaker-formTitle">{{readOnly ? strings.get('workflow_maker.VIEW_LINK', {parentName: linkConfig.parent.name, childName: linkConfig.child.name}) : strings.get('workflow_maker.EDIT_LINK', {parentName: linkConfig.parent.name, childName: linkConfig.child.name}) }}</div>
|
<div class="WorkflowMaker-formTitle">{{readOnly ? strings.get('workflow_maker.VIEW_LINK') : (linkConfig.mode === 'add' ? strings.get('workflow_maker.ADD_LINK') : strings.get('workflow_maker.EDIT_LINK')) }} | {{linkConfig.parent.name}} {{linkConfig.child ? 'to ' + linkConfig.child.name : ''}}</div>
|
||||||
<div class="WorkflowMaker-form">
|
<div class="WorkflowMaker-form">
|
||||||
<div class="form-group Form-formGroup Form-formGroup--singleColumn">
|
<div class="form-group Form-formGroup Form-formGroup--singleColumn">
|
||||||
|
<div ng-show="linkConfig.mode === 'add' && !linkConfig.child">{{:: strings.get('workflow_maker.NEW_LINK')}}</div>
|
||||||
|
<span ng-show="linkConfig.child">
|
||||||
<label for="edgeType" class="Form-inputLabelContainer">
|
<label for="edgeType" class="Form-inputLabelContainer">
|
||||||
<span class="Form-requiredAsterisk">*</span>
|
<span class="Form-requiredAsterisk">*</span>
|
||||||
<span class="Form-inputLabel">{{:: strings.get('workflow_maker.RUN') }}</span>
|
<span class="Form-inputLabel">{{:: strings.get('workflow_maker.RUN') }}</span>
|
||||||
@@ -17,11 +19,12 @@
|
|||||||
aria-hidden="true">
|
aria-hidden="true">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</span>
|
||||||
<div class="buttons Form-buttons" id="workflow_maker_controls">
|
</div>
|
||||||
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_cancel_link_btn" ng-show="!readOnly" ng-click="cancel()"> {{:: strings.get('CANCEL') }}</button>
|
<div class="buttons Form-buttons" id="workflow_maker_controls">
|
||||||
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_cancel_link_btn" ng-show="readOnly" ng-click="cancel()"> {{:: strings.get('CLOSE') }}</button>
|
<button type="button" class="btn btn-sm Form-primaryButton Form-primaryButton--noMargin" id="workflow_maker_unlink_btn" ng-show="!readOnly && linkConfig.canUnlink" ng-click="unlink()"> {{:: strings.get('workflow_maker.UNLINK') }}</button>
|
||||||
<button type="button" class="btn btn-sm Form-saveButton" id="workflow_maker_select_link_btn" ng-show="!readOnly" ng-click="select({edgeType: edgeType.value})" ng-disabled="!edgeType"> {{:: strings.get('SAVE') }}</button>
|
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_cancel_link_btn" ng-show="!readOnly" ng-click="cancel()"> {{:: strings.get('CANCEL') }}</button>
|
||||||
</div>
|
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_cancel_link_btn" ng-show="readOnly" ng-click="cancel()"> {{:: strings.get('CLOSE') }}</button>
|
||||||
|
<button type="button" class="btn btn-sm Form-saveButton" id="workflow_maker_select_link_btn" ng-show="!readOnly && linkConfig.child" ng-click="select({edgeType: edgeType.value})" ng-disabled="!edgeType"> {{:: strings.get('SAVE') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService', 'Rest', '$q',
|
export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService', 'Rest', '$q',
|
||||||
'WorkflowService', 'TemplatesStrings', 'CreateSelect2', 'Empty', 'generateList', 'QuerySet',
|
'TemplatesStrings', 'CreateSelect2', 'Empty', 'generateList', 'QuerySet',
|
||||||
'GetBasePath', 'TemplateList', 'ProjectList', 'InventorySourcesList',
|
'GetBasePath', 'TemplateList', 'ProjectList', 'InventorySourcesList', 'ProcessErrors',
|
||||||
function($scope, TemplatesService, JobTemplate, PromptService, Rest, $q,
|
function($scope, TemplatesService, JobTemplate, PromptService, Rest, $q,
|
||||||
WorkflowService, TemplatesStrings, CreateSelect2, Empty, generateList, qs,
|
TemplatesStrings, CreateSelect2, Empty, generateList, qs,
|
||||||
GetBasePath, TemplateList, ProjectList, InventorySourcesList
|
GetBasePath, TemplateList, ProjectList, InventorySourcesList, ProcessErrors
|
||||||
) {
|
) {
|
||||||
|
|
||||||
let promptWatcher, credentialsWatcher, surveyQuestionWatcher, listPromises = [];
|
let promptWatcher, credentialsWatcher, surveyQuestionWatcher, listPromises = [];
|
||||||
@@ -55,48 +55,6 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
projectList.disableRowValue = 'readOnly';
|
projectList.disableRowValue = 'readOnly';
|
||||||
$scope.projectList = projectList;
|
$scope.projectList = projectList;
|
||||||
|
|
||||||
$scope.$watch('node', (newNode, oldNode) => {
|
|
||||||
if (oldNode.id !== newNode.id) {
|
|
||||||
setupNodeForm();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$watchGroup(['templates', 'projects', 'inventory_sources', 'activeTab'], () => {
|
|
||||||
// TODO: make this more concise
|
|
||||||
switch($scope.activeTab) {
|
|
||||||
case 'jobs':
|
|
||||||
$scope.templates.forEach(function(row, i) {
|
|
||||||
if(_.hasIn($scope, 'node.unifiedJobTemplate.id') && row.id === $scope.node.unifiedJobTemplate.id) {
|
|
||||||
$scope.templates[i].checked = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$scope.templates[i].checked = 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'project_syncs':
|
|
||||||
$scope.projects.forEach(function(row, i) {
|
|
||||||
if(_.hasIn($scope, 'node.unifiedJobTemplate.id') && row.id === $scope.node.unifiedJobTemplate.id) {
|
|
||||||
$scope.projects[i].checked = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$scope.projects[i].checked = 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'inventory_syncs':
|
|
||||||
$scope.inventory_sources.forEach(function(row, i) {
|
|
||||||
if(_.hasIn($scope, 'node.unifiedJobTemplate.id') && row.id === $scope.node.unifiedJobTemplate.id) {
|
|
||||||
$scope.inventory_sources[i].checked = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$scope.inventory_sources[i].checked = 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const checkCredentialsForRequiredPasswords = () => {
|
const checkCredentialsForRequiredPasswords = () => {
|
||||||
let credentialRequiresPassword = false;
|
let credentialRequiresPassword = false;
|
||||||
$scope.promptData.prompts.credentials.value.forEach((credential) => {
|
$scope.promptData.prompts.credentials.value.forEach((credential) => {
|
||||||
@@ -135,14 +93,44 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const finishConfiguringAdd = () => {
|
||||||
|
$scope.activeTab = "jobs";
|
||||||
|
const alwaysOption = {
|
||||||
|
label: $scope.strings.get('workflow_maker.ALWAYS'),
|
||||||
|
value: 'always'
|
||||||
|
};
|
||||||
|
const successOption = {
|
||||||
|
label: $scope.strings.get('workflow_maker.ON_SUCCESS'),
|
||||||
|
value: 'success'
|
||||||
|
};
|
||||||
|
const failureOption = {
|
||||||
|
label: $scope.strings.get('workflow_maker.ON_FAILURE'),
|
||||||
|
value: 'failure'
|
||||||
|
};
|
||||||
|
$scope.edgeTypeOptions = [alwaysOption];
|
||||||
|
switch($scope.nodeConfig.newNodeIsRoot) {
|
||||||
|
case true:
|
||||||
|
$scope.edgeType = alwaysOption;
|
||||||
|
break;
|
||||||
|
case false:
|
||||||
|
$scope.edgeType = successOption;
|
||||||
|
$scope.edgeTypeOptions.push(successOption, failureOption);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CreateSelect2({
|
||||||
|
element: '#workflow_node_edge_3',
|
||||||
|
multiple: false
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.nodeFormDataLoaded = true;
|
||||||
|
};
|
||||||
|
|
||||||
const finishConfiguringEdit = () => {
|
const finishConfiguringEdit = () => {
|
||||||
|
|
||||||
let jobTemplate = new JobTemplate();
|
let jobTemplate = new JobTemplate();
|
||||||
|
|
||||||
console.log($scope.node);
|
if (_.get($scope, 'nodeConfig.node.promptData') && !_.isEmpty($scope.nodeConfig.node.promptData)) {
|
||||||
|
$scope.promptData = _.cloneDeep($scope.nodeConfig.node.promptData);
|
||||||
if (!_.isEmpty($scope.node.promptData)) {
|
|
||||||
$scope.promptData = _.cloneDeep($scope.node.promptData);
|
|
||||||
const launchConf = $scope.promptData.launchConf;
|
const launchConf = $scope.promptData.launchConf;
|
||||||
|
|
||||||
if (!launchConf.survey_enabled &&
|
if (!launchConf.survey_enabled &&
|
||||||
@@ -162,7 +150,7 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
} else {
|
} else {
|
||||||
$scope.showPromptButton = true;
|
$scope.showPromptButton = true;
|
||||||
|
|
||||||
if (launchConf.ask_inventory_on_launch && !_.has(launchConf, 'defaults.inventory') && !_.has($scope, 'node.originalNodeObj.summary_fields.inventory')) {
|
if (launchConf.ask_inventory_on_launch && !_.has(launchConf, 'defaults.inventory') && !_.has($scope, 'nodeConfig.node.originalNodeObject.summary_fields.inventory')) {
|
||||||
$scope.promptModalMissingReqFields = true;
|
$scope.promptModalMissingReqFields = true;
|
||||||
} else {
|
} else {
|
||||||
$scope.promptModalMissingReqFields = false;
|
$scope.promptModalMissingReqFields = false;
|
||||||
@@ -170,13 +158,13 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
}
|
}
|
||||||
$scope.nodeFormDataLoaded = true;
|
$scope.nodeFormDataLoaded = true;
|
||||||
} else if (
|
} else if (
|
||||||
_.get($scope, 'node.unifiedJobTemplate.unified_job_type') === 'job_template' ||
|
_.get($scope, 'nodeConfig.node.fullUnifiedJobTemplateObject.unified_job_type') === 'job_template' ||
|
||||||
_.get($scope, 'node.unifiedJobTemplate.type') === 'job_template'
|
_.get($scope, 'nodeConfig.node.fullUnifiedJobTemplateObject.type') === 'job_template'
|
||||||
) {
|
) {
|
||||||
let promises = [jobTemplate.optionsLaunch($scope.node.unifiedJobTemplate.id), jobTemplate.getLaunch($scope.node.unifiedJobTemplate.id)];
|
let promises = [jobTemplate.optionsLaunch($scope.nodeConfig.node.fullUnifiedJobTemplateObject.id), jobTemplate.getLaunch($scope.nodeConfig.node.fullUnifiedJobTemplateObject.id)];
|
||||||
|
|
||||||
if (_.has($scope, 'node.originalNodeObj.related.credentials')) {
|
if (_.has($scope, 'nodeConfig.node.originalNodeObject.related.credentials')) {
|
||||||
Rest.setUrl($scope.node.originalNodeObj.related.credentials);
|
Rest.setUrl($scope.nodeConfig.node.originalNodeObject.related.credentials);
|
||||||
promises.push(Rest.get());
|
promises.push(Rest.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +177,7 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
let prompts = PromptService.processPromptValues({
|
let prompts = PromptService.processPromptValues({
|
||||||
launchConf: responses[1].data,
|
launchConf: responses[1].data,
|
||||||
launchOptions: responses[0].data,
|
launchOptions: responses[0].data,
|
||||||
currentValues: $scope.node.originalNodeObj
|
currentValues: $scope.nodeConfig.node.originalNodeObject
|
||||||
});
|
});
|
||||||
|
|
||||||
let defaultCredsWithoutOverrides = [];
|
let defaultCredsWithoutOverrides = [];
|
||||||
@@ -222,7 +210,7 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
|
|
||||||
prompts.credentials.value = workflowNodeCredentials.concat(defaultCredsWithoutOverrides);
|
prompts.credentials.value = workflowNodeCredentials.concat(defaultCredsWithoutOverrides);
|
||||||
|
|
||||||
if ((!$scope.node.unifiedJobTemplate.inventory && !launchConf.ask_inventory_on_launch) || !$scope.node.unifiedJobTemplate.project) {
|
if ((!$scope.nodeConfig.node.fullUnifiedJobTemplateObject.inventory && !launchConf.ask_inventory_on_launch) || !$scope.nodeConfig.node.fullUnifiedJobTemplateObject.project) {
|
||||||
$scope.selectedTemplateInvalid = true;
|
$scope.selectedTemplateInvalid = true;
|
||||||
} else {
|
} else {
|
||||||
$scope.selectedTemplateInvalid = false;
|
$scope.selectedTemplateInvalid = false;
|
||||||
@@ -264,7 +252,7 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
} else {
|
} else {
|
||||||
$scope.showPromptButton = true;
|
$scope.showPromptButton = true;
|
||||||
|
|
||||||
if (launchConf.ask_inventory_on_launch && !_.has(launchConf, 'defaults.inventory') && !_.has($scope, 'node.originalNodeObj.summary_fields.inventory')) {
|
if (launchConf.ask_inventory_on_launch && !_.has(launchConf, 'defaults.inventory') && !_.has($scope, 'nodeConfig.node.originalNodeObject.summary_fields.inventory')) {
|
||||||
$scope.promptModalMissingReqFields = true;
|
$scope.promptModalMissingReqFields = true;
|
||||||
} else {
|
} else {
|
||||||
$scope.promptModalMissingReqFields = false;
|
$scope.promptModalMissingReqFields = false;
|
||||||
@@ -272,24 +260,24 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
|
|
||||||
if (responses[1].data.survey_enabled) {
|
if (responses[1].data.survey_enabled) {
|
||||||
// go out and get the survey questions
|
// go out and get the survey questions
|
||||||
jobTemplate.getSurveyQuestions($scope.node.unifiedJobTemplate.id)
|
jobTemplate.getSurveyQuestions($scope.nodeConfig.node.fullUnifiedJobTemplateObject.id)
|
||||||
.then((surveyQuestionRes) => {
|
.then((surveyQuestionRes) => {
|
||||||
|
|
||||||
let processed = PromptService.processSurveyQuestions({
|
let processed = PromptService.processSurveyQuestions({
|
||||||
surveyQuestions: surveyQuestionRes.data.spec,
|
surveyQuestions: surveyQuestionRes.data.spec,
|
||||||
extra_data: _.cloneDeep($scope.node.originalNodeObj.extra_data)
|
extra_data: _.cloneDeep($scope.nodeConfig.node.originalNodeObject.extra_data)
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.missingSurveyValue = processed.missingSurveyValue;
|
$scope.missingSurveyValue = processed.missingSurveyValue;
|
||||||
|
|
||||||
$scope.extraVars = (processed.extra_data === '' || _.isEmpty(processed.extra_data)) ? '---' : '---\n' + jsyaml.safeDump(processed.extra_data);
|
$scope.extraVars = (processed.extra_data === '' || _.isEmpty(processed.extra_data)) ? '---' : '---\n' + jsyaml.safeDump(processed.extra_data);
|
||||||
|
|
||||||
$scope.node.promptData = $scope.promptData = {
|
$scope.nodeConfig.node.promptData = $scope.promptData = {
|
||||||
launchConf: launchConf,
|
launchConf: launchConf,
|
||||||
launchOptions: launchOptions,
|
launchOptions: launchOptions,
|
||||||
prompts: prompts,
|
prompts: prompts,
|
||||||
surveyQuestions: surveyQuestionRes.data.spec,
|
surveyQuestions: surveyQuestionRes.data.spec,
|
||||||
template: $scope.node.unifiedJobTemplate.id
|
template: $scope.nodeConfig.node.fullUnifiedJobTemplateObject.id
|
||||||
};
|
};
|
||||||
|
|
||||||
surveyQuestionWatcher = $scope.$watch('promptData.surveyQuestions', () => {
|
surveyQuestionWatcher = $scope.$watch('promptData.surveyQuestions', () => {
|
||||||
@@ -309,11 +297,11 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
$scope.nodeFormDataLoaded = true;
|
$scope.nodeFormDataLoaded = true;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
$scope.node.promptData = $scope.promptData = {
|
$scope.nodeConfig.node.promptData = $scope.promptData = {
|
||||||
launchConf: launchConf,
|
launchConf: launchConf,
|
||||||
launchOptions: launchOptions,
|
launchOptions: launchOptions,
|
||||||
prompts: prompts,
|
prompts: prompts,
|
||||||
template: $scope.node.unifiedJobTemplate.id
|
template: $scope.nodeConfig.node.fullUnifiedJobTemplateObject.id
|
||||||
};
|
};
|
||||||
|
|
||||||
checkCredentialsForRequiredPasswords();
|
checkCredentialsForRequiredPasswords();
|
||||||
@@ -328,12 +316,12 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
$scope.nodeFormDataLoaded = true;
|
$scope.nodeFormDataLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_.get($scope, 'node.unifiedJobTemplate')) {
|
if (_.get($scope, 'nodeConfig.node.fullUnifiedJobTemplateObject')) {
|
||||||
if (_.get($scope, 'node.unifiedJobTemplate.type') === "job_template") {
|
if (_.get($scope, 'nodeConfig.node.fullUnifiedJobTemplateObject.type') === "job_template") {
|
||||||
$scope.activeTab = "jobs";
|
$scope.activeTab = "jobs";
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.selectedTemplate = $scope.node.unifiedJobTemplate;
|
$scope.selectedTemplate = $scope.nodeConfig.node.fullUnifiedJobTemplateObject;
|
||||||
|
|
||||||
if ($scope.selectedTemplate.unified_job_type) {
|
if ($scope.selectedTemplate.unified_job_type) {
|
||||||
switch ($scope.selectedTemplate.unified_job_type) {
|
switch ($scope.selectedTemplate.unified_job_type) {
|
||||||
@@ -364,79 +352,6 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
$scope.activeTab = "jobs";
|
$scope.activeTab = "jobs";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($scope.mode === 'add') {
|
|
||||||
const alwaysOption = {
|
|
||||||
label: $scope.strings.get('workflow_maker.ALWAYS'),
|
|
||||||
value: 'always'
|
|
||||||
};
|
|
||||||
const successOption = {
|
|
||||||
label: $scope.strings.get('workflow_maker.ON_SUCCESS'),
|
|
||||||
value: 'success'
|
|
||||||
};
|
|
||||||
const failureOption = {
|
|
||||||
label: $scope.strings.get('workflow_maker.ON_FAILURE'),
|
|
||||||
value: 'failure'
|
|
||||||
};
|
|
||||||
$scope.edgeTypeOptions = [alwaysOption];
|
|
||||||
switch($scope.node.isRoot) {
|
|
||||||
case true:
|
|
||||||
$scope.edgeType = alwaysOption;
|
|
||||||
break;
|
|
||||||
case false:
|
|
||||||
$scope.edgeType = successOption;
|
|
||||||
$scope.edgeTypeOptions.push(successOption, failureOption);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
CreateSelect2({
|
|
||||||
element: '#workflow_node_edge_3',
|
|
||||||
multiple: false
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.nodeFormDataLoaded = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Determine whether or not we need to go out and GET this nodes unified job template
|
|
||||||
// in order to determine whether or not prompt fields are needed
|
|
||||||
|
|
||||||
$scope.openPromptModal = function() {
|
|
||||||
$scope.promptData.triggerModalOpen = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.toggle_row = function(selectedRow) {
|
|
||||||
if (!$scope.readOnly) {
|
|
||||||
// TODO: make this more concise
|
|
||||||
switch($scope.activeTab) {
|
|
||||||
case 'jobs':
|
|
||||||
$scope.templates.forEach(function(row, i) {
|
|
||||||
if (row.id === selectedRow.id) {
|
|
||||||
$scope.templates[i].checked = 1;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$scope.templates[i].checked = 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'project_syncs':
|
|
||||||
$scope.projects.forEach(function(row, i) {
|
|
||||||
if (row.id === selectedRow.id) {
|
|
||||||
$scope.projects[i].checked = 1;
|
|
||||||
} else {
|
|
||||||
$scope.projects[i].checked = 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'inventory_syncs':
|
|
||||||
$scope.inventory_sources.forEach(function(row, i) {
|
|
||||||
if (row.id === selectedRow.id) {
|
|
||||||
$scope.inventory_sources[i].checked = 1;
|
|
||||||
} else {
|
|
||||||
$scope.inventory_sources[i].checked = 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
templateManuallySelected(selectedRow);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const templateManuallySelected = (selectedTemplate) => {
|
const templateManuallySelected = (selectedTemplate) => {
|
||||||
@@ -597,7 +512,7 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
page_size: '5',
|
page_size: '5',
|
||||||
order_by: 'name',
|
order_by: 'name',
|
||||||
not__source: ''
|
not__source: ''
|
||||||
}
|
};
|
||||||
|
|
||||||
$scope.inventory_sources = [];
|
$scope.inventory_sources = [];
|
||||||
$scope.inventory_source_dataset = {};
|
$scope.inventory_source_dataset = {};
|
||||||
@@ -612,26 +527,113 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
|
|
||||||
$q.all(listPromises)
|
$q.all(listPromises)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (!$scope.node.isNew && !$scope.node.edited && $scope.node.unifiedJobTemplate && $scope.node.unifiedJobTemplate.unified_job_type && $scope.node.unifiedJobTemplate.unified_job_type === 'job') {
|
if ($scope.nodeConfig.mode === "edit") {
|
||||||
// This is a node that we got back from the api with an incomplete
|
// Make sure that we have the full unified job template object
|
||||||
// unified job template so we're going to pull down the whole object
|
if (!$scope.nodeConfig.node.fullUnifiedJobTemplate && _.get($scope, 'nodeConfig.node.originalNodeObject.summary_fields.unified_job_template.unified_job_type') === 'job') {
|
||||||
|
// This is a node that we got back from the api with an incomplete
|
||||||
TemplatesService.getUnifiedJobTemplate($scope.node.unifiedJobTemplate.id)
|
// unified job template so we're going to pull down the whole object
|
||||||
.then(function(data) {
|
TemplatesService.getUnifiedJobTemplate($scope.nodeConfig.node.originalNodeObject.summary_fields.unified_job_template.id)
|
||||||
$scope.node.unifiedJobTemplate = _.clone(data.data.results[0]);
|
.then(function({data}) {
|
||||||
finishConfiguringEdit();
|
$scope.nodeConfig.node.fullUnifiedJobTemplateObject = data.results[0];
|
||||||
}, function(error) {
|
finishConfiguringEdit();
|
||||||
ProcessErrors($scope, error.data, error.status, null, {
|
}, function(error) {
|
||||||
hdr: 'Error!',
|
ProcessErrors($scope, error.data, error.status, null, {
|
||||||
msg: 'Failed to get unified job template. GET returned ' +
|
hdr: 'Error!',
|
||||||
'status: ' + error.status
|
msg: 'Failed to get unified job template. GET returned ' +
|
||||||
|
'status: ' + error.status
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
} else {
|
||||||
|
finishConfiguringEdit();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
finishConfiguringEdit();
|
finishConfiguringAdd();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
|
$scope.openPromptModal = function() {
|
||||||
|
$scope.promptData.triggerModalOpen = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.toggle_row = function(selectedRow) {
|
||||||
|
if (!$scope.readOnly) {
|
||||||
|
// TODO: make this more concise
|
||||||
|
switch($scope.activeTab) {
|
||||||
|
case 'jobs':
|
||||||
|
$scope.templates.forEach(function(row, i) {
|
||||||
|
if (row.id === selectedRow.id) {
|
||||||
|
$scope.templates[i].checked = 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$scope.templates[i].checked = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'project_syncs':
|
||||||
|
$scope.projects.forEach(function(row, i) {
|
||||||
|
if (row.id === selectedRow.id) {
|
||||||
|
$scope.projects[i].checked = 1;
|
||||||
|
} else {
|
||||||
|
$scope.projects[i].checked = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'inventory_syncs':
|
||||||
|
$scope.inventory_sources.forEach(function(row, i) {
|
||||||
|
if (row.id === selectedRow.id) {
|
||||||
|
$scope.inventory_sources[i].checked = 1;
|
||||||
|
} else {
|
||||||
|
$scope.inventory_sources[i].checked = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
templateManuallySelected(selectedRow);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$watch('nodeConfig.nodeId', (newNodeId, oldNodeId) => {
|
||||||
|
if (newNodeId !== oldNodeId) {
|
||||||
|
setupNodeForm();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$watchGroup(['templates', 'projects', 'inventory_sources', 'activeTab'], () => {
|
||||||
|
// TODO: make this more concise
|
||||||
|
switch($scope.activeTab) {
|
||||||
|
case 'jobs':
|
||||||
|
$scope.templates.forEach(function(row, i) {
|
||||||
|
if(_.hasIn($scope, 'nodeConfig.node.fullUnifiedJobTemplateObject.id') && row.id === $scope.nodeConfig.node.fullUnifiedJobTemplateObject.id) {
|
||||||
|
$scope.templates[i].checked = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$scope.templates[i].checked = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'project_syncs':
|
||||||
|
$scope.projects.forEach(function(row, i) {
|
||||||
|
if(_.hasIn($scope, 'nodeConfig.node.fullUnifiedJobTemplateObject.id') && row.id === $scope.nodeConfig.node.fullUnifiedJobTemplateObject.id) {
|
||||||
|
$scope.projects[i].checked = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$scope.projects[i].checked = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'inventory_syncs':
|
||||||
|
$scope.inventory_sources.forEach(function(row, i) {
|
||||||
|
if(_.hasIn($scope, 'nodeConfig.node.fullUnifiedJobTemplateObject.id') && row.id === $scope.nodeConfig.node.fullUnifiedJobTemplateObject.id) {
|
||||||
|
$scope.inventory_sources[i].checked = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$scope.inventory_sources[i].checked = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
setupNodeForm();
|
setupNodeForm();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ export default ['templateUrl',
|
|||||||
function(templateUrl) {
|
function(templateUrl) {
|
||||||
return {
|
return {
|
||||||
scope: {
|
scope: {
|
||||||
mode: '<',
|
nodeConfig: '<',
|
||||||
node: '=',
|
|
||||||
cancel: '&',
|
cancel: '&',
|
||||||
select: '&',
|
select: '&',
|
||||||
readOnly: '<'
|
readOnly: '<'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<div ng-show="nodeFormDataLoaded">
|
<div ng-show="nodeFormDataLoaded">
|
||||||
<div class="WorkflowMaker-formTitle ng-binding">{{mode === 'edit' ? node.unifiedJobTemplate.name : strings.get('workflow_maker.ADD_A_TEMPLATE')}}</div>
|
<div class="WorkflowMaker-formTitle ng-binding">{{nodeConfig.mode === 'edit' ? node.unifiedJobTemplate.name : strings.get('workflow_maker.ADD_A_TEMPLATE')}}</div>
|
||||||
<div class="Form-tabHolder">
|
<div class="Form-tabHolder">
|
||||||
<div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': activeTab === 'jobs'}" ng-click="activeTab = 'jobs'">{{strings.get('workflow_maker.JOBS')}}</div>
|
<div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': activeTab === 'jobs'}" ng-click="activeTab = 'jobs'">{{strings.get('workflow_maker.JOBS')}}</div>
|
||||||
<div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': activeTab === 'project_syncs'}" ng-click="activeTab = 'project_syncs'">{{strings.get('workflow_maker.PROJECT_SYNC')}}</div>
|
<div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': activeTab === 'project_syncs'}" ng-click="activeTab = 'project_syncs'">{{strings.get('workflow_maker.PROJECT_SYNC')}}</div>
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
<span>{{:: strings.get('workflows.CREDENTIAL_WITH_PASS') }}</span>
|
<span>{{:: strings.get('workflows.CREDENTIAL_WITH_PASS') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group Form-formGroup Form-formGroup--singleColumn" ng-show="mode === 'add'">
|
<div class="form-group Form-formGroup Form-formGroup--singleColumn" ng-show="nodeConfig.mode === 'add'">
|
||||||
<label for="edgeType" class="Form-inputLabelContainer">
|
<label for="edgeType" class="Form-inputLabelContainer">
|
||||||
<span class="Form-requiredAsterisk">*</span>
|
<span class="Form-requiredAsterisk">*</span>
|
||||||
<span class="Form-inputLabel">{{:: strings.get('workflow_maker.RUN') }}</span>
|
<span class="Form-inputLabel">{{:: strings.get('workflow_maker.RUN') }}</span>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -74,26 +74,39 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="WorkflowLegend-maker--right">
|
<div class="WorkflowLegend-maker--right">
|
||||||
<span class="WorkflowMaker-totalJobs">{{strings.get('workflow_maker.TOTAL_TEMPLATES')}}</span>
|
<span class="WorkflowMaker-totalJobs">{{strings.get('workflow_maker.TOTAL_TEMPLATES')}}</span>
|
||||||
<span class="badge List-titleBadge" ng-bind="treeData.data.totalNodes"></span>
|
<span class="badge List-titleBadge" ng-bind="treeState.arrayOfNodesForChart.length-1"></span>
|
||||||
<i ng-class="{'WorkflowMaker-manualControlsIcon--active': showManualControls}" class="fa fa-cog WorkflowMaker-manualControlsIcon" aria-hidden="true" alt="Controls" ng-click="toggleManualControls()"></i>
|
<i ng-class="{'WorkflowMaker-manualControlsIcon--active': showManualControls}" class="fa fa-cog WorkflowMaker-manualControlsIcon" aria-hidden="true" alt="Controls" ng-click="toggleManualControls()"></i>
|
||||||
<div ng-show="showManualControls" class="WorkflowMaker-manualControls noselect">
|
<div ng-show="showManualControls" class="WorkflowMaker-manualControls noselect">
|
||||||
<workflow-controls class="WorkflowControls" pan-chart="panChart(direction)" zoom-chart="zoomChart(zoom)" reset-chart="resetChart()" zoom-to-fit-chart="zoomToFitChart()"></workflow-controls>
|
<workflow-controls class="WorkflowControls" pan-chart="panChart(direction)" zoom-chart="zoomChart(zoom)" reset-chart="resetChart()" zoom-to-fit-chart="zoomToFitChart()"></workflow-controls>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<workflow-chart ng-if="modalOpen" tree-data="treeData.data" add-node="startAddNode(parent, betweenTwoNodes)" edit-node="startEditNode(nodeToEdit)" edit-link="startEditLink(parentId, childId)" delete-node="startDeleteNode(nodeToDelete)" workflow-zoomed="workflowZoomed(zoom)" can-add-workflow-job-template="canAddWorkflowJobTemplate" workflow-job-template-obj="workflowJobTemplateObj" mode="edit" class="WorkflowMaker-chart"></workflow-chart>
|
<workflow-chart
|
||||||
|
ng-if="modalOpen"
|
||||||
|
tree-state="treeState"
|
||||||
|
add-node-without-child="startAddNodeWithoutChild(parent)"
|
||||||
|
add-node-with-child="startAddNodeWithChild(link)"
|
||||||
|
edit-node="startEditNode(nodeToEdit)"
|
||||||
|
edit-link="startEditLink(linkToEdit)"
|
||||||
|
select-node-for-linking="selectNodeForLinking(nodeToStartLink)"
|
||||||
|
delete-node="startDeleteNode(nodeToDelete)"
|
||||||
|
workflow-zoomed="workflowZoomed(zoom)"
|
||||||
|
read-only="readOnly"
|
||||||
|
mode="edit"
|
||||||
|
class="WorkflowMaker-chart">
|
||||||
|
</workflow-chart>
|
||||||
</div>
|
</div>
|
||||||
<div class="WorkflowMaker-contentRight">
|
<div class="WorkflowMaker-contentRight">
|
||||||
<span ng-if="formState.showNodeForm">
|
<span ng-if="formState.showNodeForm">
|
||||||
<workflow-node-form mode="nodeFormMode" node="nodeBeingWorkedOn" select="confirmNodeForm(selectedTemplate, promptData, edgeType)" cancel="cancelNodeForm()" read-only="!workflowJobTemplateObj.summary_fields.user_capabilities.edit"/>
|
<workflow-node-form node-config="nodeConfig" node="nodeBeingWorkedOn" select="confirmNodeForm(selectedTemplate, promptData, edgeType)" cancel="cancelNodeForm()" read-only="!workflowJobTemplateObj.summary_fields.user_capabilities.edit"/>
|
||||||
</span>
|
</span>
|
||||||
<span ng-if="formState.showLinkForm">
|
<span ng-if="formState.showLinkForm">
|
||||||
<workflow-link-form link-config="linkConfig" read-only="!workflowJobTemplateObj.summary_fields.user_capabilities.edit" select="confirmLinkForm(edgeType)" cancel="cancelLinkForm()"/>
|
<workflow-link-form link-config="linkConfig" read-only="!workflowJobTemplateObj.summary_fields.user_capabilities.edit" select="confirmLinkForm(edgeType)" cancel="cancelLinkForm()" unlink="unlink()"/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="WorkflowMaker-buttonHolder">
|
<div class="WorkflowMaker-buttonHolder">
|
||||||
<button type="button" class="btn btn-sm WorkflowMaker-cancelButton" ng-click="closeWorkflowMaker()"> {{:: strings.get('CLOSE') }}</button>
|
<button type="button" class="btn btn-sm WorkflowMaker-cancelButton" ng-click="closeWorkflowMaker()"> {{:: strings.get('CLOSE') }}</button>
|
||||||
<button type="button" class="btn btn-sm WorkflowMaker-saveButton" ng-click="saveWorkflowMaker()" ng-show="workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate" ng-disabled="showNodeForm || showLinkForm"> {{:: strings.get('SAVE') }}</button>
|
<button type="button" class="btn btn-sm WorkflowMaker-saveButton" ng-click="saveWorkflowMaker()" ng-show="workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate" ng-disabled="formState.showNodeForm || formState.showLinkForm"> {{:: strings.get('SAVE') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,294 +0,0 @@
|
|||||||
export default ['$q', function($q){
|
|
||||||
return {
|
|
||||||
searchTree: function(params) {
|
|
||||||
// params.element
|
|
||||||
// params.matchingId
|
|
||||||
// params.byNodeId
|
|
||||||
|
|
||||||
let prospectiveId = params.byNodeId ? params.element.nodeId : params.element.id;
|
|
||||||
|
|
||||||
if(prospectiveId === params.matchingId){
|
|
||||||
return params.element;
|
|
||||||
}else if (params.element.children && params.element.children.length > 0){
|
|
||||||
let result = null;
|
|
||||||
const thisService = this;
|
|
||||||
_.forEach(params.element.children, function(child) {
|
|
||||||
result = thisService.searchTree({
|
|
||||||
element: child,
|
|
||||||
matchingId: params.matchingId,
|
|
||||||
byNodeId: params.byNodeId ? params.byNodeId : false
|
|
||||||
});
|
|
||||||
if(result) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
removeNodeFromTree: function(params) {
|
|
||||||
// params.tree
|
|
||||||
// params.nodeToBeDeleted
|
|
||||||
|
|
||||||
let parentNode = this.searchTree({
|
|
||||||
element: params.tree,
|
|
||||||
matchingId: params.nodeToBeDeleted.parent.id
|
|
||||||
});
|
|
||||||
let nodeToBeDeleted = this.searchTree({
|
|
||||||
element: parentNode,
|
|
||||||
matchingId: params.nodeToBeDeleted.id
|
|
||||||
});
|
|
||||||
|
|
||||||
if(nodeToBeDeleted.children) {
|
|
||||||
_.forEach(nodeToBeDeleted.children, function(child) {
|
|
||||||
if(nodeToBeDeleted.isRoot) {
|
|
||||||
child.isRoot = true;
|
|
||||||
child.edgeType = "always";
|
|
||||||
}
|
|
||||||
child.parent = parentNode;
|
|
||||||
parentNode.children.push(child);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_.forEach(parentNode.children, function(child, index) {
|
|
||||||
if(child.id === params.nodeToBeDeleted.id) {
|
|
||||||
parentNode.children.splice(index, 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addPlaceholderNode: function(params) {
|
|
||||||
// params.parent
|
|
||||||
// params.betweenTwoNodes
|
|
||||||
// params.tree
|
|
||||||
// params.id
|
|
||||||
|
|
||||||
let placeholder = {
|
|
||||||
children: [],
|
|
||||||
c: "#D7D7D7",
|
|
||||||
id: params.id,
|
|
||||||
canDelete: true,
|
|
||||||
canEdit: false,
|
|
||||||
canAddTo: true,
|
|
||||||
placeholder: true,
|
|
||||||
isNew: true,
|
|
||||||
edited: false,
|
|
||||||
isRoot: (params.betweenTwoNodes) ? _.get(params, 'parent.source.isStartNode', false) : _.get(params, 'parent.isStartNode', false)
|
|
||||||
};
|
|
||||||
|
|
||||||
let parentNode = (params.betweenTwoNodes) ? this.searchTree({element: params.tree, matchingId: params.parent.source.id}) : this.searchTree({element: params.tree, matchingId: params.parent.id});
|
|
||||||
let placeholderRef;
|
|
||||||
|
|
||||||
if (params.betweenTwoNodes) {
|
|
||||||
_.forEach(parentNode.children, function(child, index) {
|
|
||||||
if (child.id === params.parent.target.id) {
|
|
||||||
child.isRoot = false;
|
|
||||||
placeholder.children.push(child);
|
|
||||||
parentNode.children[index] = placeholder;
|
|
||||||
placeholderRef = parentNode.children[index];
|
|
||||||
child.parent = parentNode.children[index];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (parentNode.children) {
|
|
||||||
parentNode.children.push(placeholder);
|
|
||||||
placeholderRef = parentNode.children[parentNode.children.length - 1];
|
|
||||||
} else {
|
|
||||||
parentNode.children = [placeholder];
|
|
||||||
placeholderRef = parentNode.children[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return placeholderRef;
|
|
||||||
},
|
|
||||||
getSiblingConnectionTypes: function(params) {
|
|
||||||
// params.parentId
|
|
||||||
// params.childId
|
|
||||||
// params.tree
|
|
||||||
|
|
||||||
let siblingConnectionTypes = {};
|
|
||||||
|
|
||||||
let parentNode = this.searchTree({
|
|
||||||
element: params.tree,
|
|
||||||
matchingId: params.parentId
|
|
||||||
});
|
|
||||||
|
|
||||||
if(parentNode.children && parentNode.children.length > 0) {
|
|
||||||
// Loop across them and add the types as keys to siblingConnectionTypes
|
|
||||||
_.forEach(parentNode.children, function(child) {
|
|
||||||
if(child.id !== params.childId && !child.placeholder && child.edgeType) {
|
|
||||||
siblingConnectionTypes[child.edgeType] = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.keys(siblingConnectionTypes);
|
|
||||||
},
|
|
||||||
buildTree: function(params) {
|
|
||||||
//params.workflowNodes
|
|
||||||
|
|
||||||
let deferred = $q.defer();
|
|
||||||
|
|
||||||
let _this = this;
|
|
||||||
|
|
||||||
let treeData = {
|
|
||||||
data: {
|
|
||||||
id: 1,
|
|
||||||
canDelete: false,
|
|
||||||
canEdit: false,
|
|
||||||
canAddTo: true,
|
|
||||||
isStartNode: true,
|
|
||||||
unifiedJobTemplate: {
|
|
||||||
name: "Workflow Launch"
|
|
||||||
},
|
|
||||||
children: [],
|
|
||||||
deletedNodes: [],
|
|
||||||
totalNodes: 0
|
|
||||||
},
|
|
||||||
nextIndex: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
let nodesArray = params.workflowNodes;
|
|
||||||
let nodesObj = {};
|
|
||||||
let nonRootNodeIds = [];
|
|
||||||
let allNodeIds = [];
|
|
||||||
|
|
||||||
// Determine which nodes are root nodes
|
|
||||||
_.forEach(nodesArray, function(node) {
|
|
||||||
nodesObj[node.id] = _.clone(node);
|
|
||||||
|
|
||||||
allNodeIds.push(node.id);
|
|
||||||
|
|
||||||
_.forEach(node.success_nodes, function(nodeId){
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
_.forEach(node.failure_nodes, function(nodeId){
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
_.forEach(node.always_nodes, function(nodeId){
|
|
||||||
nonRootNodeIds.push(nodeId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let rootNodes = _.difference(allNodeIds, nonRootNodeIds);
|
|
||||||
|
|
||||||
// Loop across the root nodes and re-build the tree
|
|
||||||
_.forEach(rootNodes, function(rootNodeId) {
|
|
||||||
let branch = _this.buildBranch({
|
|
||||||
nodeId: rootNodeId,
|
|
||||||
edgeType: "always",
|
|
||||||
nodesObj: nodesObj,
|
|
||||||
isRoot: true,
|
|
||||||
treeData: treeData
|
|
||||||
});
|
|
||||||
|
|
||||||
treeData.data.children.push(branch);
|
|
||||||
});
|
|
||||||
|
|
||||||
deferred.resolve(treeData);
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
},
|
|
||||||
buildBranch: function(params) {
|
|
||||||
// params.nodeId
|
|
||||||
// params.parentId
|
|
||||||
// params.edgeType
|
|
||||||
// params.nodesObj
|
|
||||||
// params.isRoot
|
|
||||||
// params.treeData
|
|
||||||
|
|
||||||
let _this = this;
|
|
||||||
|
|
||||||
let treeNode = {
|
|
||||||
children: [],
|
|
||||||
c: "#D7D7D7",
|
|
||||||
id: params.treeData.nextIndex,
|
|
||||||
nodeId: params.nodeId,
|
|
||||||
canDelete: true,
|
|
||||||
canEdit: true,
|
|
||||||
canAddTo: true,
|
|
||||||
placeholder: false,
|
|
||||||
edgeType: params.edgeType,
|
|
||||||
isNew: false,
|
|
||||||
edited: false,
|
|
||||||
originalEdge: params.edgeType,
|
|
||||||
originalNodeObj: _.clone(params.nodesObj[params.nodeId]),
|
|
||||||
promptValues: {},
|
|
||||||
isRoot: params.isRoot ? params.isRoot : false
|
|
||||||
};
|
|
||||||
|
|
||||||
params.treeData.data.totalNodes++;
|
|
||||||
|
|
||||||
params.treeData.nextIndex++;
|
|
||||||
|
|
||||||
if(params.parentId) {
|
|
||||||
treeNode.originalParentId = params.parentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(params.nodesObj[params.nodeId].summary_fields) {
|
|
||||||
if(params.nodesObj[params.nodeId].summary_fields.job) {
|
|
||||||
treeNode.job = _.clone(params.nodesObj[params.nodeId].summary_fields.job);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(params.nodesObj[params.nodeId].summary_fields.unified_job_template) {
|
|
||||||
treeNode.unifiedJobTemplate = _.clone(params.nodesObj[params.nodeId].summary_fields.unified_job_template);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop across the success nodes and add them recursively
|
|
||||||
_.forEach(params.nodesObj[params.nodeId].success_nodes, function(successNodeId) {
|
|
||||||
treeNode.children.push(_this.buildBranch({
|
|
||||||
nodeId: successNodeId,
|
|
||||||
parentId: params.nodeId,
|
|
||||||
edgeType: "success",
|
|
||||||
nodesObj: params.nodesObj,
|
|
||||||
treeData: params.treeData
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
// failure nodes
|
|
||||||
_.forEach(params.nodesObj[params.nodeId].failure_nodes, function(failureNodesId) {
|
|
||||||
treeNode.children.push(_this.buildBranch({
|
|
||||||
nodeId: failureNodesId,
|
|
||||||
parentId: params.nodeId,
|
|
||||||
edgeType: "failure",
|
|
||||||
nodesObj: params.nodesObj,
|
|
||||||
treeData: params.treeData
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
// always nodes
|
|
||||||
_.forEach(params.nodesObj[params.nodeId].always_nodes, function(alwaysNodesId) {
|
|
||||||
treeNode.children.push(_this.buildBranch({
|
|
||||||
nodeId: alwaysNodesId,
|
|
||||||
parentId: params.nodeId,
|
|
||||||
edgeType: "always",
|
|
||||||
nodesObj: params.nodesObj,
|
|
||||||
treeData: params.treeData
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
return treeNode;
|
|
||||||
},
|
|
||||||
updateStatusOfNode: function(params) {
|
|
||||||
// params.treeData
|
|
||||||
// params.nodeId
|
|
||||||
// params.status
|
|
||||||
|
|
||||||
let matchingNode = this.searchTree({
|
|
||||||
element: params.treeData.data,
|
|
||||||
matchingId: params.nodeId,
|
|
||||||
byNodeId: true
|
|
||||||
});
|
|
||||||
|
|
||||||
if(matchingNode) {
|
|
||||||
matchingNode.job = {
|
|
||||||
status: params.status,
|
|
||||||
id: params.unified_job_id
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}];
|
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
||||||
'jobLabels', 'workflowNodes', '$scope', 'ParseTypeChange',
|
'jobLabels', 'workflowNodes', '$scope', 'ParseTypeChange',
|
||||||
'ParseVariableString', 'WorkflowService', 'count', '$state', 'i18n',
|
'ParseVariableString', 'count', '$state', 'i18n',
|
||||||
'moment', '$filter', function(workflowData, workflowResultsService,
|
'moment', function(workflowData, workflowResultsService,
|
||||||
workflowDataOptions, jobLabels, workflowNodes, $scope, ParseTypeChange,
|
workflowDataOptions, jobLabels, workflowNodes, $scope, ParseTypeChange,
|
||||||
ParseVariableString, WorkflowService, count, $state, i18n, moment, $filter) {
|
ParseVariableString, count, $state, i18n, moment) {
|
||||||
var runTimeElapsedTimer = null;
|
var runTimeElapsedTimer = null;
|
||||||
|
let workflowMakerNodeIdCounter = 1;
|
||||||
|
let nodeIdToMakerIdMapping = {};
|
||||||
|
let chartNodeIdToIndexMapping = {};
|
||||||
|
|
||||||
var getLinks = function() {
|
var getLinks = function() {
|
||||||
var getLink = function(key) {
|
var getLink = function(key) {
|
||||||
@@ -104,11 +107,8 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
|||||||
$scope.workflow_nodes = workflowNodes;
|
$scope.workflow_nodes = workflowNodes;
|
||||||
$scope.workflowOptions = workflowDataOptions.actions.GET;
|
$scope.workflowOptions = workflowDataOptions.actions.GET;
|
||||||
$scope.labels = jobLabels;
|
$scope.labels = jobLabels;
|
||||||
$scope.count = count.val;
|
|
||||||
$scope.showManualControls = false;
|
$scope.showManualControls = false;
|
||||||
$scope.showKey = false;
|
$scope.readOnly = true;
|
||||||
$scope.toggleKey = () => $scope.showKey = !$scope.showKey;
|
|
||||||
$scope.keyClassList = `{ 'Key-menuIcon--active': showKey }`;
|
|
||||||
|
|
||||||
// Start elapsed time updater for job known to be running
|
// Start elapsed time updater for job known to be running
|
||||||
if ($scope.workflow.started !== null && $scope.workflow.status === 'running') {
|
if ($scope.workflow.started !== null && $scope.workflow.status === 'running') {
|
||||||
@@ -158,25 +158,96 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
|||||||
$scope.varsTooltip= i18n._('Read only view of extra variables added to the workflow.');
|
$scope.varsTooltip= i18n._('Read only view of extra variables added to the workflow.');
|
||||||
$scope.varsLabel = i18n._('Extra Variables');
|
$scope.varsLabel = i18n._('Extra Variables');
|
||||||
|
|
||||||
|
|
||||||
// Click binding for the expand/collapse button on the standard out log
|
// Click binding for the expand/collapse button on the standard out log
|
||||||
$scope.stdoutFullScreen = false;
|
$scope.stdoutFullScreen = false;
|
||||||
|
|
||||||
WorkflowService.buildTree({
|
let nonRootNodeIds = [];
|
||||||
workflowNodes: workflowNodes
|
let allNodeIds = [];
|
||||||
}).then(function(data){
|
let arrayOfLinksForChart = [];
|
||||||
$scope.treeData = data;
|
let arrayOfNodesForChart = [
|
||||||
|
{
|
||||||
// TODO: I think that the workflow chart directive (and eventually d3) is meddling with
|
index: 0,
|
||||||
// this treeData object and removing the children object for some reason (?)
|
id: workflowMakerNodeIdCounter,
|
||||||
// This happens on occasion and I think is a race condition (?)
|
isStartNode: true,
|
||||||
if(!$scope.treeData.data.children) {
|
unifiedJobTemplate: {
|
||||||
$scope.treeData.data.children = [];
|
name: "START"
|
||||||
|
},
|
||||||
|
fixed: true,
|
||||||
|
x: 0,
|
||||||
|
y: 0
|
||||||
}
|
}
|
||||||
|
];
|
||||||
|
|
||||||
$scope.canAddWorkflowJobTemplate = false;
|
workflowMakerNodeIdCounter++;
|
||||||
|
// Assign each node an ID - 0 is reserved for the start node. We need to
|
||||||
|
// make sure that we have an ID on every node including new nodes so the
|
||||||
|
// ID returned by the api won't do
|
||||||
|
workflowNodes.forEach((node) => {
|
||||||
|
node.workflowMakerNodeId = workflowMakerNodeIdCounter;
|
||||||
|
const nodeObj = {
|
||||||
|
index: workflowMakerNodeIdCounter-1,
|
||||||
|
id: workflowMakerNodeIdCounter,
|
||||||
|
unifiedJobTemplate: node.summary_fields.unified_job_template
|
||||||
|
};
|
||||||
|
if(node.summary_fields.job) {
|
||||||
|
nodeObj.job = node.summary_fields.job;
|
||||||
|
}
|
||||||
|
if(node.summary_fields.unified_job_template) {
|
||||||
|
nodeObj.unifiedJobTemplate = node.summary_fields.unified_job_template;
|
||||||
|
}
|
||||||
|
arrayOfNodesForChart.push(nodeObj);
|
||||||
|
allNodeIds.push(node.id);
|
||||||
|
nodeIdToMakerIdMapping[node.id] = node.workflowMakerNodeId;
|
||||||
|
chartNodeIdToIndexMapping[workflowMakerNodeIdCounter] = workflowMakerNodeIdCounter-1;
|
||||||
|
workflowMakerNodeIdCounter++;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
workflowNodes.forEach((node) => {
|
||||||
|
const sourceIndex = chartNodeIdToIndexMapping[node.workflowMakerNodeId];
|
||||||
|
node.success_nodes.forEach((nodeId) => {
|
||||||
|
const targetIndex = chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[nodeId]];
|
||||||
|
arrayOfLinksForChart.push({
|
||||||
|
source: arrayOfNodesForChart[sourceIndex],
|
||||||
|
target: arrayOfNodesForChart[targetIndex],
|
||||||
|
edgeType: "success"
|
||||||
|
});
|
||||||
|
nonRootNodeIds.push(nodeId);
|
||||||
|
});
|
||||||
|
node.failure_nodes.forEach((nodeId) => {
|
||||||
|
const targetIndex = chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[nodeId]];
|
||||||
|
arrayOfLinksForChart.push({
|
||||||
|
source: arrayOfNodesForChart[sourceIndex],
|
||||||
|
target: arrayOfNodesForChart[targetIndex],
|
||||||
|
edgeType: "failure"
|
||||||
|
});
|
||||||
|
nonRootNodeIds.push(nodeId);
|
||||||
|
});
|
||||||
|
node.always_nodes.forEach((nodeId) => {
|
||||||
|
const targetIndex = chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[nodeId]];
|
||||||
|
arrayOfLinksForChart.push({
|
||||||
|
source: arrayOfNodesForChart[sourceIndex],
|
||||||
|
target: arrayOfNodesForChart[targetIndex],
|
||||||
|
edgeType: "always"
|
||||||
|
});
|
||||||
|
nonRootNodeIds.push(nodeId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let uniqueNonRootNodeIds = Array.from(new Set(nonRootNodeIds));
|
||||||
|
|
||||||
|
let rootNodes = _.difference(allNodeIds, uniqueNonRootNodeIds);
|
||||||
|
|
||||||
|
rootNodes.forEach((rootNodeId) => {
|
||||||
|
const targetIndex = chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[rootNodeId]];
|
||||||
|
arrayOfLinksForChart.push({
|
||||||
|
source: arrayOfNodesForChart[0],
|
||||||
|
target: arrayOfNodesForChart[targetIndex],
|
||||||
|
edgeType: "always"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.treeState = { arrayOfNodesForChart, arrayOfLinksForChart };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.toggleStdoutFullscreen = function() {
|
$scope.toggleStdoutFullscreen = function() {
|
||||||
@@ -276,12 +347,11 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
|||||||
runTimeElapsedTimer = workflowResultsService.createOneSecondTimer(moment(), updateWorkflowJobElapsedTimer);
|
runTimeElapsedTimer = workflowResultsService.createOneSecondTimer(moment(), updateWorkflowJobElapsedTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkflowService.updateStatusOfNode({
|
$scope.treeState.arrayOfNodesForChart[chartNodeIdToIndexMapping[nodeIdToMakerIdMapping[data.workflow_node_id]]].job = {
|
||||||
treeData: $scope.treeData,
|
id: data.unified_job_id,
|
||||||
nodeId: data.workflow_node_id,
|
status: data.status
|
||||||
status: data.status,
|
};
|
||||||
unified_job_id: data.unified_job_id
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.workflow_nodes.forEach(node => {
|
$scope.workflow_nodes.forEach(node => {
|
||||||
if(parseInt(node.id) === parseInt(data.workflow_node_id)){
|
if(parseInt(node.id) === parseInt(data.workflow_node_id)){
|
||||||
@@ -291,8 +361,6 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.count = workflowResultsService
|
|
||||||
.getCounts($scope.workflow_nodes);
|
|
||||||
$scope.$broadcast("refreshWorkflowChart");
|
$scope.$broadcast("refreshWorkflowChart");
|
||||||
}
|
}
|
||||||
getLabelsAndTooltips();
|
getLabelsAndTooltips();
|
||||||
|
|||||||
@@ -348,7 +348,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<workflow-chart tree-data="treeData.data" workflow-zoomed="workflowZoomed(zoom)" can-add-workflow-job-template="canAddWorkflowJobTemplate" mode="details" class="WorkflowMaker-chart"></workflow-chart>
|
<workflow-chart
|
||||||
|
tree-state="treeState"
|
||||||
|
workflow-zoomed="workflowZoomed(zoom)"
|
||||||
|
can-add-workflow-job-template="canAddWorkflowJobTemplate"
|
||||||
|
mode="details"
|
||||||
|
read-only="readOnly"
|
||||||
|
class="WorkflowMaker-chart">
|
||||||
|
</workflow-chart>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user