mirror of
https://github.com/ansible/awx.git
synced 2026-03-16 00:17:29 -02:30
Fix some styling discrepancies between Chrome and Firefox in the workflow viz/output graphs.
Cleans up deleted job/job template use cases. Show message indicating that the ujt associated with a node has been deleted.
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React from 'react';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t, Trans } from '@lingui/macro';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import { ExclamationTriangleIcon } from '@patternfly/react-icons';
|
||||||
import { shape } from 'prop-types';
|
import { shape } from 'prop-types';
|
||||||
import { secondsToHHMMSS } from '@util/dates';
|
import { secondsToHHMMSS } from '@util/dates';
|
||||||
|
|
||||||
@@ -18,11 +19,23 @@ const GridDL = styled.dl`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const ResourceDeleted = styled.p`
|
||||||
|
margin-bottom: ${props => (props.job ? '10px' : '0px')};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledExclamationTriangleIcon = styled(ExclamationTriangleIcon)`
|
||||||
|
color: #f0ad4d;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
width: 20px;
|
||||||
|
`;
|
||||||
|
|
||||||
function WorkflowNodeHelp({ node, i18n }) {
|
function WorkflowNodeHelp({ node, i18n }) {
|
||||||
let nodeType;
|
let nodeType;
|
||||||
if (node.unifiedJobTemplate) {
|
if (node.unifiedJobTemplate || node.job) {
|
||||||
const type =
|
const type = node.unifiedJobTemplate
|
||||||
node.unifiedJobTemplate.unified_job_type || node.unifiedJobTemplate.type;
|
? node.unifiedJobTemplate.unified_job_type || node.unifiedJobTemplate.type
|
||||||
|
: node.job.type;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'job_template':
|
case 'job_template':
|
||||||
case 'job':
|
case 'job':
|
||||||
@@ -97,43 +110,59 @@ function WorkflowNodeHelp({ node, i18n }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<>
|
||||||
<GridDL>
|
{!node.unifiedJobTemplate && (
|
||||||
{node.unifiedJobTemplate && (
|
<>
|
||||||
<Fragment>
|
<ResourceDeleted job={node.job}>
|
||||||
<dt>
|
<StyledExclamationTriangleIcon />
|
||||||
<b>{i18n._(t`Name`)}</b>
|
<Trans>
|
||||||
</dt>
|
The resource associated with this node has been deleted.
|
||||||
<dd id="workflow-node-help-name">{node.unifiedJobTemplate.name}</dd>
|
</Trans>
|
||||||
<dt>
|
</ResourceDeleted>
|
||||||
<b>{i18n._(t`Type`)}</b>
|
</>
|
||||||
</dt>
|
)}
|
||||||
<dd id="workflow-node-help-type">{nodeType}</dd>
|
{node.job && (
|
||||||
</Fragment>
|
<GridDL>
|
||||||
)}
|
<dt>
|
||||||
{node.job && (
|
<b>{i18n._(t`Name`)}</b>
|
||||||
<Fragment>
|
</dt>
|
||||||
<dt>
|
<dd id="workflow-node-help-name">{node.job.name}</dd>
|
||||||
<b>{i18n._(t`Job Status`)}</b>
|
<dt>
|
||||||
</dt>
|
<b>{i18n._(t`Type`)}</b>
|
||||||
<dd id="workflow-node-help-status">{jobStatus}</dd>
|
</dt>
|
||||||
{node.job.elapsed && (
|
<dd id="workflow-node-help-type">{nodeType}</dd>
|
||||||
<Fragment>
|
<dt>
|
||||||
<dt>
|
<b>{i18n._(t`Job Status`)}</b>
|
||||||
<b>{i18n._(t`Elapsed`)}</b>
|
</dt>
|
||||||
</dt>
|
<dd id="workflow-node-help-status">{jobStatus}</dd>
|
||||||
<dd id="workflow-node-help-elapsed">
|
{node.job.elapsed && (
|
||||||
{secondsToHHMMSS(node.job.elapsed)}
|
<>
|
||||||
</dd>
|
<dt>
|
||||||
</Fragment>
|
<b>{i18n._(t`Elapsed`)}</b>
|
||||||
)}
|
</dt>
|
||||||
</Fragment>
|
<dd id="workflow-node-help-elapsed">
|
||||||
)}
|
{secondsToHHMMSS(node.job.elapsed)}
|
||||||
</GridDL>
|
</dd>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</GridDL>
|
||||||
|
)}
|
||||||
|
{node.unifiedJobTemplate && !node.job && (
|
||||||
|
<GridDL>
|
||||||
|
<dt>
|
||||||
|
<b>{i18n._(t`Name`)}</b>
|
||||||
|
</dt>
|
||||||
|
<dd id="workflow-node-help-name">{node.unifiedJobTemplate.name}</dd>
|
||||||
|
<dt>
|
||||||
|
<b>{i18n._(t`Type`)}</b>
|
||||||
|
</dt>
|
||||||
|
<dd id="workflow-node-help-type">{nodeType}</dd>
|
||||||
|
</GridDL>
|
||||||
|
)}
|
||||||
{node.job && (
|
{node.job && (
|
||||||
<p css="margin-top: 10px">{i18n._(t`Click to view job details`)}</p>
|
<p css="margin-top: 10px">{i18n._(t`Click to view job details`)}</p>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ describe('WorkflowNodeHelp', () => {
|
|||||||
test('renders the expected content for a completed job template job', () => {
|
test('renders the expected content for a completed job template job', () => {
|
||||||
const node = {
|
const node = {
|
||||||
job: {
|
job: {
|
||||||
|
name: 'Foo Job Template',
|
||||||
elapsed: 9000,
|
elapsed: 9000,
|
||||||
status: 'successful',
|
status: 'successful',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,13 +3,15 @@ import styled from 'styled-components';
|
|||||||
import { shape } from 'prop-types';
|
import { shape } from 'prop-types';
|
||||||
import { PauseIcon } from '@patternfly/react-icons';
|
import { PauseIcon } from '@patternfly/react-icons';
|
||||||
|
|
||||||
const NodeTypeLetter = styled.foreignObject`
|
const NodeTypeLetter = styled.div`
|
||||||
background-color: #393f43;
|
background-color: #393f43;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const CenteredPauseIcon = styled(PauseIcon)`
|
const CenteredPauseIcon = styled(PauseIcon)`
|
||||||
@@ -19,11 +21,14 @@ const CenteredPauseIcon = styled(PauseIcon)`
|
|||||||
function WorkflowNodeTypeLetter({ node }) {
|
function WorkflowNodeTypeLetter({ node }) {
|
||||||
let nodeTypeLetter;
|
let nodeTypeLetter;
|
||||||
if (
|
if (
|
||||||
node.unifiedJobTemplate &&
|
(node.unifiedJobTemplate &&
|
||||||
(node.unifiedJobTemplate.type || node.unifiedJobTemplate.unified_job_type)
|
(node.unifiedJobTemplate.type ||
|
||||||
|
node.unifiedJobTemplate.unified_job_type)) ||
|
||||||
|
(node.job && node.job.type)
|
||||||
) {
|
) {
|
||||||
const ujtType =
|
const ujtType = node.unifiedJobTemplate
|
||||||
node.unifiedJobTemplate.type || node.unifiedJobTemplate.unified_job_type;
|
? node.unifiedJobTemplate.type || node.unifiedJobTemplate.unified_job_type
|
||||||
|
: node.job.type;
|
||||||
switch (ujtType) {
|
switch (ujtType) {
|
||||||
case 'job_template':
|
case 'job_template':
|
||||||
case 'job':
|
case 'job':
|
||||||
@@ -51,9 +56,9 @@ function WorkflowNodeTypeLetter({ node }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeTypeLetter y="50" x="-10" height="20" width="20">
|
<foreignObject y="50" x="-10" height="20" width="20">
|
||||||
{nodeTypeLetter}
|
<NodeTypeLetter>{nodeTypeLetter}</NodeTypeLetter>
|
||||||
</NodeTypeLetter>
|
</foreignObject>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const Elapsed = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const NodeContents = styled.foreignObject`
|
const NodeContents = styled.div`
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
padding: 0px 10px;
|
padding: 0px 10px;
|
||||||
`;
|
`;
|
||||||
@@ -98,29 +98,28 @@ function WorkflowOutputNode({ history, i18n, mouseEnter, mouseLeave, node }) {
|
|||||||
strokeWidth="2px"
|
strokeWidth="2px"
|
||||||
width={wfConstants.nodeW}
|
width={wfConstants.nodeW}
|
||||||
/>
|
/>
|
||||||
<NodeContents height="60" width="180">
|
<foreignObject height="58" width="178" x="1" y="1">
|
||||||
{node.job ? (
|
<NodeContents>
|
||||||
<>
|
{node.job ? (
|
||||||
<JobTopLine>
|
<>
|
||||||
<StatusIcon status={node.job.status} />
|
<JobTopLine>
|
||||||
<p>
|
<StatusIcon status={node.job.status} />
|
||||||
{node.unifiedJobTemplate
|
<p>{node.job.name}</p>
|
||||||
? node.unifiedJobTemplate.name
|
</JobTopLine>
|
||||||
: i18n._(t`DELETED`)}
|
<Elapsed>{secondsToHHMMSS(node.job.elapsed)}</Elapsed>
|
||||||
</p>
|
</>
|
||||||
</JobTopLine>
|
) : (
|
||||||
<Elapsed>{secondsToHHMMSS(node.job.elapsed)}</Elapsed>
|
<NodeDefaultLabel>
|
||||||
</>
|
{node.unifiedJobTemplate
|
||||||
) : (
|
? node.unifiedJobTemplate.name
|
||||||
<NodeDefaultLabel>
|
: i18n._(t`DELETED`)}
|
||||||
{node.unifiedJobTemplate
|
</NodeDefaultLabel>
|
||||||
? node.unifiedJobTemplate.name
|
)}
|
||||||
: i18n._(t`DELETED`)}
|
</NodeContents>
|
||||||
</NodeDefaultLabel>
|
</foreignObject>
|
||||||
)}
|
{(node.unifiedJobTemplate || node.job) && (
|
||||||
</NodeContents>
|
<WorkflowNodeTypeLetter node={node} />
|
||||||
<circle cy="60" r="10" fill="#393F43" />
|
)}
|
||||||
{node.unifiedJobTemplate && <WorkflowNodeTypeLetter node={node} />}
|
|
||||||
</NodeG>
|
</NodeG>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const nodeWithoutJT = {
|
|||||||
job: {
|
job: {
|
||||||
elapsed: 7,
|
elapsed: 7,
|
||||||
id: 9000,
|
id: 9000,
|
||||||
name: 'Automation JT',
|
name: 'Automation JT 2',
|
||||||
status: 'successful',
|
status: 'successful',
|
||||||
type: 'job',
|
type: 'job',
|
||||||
},
|
},
|
||||||
@@ -87,7 +87,7 @@ describe('WorkflowOutputNode', () => {
|
|||||||
</WorkflowStateContext.Provider>
|
</WorkflowStateContext.Provider>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
expect(wrapper.contains(<p>DELETED</p>)).toEqual(true);
|
expect(wrapper.contains(<p>Automation JT 2</p>)).toEqual(true);
|
||||||
expect(wrapper.find('WorkflowOutputNode__Elapsed').text()).toBe('00:00:07');
|
expect(wrapper.find('WorkflowOutputNode__Elapsed').text()).toBe('00:00:07');
|
||||||
});
|
});
|
||||||
test('node contents displayed correctly when Job deleted', () => {
|
test('node contents displayed correctly when Job deleted', () => {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const NodeG = styled.g`
|
|||||||
cursor: ${props => (props.job ? 'pointer' : 'default')};
|
cursor: ${props => (props.job ? 'pointer' : 'default')};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const NodeContents = styled.foreignObject`
|
const NodeContents = styled.div`
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
padding: 0px 10px;
|
padding: 0px 10px;
|
||||||
background-color: ${props =>
|
background-color: ${props =>
|
||||||
@@ -183,25 +183,28 @@ function VisualizerNode({
|
|||||||
? '#007ABC'
|
? '#007ABC'
|
||||||
: '#93969A'
|
: '#93969A'
|
||||||
}
|
}
|
||||||
strokeWidth="4px"
|
strokeWidth="2px"
|
||||||
width={wfConstants.nodeW}
|
width={wfConstants.nodeW}
|
||||||
/>
|
/>
|
||||||
<NodeContents
|
<foreignObject
|
||||||
height="60"
|
height="58"
|
||||||
isInvalidLinkTarget={node.isInvalidLinkTarget}
|
|
||||||
{...(!addingLink && {
|
{...(!addingLink && {
|
||||||
onMouseEnter: () => updateNodeHelp(node),
|
onMouseEnter: () => updateNodeHelp(node),
|
||||||
onMouseLeave: () => updateNodeHelp(null),
|
onMouseLeave: () => updateNodeHelp(null),
|
||||||
})}
|
})}
|
||||||
onClick={() => handleNodeClick()}
|
onClick={() => handleNodeClick()}
|
||||||
width="180"
|
width="178"
|
||||||
|
x="1"
|
||||||
|
y="1"
|
||||||
>
|
>
|
||||||
<NodeDefaultLabel>
|
<NodeContents isInvalidLinkTarget={node.isInvalidLinkTarget}>
|
||||||
{node.unifiedJobTemplate
|
<NodeDefaultLabel>
|
||||||
? node.unifiedJobTemplate.name
|
{node.unifiedJobTemplate
|
||||||
: i18n._(t`DELETED`)}
|
? node.unifiedJobTemplate.name
|
||||||
</NodeDefaultLabel>
|
: i18n._(t`DELETED`)}
|
||||||
</NodeContents>
|
</NodeDefaultLabel>
|
||||||
|
</NodeContents>
|
||||||
|
</foreignObject>
|
||||||
{node.unifiedJobTemplate && <WorkflowNodeTypeLetter node={node} />}
|
{node.unifiedJobTemplate && <WorkflowNodeTypeLetter node={node} />}
|
||||||
{hovering && !addingLink && (
|
{hovering && !addingLink && (
|
||||||
<WorkflowActionTooltip
|
<WorkflowActionTooltip
|
||||||
|
|||||||
Reference in New Issue
Block a user