1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-30 22:21:13 +03:00

Various bug fixes and minor ux enhancements

This commit is contained in:
mabashian 2019-08-20 15:53:17 -04:00 committed by Ryan Petrello
parent 5fc3b2c3f5
commit 3fa9497e3c
No known key found for this signature in database
GPG Key ID: F2AA5F2122351777
7 changed files with 136 additions and 109 deletions

View File

@ -150,7 +150,10 @@ function TemplatesStrings (BaseString) {
SAVE_AND_EXIT: t.s('SAVE & EXIT'), SAVE_AND_EXIT: t.s('SAVE & EXIT'),
APPROVAL: t.s('Approval'), APPROVAL: t.s('Approval'),
TIMEOUT_POPOVER: t.s('The amount of time to wait before this approval step is automatically denied. Defaults to 0 for no timeout.'), TIMEOUT_POPOVER: t.s('The amount of time to wait before this approval step is automatically denied. Defaults to 0 for no timeout.'),
TIMED_OUT: t.s('APPROVAL TIMED OUT') TIMED_OUT: t.s('APPROVAL TIMED OUT'),
TIMEOUT: t.s('Timeout'),
APPROVED: t.s('APPROVED'),
DENIED: t.s('DENIED')
}; };
} }

View File

@ -30,13 +30,13 @@
<div class="at-Row-container"> <div class="at-Row-container">
<at-row-item <at-row-item
header-value="{{ approval.summary_fields.source_workflow_job.name }}" header-value="{{ approval.summary_fields.source_workflow_job.name }}"
header-state="workflowResults({pid: {{approval.summary_fields.source_workflow_job.id}}})"> header-state="workflowResults({id: {{approval.summary_fields.source_workflow_job.id}}})">
</at-row-item> </at-row-item>
</div> </div>
</div> </div>
<div class="at-Row-container--wrapped"> <div class="at-Row-container--wrapped">
<at-row-item <at-row-item
value-bind-html="<b>Pause Node</b>"> value-bind-html="<b>{{:: vm.strings.get('approvals.APPROVAL') }}</b>">
</at-row-item> </at-row-item>
<at-row-item <at-row-item
value-bind-html="{{ approval.name }}"> value-bind-html="{{ approval.name }}">

View File

@ -121,6 +121,7 @@ function ComponentsStrings (BaseString) {
}; };
ns.approvals = { ns.approvals = {
APPROVAL: t.s('APPROVAL'),
NONE: t.s('There are no jobs awaiting approval'), NONE: t.s('There are no jobs awaiting approval'),
APPROVE: t.s('APPROVE'), APPROVE: t.s('APPROVE'),
DENY: t.s('DENY'), DENY: t.s('DENY'),

View File

@ -97,7 +97,6 @@
color: @at-white; color: @at-white;
height: 16px; height: 16px;
font-size: 11px; font-size: 11px;
font-weight: bold;
cursor: default; cursor: default;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -170,13 +170,20 @@
text-align: center; text-align: center;
} }
.WorkflowChart-timedOutText { .WorkflowChart-timedOutText, .WorkflowChart-deniedText {
width: 180px; width: 180px;
height: 14px; height: 14px;
color: @default-err; color: @default-err;
text-align: center; text-align: center;
} }
.WorkflowChart-approvedText {
width: 180px;
height: 14px;
color: @default-succ;
text-align: center;
}
.WorkflowChart-tooltip { .WorkflowChart-tooltip {
pointer-events: none; pointer-events: none;
text-align: center; text-align: center;

View File

@ -835,6 +835,12 @@ export default ['moment', '$timeout', '$window', '$filter', 'TemplatesStrings',
baseSvg.selectAll(".WorkflowChart-timedOutText") baseSvg.selectAll(".WorkflowChart-timedOutText")
.style("display", (d) => { return d.job && d.job.timed_out ? null : "none"; }); .style("display", (d) => { return d.job && d.job.timed_out ? null : "none"; });
baseSvg.selectAll(".WorkflowChart-deniedText")
.style("display", (d) => { return d.job && d.job.type === "workflow_approval" && d.job.status === "failed" && !d.job.timed_out ? null : "none"; });
baseSvg.selectAll(".WorkflowChart-approvedText")
.style("display", (d) => { return d.job && d.job.type === "workflow_approval" && d.job.status === "successful" && !d.job.timed_out ? null : "none"; });
baseSvg.selectAll(".WorkflowChart-activeNode") baseSvg.selectAll(".WorkflowChart-activeNode")
.style("display", (d) => { return d.id === scope.graphState.nodeBeingEdited ? null : "none"; }); .style("display", (d) => { return d.id === scope.graphState.nodeBeingEdited ? null : "none"; });
@ -950,7 +956,25 @@ export default ['moment', '$timeout', '$window', '$filter', 'TemplatesStrings',
.attr("text-anchor", "middle") .attr("text-anchor", "middle")
.attr("class", "WorkflowChart-defaultText WorkflowChart-timedOutText") .attr("class", "WorkflowChart-defaultText WorkflowChart-timedOutText")
.html(`<span>${TemplatesStrings.get('workflow_maker.TIMED_OUT')}</span>`) .html(`<span>${TemplatesStrings.get('workflow_maker.TIMED_OUT')}</span>`)
.style("display", (d) => { return d.job && d.job.timed_out ? null : "none"; }); .style("display", (d) => { return d.job && d.job.type === "workflow_approval" && d.job.timed_out ? null : "none"; });
thisNode.append("foreignObject")
.attr("x", 0)
.attr("y", 22)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.attr("class", "WorkflowChart-defaultText WorkflowChart-deniedText")
.html(`<span>${TemplatesStrings.get('workflow_maker.DENIED')}</span>`)
.style("display", (d) => { return d.job && d.job.type === "workflow_approval" && d.job.status === "failed" && !d.job.timed_out ? null : "none"; });
thisNode.append("foreignObject")
.attr("x", 0)
.attr("y", 22)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.attr("class", "WorkflowChart-defaultText WorkflowChart-approvedText")
.html(`<span>${TemplatesStrings.get('workflow_maker.APPROVED')}</span>`)
.style("display", (d) => { return d.job && d.job.type === "workflow_approval" && d.job.status === "successful" && !d.job.timed_out ? null : "none"; });
thisNode.append("circle") thisNode.append("circle")
.attr("cy", nodeH) .attr("cy", nodeH)

View File

@ -159,110 +159,104 @@
<span>{{:: strings.get('workflows.INVALID_JOB_TEMPLATE') }}</span> <span>{{:: strings.get('workflows.INVALID_JOB_TEMPLATE') }}</span>
</div> </div>
</div> </div>
<div ng-if="selectedTemplate && credentialRequiresPassword"> <div ng-if="selectedTemplate && jobNodeState.credentialRequiresPassword">
<div class="WorkflowMaker-invalidJobTemplateWarning"> <div class="WorkflowMaker-invalidJobTemplateWarning">
<span class="fa fa-warning"></span> <span class="fa fa-warning"></span>
<span>{{:: strings.get('workflows.CREDENTIAL_WITH_PASS') }}</span> <span>{{:: strings.get('workflows.CREDENTIAL_WITH_PASS') }}</span>
</div> </div>
<div ng-if="selectedTemplate && jobNodeState.credentialRequiresPassword"> </div>
<div class="WorkflowMaker-invalidJobTemplateWarning"> <div class="form-group Form-formGroup Form-formGroup--singleColumn" ng-show="nodeConfig.mode === 'add'">
<span class="fa fa-warning"></span> <label for="edgeType" class="Form-inputLabelContainer">
<span>{{:: strings.get('workflows.CREDENTIAL_WITH_PASS') }}</span> <span class="Form-requiredAsterisk">*</span>
<span class="Form-inputLabel">{{:: strings.get('workflow_maker.RUN') }}</span>
</label>
<div>
<select
id="workflow_node_edge"
ng-options="v as v.label for v in edgeTypeOptions track by v.value"
ng-model="edgeType"
class="form-control Form-dropDown"
name="edgeType"
tabindex="-1"
ng-disabled="readOnly"
aria-hidden="true">
</select>
</div>
</div>
<div ng-show="readOnly">
<div
class="WorkflowMaker-readOnlyPromptText"
ng-show="nodeConfig.node.originalNodeObject.job_type !== null ||
(jobNodeState.promptData.prompts.credentials.value && jobNodeState.promptData.prompts.credentials.value.length > 0) ||
nodeConfig.node.originalNodeObject.inventory !== null ||
nodeConfig.node.originalNodeObject.limit !== null ||
nodeConfig.node.originalNodeObject.verbosity !== null ||
nodeConfig.node.originalNodeObject.job_tags !== null ||
nodeConfig.node.originalNodeObject.skip_tags !== null ||
nodeConfig.node.originalNodeObject.diff_mode !== null ||
showExtraVars">
{{:: strings.get('workflow_maker.READ_ONLY_PROMPT_VALUES')}}
</div>
<div
class="WorkflowMaker-readOnlyPromptText"
ng-show="!(nodeConfig.node.originalNodeObject.job_type !== null ||
(jobNodeState.promptData.prompts.credentials.value && jobNodeState.promptData.prompts.credentials.value.length > 0) ||
nodeConfig.node.originalNodeObject.inventory !== null ||
nodeConfig.node.originalNodeObject.limit !== null ||
nodeConfig.node.originalNodeObject.verbosity !== null ||
nodeConfig.node.originalNodeObject.job_tags !== null ||
nodeConfig.node.originalNodeObject.skip_tags !== null ||
nodeConfig.node.originalNodeObject.diff_mode !== null ||
showExtraVars)">
{{:: strings.get('workflow_maker.READ_ONLY_NO_PROMPT_VALUES')}}
</div>
<div class="Prompt-previewRow--flex" ng-if="nodeConfig.node.originalNodeObject.job_type !== null">
<div class="Prompt-previewRowTitle">{{:: strings.get('prompt.JOB_TYPE') }}</div>
<div class="Prompt-previewRowValue">
<span ng-if="nodeConfig.node.originalNodeObject.job_type === 'run'">{{:: strings.get('prompt.PLAYBOOK_RUN') }}</span>
<span ng-if="nodeConfig.node.originalNodeObject.job_type === 'check'">{{:: strings.get('prompt.CHECK') }}</span>
</div> </div>
</div> </div>
<div class="form-group Form-formGroup Form-formGroup--singleColumn" ng-show="nodeConfig.mode === 'add'"> <div class="Prompt-previewRow--flex" ng-if="nodeConfig.node.originalNodeObject.inventory !== null">
<label for="edgeType" class="Form-inputLabelContainer"> <div class="Prompt-previewRowTitle">{{:: strings.get('prompt.INVENTORY') }}</div>
<span class="Form-requiredAsterisk">*</span> <div class="Prompt-previewRowValue" ng-bind="nodeConfig.node.originalNodeObject.summary_fields.inventory.name"></div>
<span class="Form-inputLabel">{{:: strings.get('workflow_maker.RUN') }}</span>
</label>
<div>
<select
id="workflow_node_edge"
ng-options="v as v.label for v in edgeTypeOptions track by v.value"
ng-model="edgeType"
class="form-control Form-dropDown"
name="edgeType"
tabindex="-1"
ng-disabled="readOnly"
aria-hidden="true">
</select>
</div>
</div> </div>
<div ng-show="readOnly"> <div class="Prompt-previewRow--flex" ng-if="nodeConfig.node.originalNodeObject.limit !== null">
<div <div class="Prompt-previewRowTitle">{{:: strings.get('prompt.LIMIT') }}</div>
class="WorkflowMaker-readOnlyPromptText" <div class="Prompt-previewRowValue" ng-bind="nodeConfig.node.originalNodeObject.limit"></div>
ng-show="nodeConfig.node.originalNodeObject.job_type !== null || </div>
(jobNodeState.promptData.prompts.credentials.value && jobNodeState.promptData.prompts.credentials.value.length > 0) || <div class="Prompt-previewRow--flex" ng-if="nodeConfig.node.originalNodeObject.verbosity !== null">
nodeConfig.node.originalNodeObject.inventory !== null || <div class="Prompt-previewRowTitle">{{:: strings.get('prompt.VERBOSITY') }}</div>
nodeConfig.node.originalNodeObject.limit !== null || <div class="Prompt-previewRowValue" ng-bind="nodeConfig.node.originalNodeObject.verbosity"></div>
nodeConfig.node.originalNodeObject.verbosity !== null || </div>
nodeConfig.node.originalNodeObject.job_tags !== null || <div class="Prompt-previewRow--noflex" ng-if="nodeConfig.node.originalNodeObject.job_tags !== null">
nodeConfig.node.originalNodeObject.skip_tags !== null || <div class="Prompt-previewRowTitle">
nodeConfig.node.originalNodeObject.diff_mode !== null || <span>{{:: strings.get('prompt.JOB_TAGS') }}&nbsp;</span>
showExtraVars"> <span ng-click="showJobTags = !showJobTags">
{{:: strings.get('workflow_maker.READ_ONLY_PROMPT_VALUES')}} <span class="fa fa-caret-down" ng-show="showJobTags" ></span>
<span class="fa fa-caret-left" ng-show="!showJobTags"></span>
</span>
</div> </div>
<div <div ng-show="showJobTags" class="Prompt-previewTagContainer">
class="WorkflowMaker-readOnlyPromptText" <div class="u-wordwrap" ng-repeat="tag in jobTags">
ng-show="!(nodeConfig.node.originalNodeObject.job_type !== null || <div class="LabelList-tag">
(jobNodeState.promptData.prompts.credentials.value && jobNodeState.promptData.prompts.credentials.value.length > 0) || <span>{{tag}}</span>
nodeConfig.node.originalNodeObject.inventory !== null ||
nodeConfig.node.originalNodeObject.limit !== null ||
nodeConfig.node.originalNodeObject.verbosity !== null ||
nodeConfig.node.originalNodeObject.job_tags !== null ||
nodeConfig.node.originalNodeObject.skip_tags !== null ||
nodeConfig.node.originalNodeObject.diff_mode !== null ||
showExtraVars)">
{{:: strings.get('workflow_maker.READ_ONLY_NO_PROMPT_VALUES')}}
</div>
<div class="Prompt-previewRow--flex" ng-if="nodeConfig.node.originalNodeObject.job_type !== null">
<div class="Prompt-previewRowTitle">{{:: strings.get('prompt.JOB_TYPE') }}</div>
<div class="Prompt-previewRowValue">
<span ng-if="nodeConfig.node.originalNodeObject.job_type === 'run'">{{:: strings.get('prompt.PLAYBOOK_RUN') }}</span>
<span ng-if="nodeConfig.node.originalNodeObject.job_type === 'check'">{{:: strings.get('prompt.CHECK') }}</span>
</div>
</div>
<div class="Prompt-previewRow--flex" ng-if="nodeConfig.node.originalNodeObject.inventory !== null">
<div class="Prompt-previewRowTitle">{{:: strings.get('prompt.INVENTORY') }}</div>
<div class="Prompt-previewRowValue" ng-bind="nodeConfig.node.originalNodeObject.summary_fields.inventory.name"></div>
</div>
<div class="Prompt-previewRow--flex" ng-if="nodeConfig.node.originalNodeObject.limit !== null">
<div class="Prompt-previewRowTitle">{{:: strings.get('prompt.LIMIT') }}</div>
<div class="Prompt-previewRowValue" ng-bind="nodeConfig.node.originalNodeObject.limit"></div>
</div>
<div class="Prompt-previewRow--flex" ng-if="nodeConfig.node.originalNodeObject.verbosity !== null">
<div class="Prompt-previewRowTitle">{{:: strings.get('prompt.VERBOSITY') }}</div>
<div class="Prompt-previewRowValue" ng-bind="nodeConfig.node.originalNodeObject.verbosity"></div>
</div>
<div class="Prompt-previewRow--noflex" ng-if="nodeConfig.node.originalNodeObject.job_tags !== null">
<div class="Prompt-previewRowTitle">
<span>{{:: strings.get('prompt.JOB_TAGS') }}&nbsp;</span>
<span ng-click="showJobTags = !showJobTags">
<span class="fa fa-caret-down" ng-show="showJobTags" ></span>
<span class="fa fa-caret-left" ng-show="!showJobTags"></span>
</span>
</div>
<div ng-show="showJobTags" class="Prompt-previewTagContainer">
<div class="u-wordwrap" ng-repeat="tag in jobTags">
<div class="LabelList-tag">
<span>{{tag}}</span>
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="Prompt-previewRow--noflex" ng-if="nodeConfig.node.originalNodeObject.skip_tags !== null"> </div>
<div class="Prompt-previewRowTitle"> <div class="Prompt-previewRow--noflex" ng-if="nodeConfig.node.originalNodeObject.skip_tags !== null">
<span>{{:: strings.get('prompt.SKIP_TAGS') }}&nbsp;</span> <div class="Prompt-previewRowTitle">
<span ng-click="showSkipTags = !showSkipTags"> <span>{{:: strings.get('prompt.SKIP_TAGS') }}&nbsp;</span>
<span class="fa fa-caret-down" ng-show="showSkipTags" ></span> <span ng-click="showSkipTags = !showSkipTags">
<span class="fa fa-caret-left" ng-show="!showSkipTags"></span> <span class="fa fa-caret-down" ng-show="showSkipTags" ></span>
</span> <span class="fa fa-caret-left" ng-show="!showSkipTags"></span>
</div> </span>
<div ng-show="showSkipTags" class="Prompt-previewTagContainer"> </div>
<div class="u-wordwrap" ng-repeat="tag in skipTags"> <div ng-show="showSkipTags" class="Prompt-previewTagContainer">
<div class="LabelList-tag"> <div class="u-wordwrap" ng-repeat="tag in skipTags">
<span>{{tag}}</span> <div class="LabelList-tag">
</div> <span>{{tag}}</span>
</div> </div>
</div> </div>
</div> </div>
@ -283,16 +277,15 @@
<div> <div>
<textarea rows="6" ng-model="extraVars" name="node_form_extra_vars" class="form-control Form-textArea Form-textAreaLabel" id="workflow_node_form_extra_vars"></textarea> <textarea rows="6" ng-model="extraVars" name="node_form_extra_vars" class="form-control Form-textArea Form-textAreaLabel" id="workflow_node_form_extra_vars"></textarea>
</div> </div>
</div>
</div> </div>
<div ng-show="editNodeHelpMessage && activeTab === 'templates'" class="WorkflowMaker-formHelp" ng-bind="editNodeHelpMessage"></div>
<br />
<div class="buttons Form-buttons" id="workflow_maker_controls">
<button type="button" class="btn btn-sm Form-primaryButton Form-primaryButton--noMargin" id="workflow_maker_prompt_btn" ng-show="jobNodeState.showPromptButton && activeTab == 'templates' " ng-click="openPromptModal()"> {{:: strings.get('prompt.PROMPT') }}</button>
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_cancel_node_btn" ng-show="!readOnly" ng-click="cancel()"> {{:: strings.get('CANCEL') }}</button>
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_close_node_btn" ng-show="readOnly" ng-click="cancel()"> {{:: strings.get('CLOSE') }}</button>
<button type="button" class="btn btn-sm Form-saveButton" id="workflow_maker_select_node_btn" ng-show="!readOnly" ng-click="confirmNodeForm()" ng-disabled="selectIsDisabled()"> {{:: strings.get('workflow_maker.SELECT') }}</button>
</div>
<prompt prompt-data="jobNodeState.promptData" action-text="{{:: strings.get('prompt.CONFIRM')}}" prevent-creds-with-passwords="preventCredsWithPasswords" read-only-prompts="readOnly"></prompt>
</div> </div>
<div ng-show="editNodeHelpMessage && activeTab === 'templates'" class="WorkflowMaker-formHelp" ng-bind="editNodeHelpMessage"></div>
<br />
<div class="buttons Form-buttons" id="workflow_maker_controls">
<button type="button" class="btn btn-sm Form-primaryButton Form-primaryButton--noMargin" id="workflow_maker_prompt_btn" ng-show="jobNodeState.showPromptButton && activeTab == 'templates' " ng-click="openPromptModal()"> {{:: strings.get('prompt.PROMPT') }}</button>
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_cancel_node_btn" ng-show="!readOnly" ng-click="cancel()"> {{:: strings.get('CANCEL') }}</button>
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_close_node_btn" ng-show="readOnly" ng-click="cancel()"> {{:: strings.get('CLOSE') }}</button>
<button type="button" class="btn btn-sm Form-saveButton" id="workflow_maker_select_node_btn" ng-show="!readOnly" ng-click="confirmNodeForm()" ng-disabled="selectIsDisabled()"> {{:: strings.get('workflow_maker.SELECT') }}</button>
</div>
<prompt prompt-data="jobNodeState.promptData" action-text="{{:: strings.get('prompt.CONFIRM')}}" prevent-creds-with-passwords="preventCredsWithPasswords" read-only-prompts="readOnly"></prompt>
</div> </div>