diff --git a/awx/ui_next/src/components/Sparkline/HostStatusIcon.jsx b/awx/ui_next/src/components/Sparkline/HostStatusIcon.jsx
deleted file mode 100644
index 5558016bf2..0000000000
--- a/awx/ui_next/src/components/Sparkline/HostStatusIcon.jsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import React from 'react';
-import { string } from 'prop-types';
-import {
- ChangedBottom,
- ChangedTop,
- FailedBottom,
- FailedTop,
- FinishedJob,
- SkippedBottom,
- SkippedTop,
- SuccessfulBottom,
- SuccessfulTop,
- UnreachableBottom,
- UnreachableTop,
-} from './shared/StatusIcon';
-
-const HostStatusIcon = ({ status }) => {
- return (
-
- {status === 'changed' && (
-
-
-
-
- )}
- {status === 'failed' && (
-
-
-
-
- )}
- {status === 'skipped' && (
-
-
-
-
- )}
- {status === 'ok' && (
-
-
-
-
- )}
- {status === 'unreachable' && (
-
-
-
-
- )}
-
- );
-};
-
-HostStatusIcon.propTypes = {
- status: string.isRequired,
-};
-
-export default HostStatusIcon;
diff --git a/awx/ui_next/src/components/Sparkline/HostStatusIcon.test.jsx b/awx/ui_next/src/components/Sparkline/HostStatusIcon.test.jsx
deleted file mode 100644
index 69c2070582..0000000000
--- a/awx/ui_next/src/components/Sparkline/HostStatusIcon.test.jsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react';
-import { mount } from 'enzyme';
-import HostStatusIcon from './HostStatusIcon';
-
-describe('HostStatusIcon', () => {
- test('renders the "ok" host status', () => {
- const wrapper = mount();
- expect(wrapper).toHaveLength(1);
- expect(wrapper.find('StatusIcon__SuccessfulTop')).toHaveLength(1);
- expect(wrapper.find('StatusIcon__SuccessfulBottom')).toHaveLength(1);
- });
- test('renders "failed" host status', () => {
- const wrapper = mount();
- expect(wrapper).toHaveLength(1);
- expect(wrapper.find('StatusIcon__FailedTop')).toHaveLength(1);
- expect(wrapper.find('StatusIcon__FailedBottom')).toHaveLength(1);
- });
- test('renders "changed" host status', () => {
- const wrapper = mount();
- expect(wrapper).toHaveLength(1);
- expect(wrapper.find('StatusIcon__ChangedTop')).toHaveLength(1);
- expect(wrapper.find('StatusIcon__ChangedBottom')).toHaveLength(1);
- });
- test('renders "skipped" host status', () => {
- const wrapper = mount();
- expect(wrapper).toHaveLength(1);
- expect(wrapper.find('StatusIcon__SkippedTop')).toHaveLength(1);
- expect(wrapper.find('StatusIcon__SkippedBottom')).toHaveLength(1);
- });
- test('renders "unreachable" host status', () => {
- const wrapper = mount();
- expect(wrapper).toHaveLength(1);
- expect(wrapper.find('StatusIcon__UnreachableTop')).toHaveLength(1);
- expect(wrapper.find('StatusIcon__UnreachableBottom')).toHaveLength(1);
- });
-});
diff --git a/awx/ui_next/src/components/Sparkline/JobStatusIcon.jsx b/awx/ui_next/src/components/Sparkline/JobStatusIcon.jsx
deleted file mode 100644
index 0167793fa8..0000000000
--- a/awx/ui_next/src/components/Sparkline/JobStatusIcon.jsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import React from 'react';
-import { string } from 'prop-types';
-import {
- RunningJob,
- WaitingJob,
- FinishedJob,
- SuccessfulTop,
- SuccessfulBottom,
- FailedBottom,
- FailedTop,
-} from './shared/StatusIcon';
-
-const JobStatusIcon = ({ status, ...props }) => {
- return (
-
- {status === 'running' && }
- {(status === 'new' || status === 'pending' || status === 'waiting') && (
-
- )}
- {(status === 'failed' || status === 'error' || status === 'canceled') && (
-
-
-
-
- )}
- {status === 'successful' && (
-
-
-
-
- )}
-
- );
-};
-
-JobStatusIcon.propTypes = {
- status: string.isRequired,
-};
-
-export default JobStatusIcon;
diff --git a/awx/ui_next/src/components/Sparkline/JobStatusIcon.test.jsx b/awx/ui_next/src/components/Sparkline/JobStatusIcon.test.jsx
deleted file mode 100644
index 86485223ab..0000000000
--- a/awx/ui_next/src/components/Sparkline/JobStatusIcon.test.jsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react';
-import { mount } from 'enzyme';
-import JobStatusIcon from './JobStatusIcon';
-
-describe('JobStatusIcon', () => {
- test('renders the successful job', () => {
- const wrapper = mount();
- expect(wrapper).toHaveLength(1);
- expect(wrapper.find('StatusIcon__SuccessfulTop')).toHaveLength(1);
- expect(wrapper.find('StatusIcon__SuccessfulBottom')).toHaveLength(1);
- });
- test('renders running job', () => {
- const wrapper = mount();
- expect(wrapper).toHaveLength(1);
- expect(wrapper.find('StatusIcon__RunningJob')).toHaveLength(1);
- });
- test('renders waiting job', () => {
- const wrapper = mount();
- expect(wrapper).toHaveLength(1);
- expect(wrapper.find('StatusIcon__WaitingJob')).toHaveLength(1);
- });
- test('renders failed job', () => {
- const wrapper = mount();
- expect(wrapper).toHaveLength(1);
- expect(wrapper.find('StatusIcon__FailedTop')).toHaveLength(1);
- expect(wrapper.find('StatusIcon__FailedBottom')).toHaveLength(1);
- });
-});
diff --git a/awx/ui_next/src/components/Sparkline/Sparkline.jsx b/awx/ui_next/src/components/Sparkline/Sparkline.jsx
index 5291eeca85..57029ce73a 100644
--- a/awx/ui_next/src/components/Sparkline/Sparkline.jsx
+++ b/awx/ui_next/src/components/Sparkline/Sparkline.jsx
@@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
import { arrayOf, object } from 'prop-types';
import { withI18n } from '@lingui/react';
import { Link as _Link } from 'react-router-dom';
-import { JobStatusIcon } from '@components/Sparkline';
+import { StatusIcon } from '@components/Sparkline';
import { Tooltip } from '@patternfly/react-core';
import styled from 'styled-components';
import { t } from '@lingui/macro';
@@ -34,7 +34,7 @@ const Sparkline = ({ i18n, jobs }) => {
return jobs.map(job => (
-
+
));
diff --git a/awx/ui_next/src/components/Sparkline/Sparkline.test.jsx b/awx/ui_next/src/components/Sparkline/Sparkline.test.jsx
index e39003a841..0d4d5579e9 100644
--- a/awx/ui_next/src/components/Sparkline/Sparkline.test.jsx
+++ b/awx/ui_next/src/components/Sparkline/Sparkline.test.jsx
@@ -23,7 +23,7 @@ describe('Sparkline', () => {
},
];
const wrapper = mountWithContexts();
- expect(wrapper.find('JobStatusIcon')).toHaveLength(2);
+ expect(wrapper.find('StatusIcon')).toHaveLength(2);
expect(wrapper.find('Tooltip')).toHaveLength(2);
expect(wrapper.find('Link')).toHaveLength(2);
});
diff --git a/awx/ui_next/src/components/Sparkline/StatusIcon.jsx b/awx/ui_next/src/components/Sparkline/StatusIcon.jsx
new file mode 100644
index 0000000000..5f048f5cb5
--- /dev/null
+++ b/awx/ui_next/src/components/Sparkline/StatusIcon.jsx
@@ -0,0 +1,121 @@
+import React from 'react';
+import { string } from 'prop-types';
+import styled, { keyframes } from 'styled-components';
+
+const Pulse = keyframes`
+ from {
+ -webkit-transform:scale(1);
+ }
+ to {
+ -webkit-transform:scale(0);
+ }
+`;
+
+const Wrapper = styled.div`
+ width: 14px;
+ height: 14px;
+`;
+
+const WhiteTop = styled.div`
+ border: 1px solid #b7b7b7;
+ border-bottom: 0;
+ background: #ffffff;
+`;
+
+const WhiteBottom = styled.div`
+ border: 1px solid #b7b7b7;
+ border-top: 0;
+ background: #ffffff;
+`;
+
+const RunningJob = styled(Wrapper)`
+ background-color: #5cb85c;
+ padding-right: 0px;
+ text-shadow: -1px -1px 0 #ffffff, 1px -1px 0 #ffffff, -1px 1px 0 #ffffff,
+ 1px 1px 0 #ffffff;
+ animation: ${Pulse} 1.5s linear infinite alternate;
+`;
+
+const WaitingJob = styled(Wrapper)`
+ border: 1px solid #d7d7d7;
+`;
+
+const FinishedJob = styled(Wrapper)`
+ flex: 0 1 auto;
+ > * {
+ width: 14px;
+ height: 7px;
+ }
+`;
+
+const SuccessfulTop = styled.div`
+ background-color: #5cb85c;
+`;
+const SuccessfulBottom = styled(WhiteBottom)``;
+
+const FailedTop = styled(WhiteTop)``;
+const FailedBottom = styled.div`
+ background-color: #d9534f;
+`;
+
+const UnreachableTop = styled(WhiteTop)``;
+const UnreachableBottom = styled.div`
+ background-color: #ff0000;
+`;
+
+const ChangedTop = styled(WhiteTop)``;
+const ChangedBottom = styled.div`
+ background-color: #ff9900;
+`;
+
+const SkippedTop = styled(WhiteTop)``;
+const SkippedBottom = styled.div`
+ background-color: #2dbaba;
+`;
+
+const StatusIcon = ({ status, ...props }) => {
+ return (
+
+ {status === 'running' && }
+ {(status === 'new' || status === 'pending' || status === 'waiting') && (
+
+ )}
+ {(status === 'failed' || status === 'error' || status === 'canceled') && (
+
+
+
+
+ )}
+ {(status === 'successful' || status === 'ok') && (
+
+
+
+
+ )}
+ {status === 'changed' && (
+
+
+
+
+ )}
+ {status === 'skipped' && (
+
+
+
+
+ )}
+ {status === 'unreachable' && (
+
+
+
+
+ )}
+
+ );
+};
+
+StatusIcon.propTypes = {
+ status: string.isRequired,
+};
+
+export default StatusIcon;
diff --git a/awx/ui_next/src/components/Sparkline/StatusIcon.test.jsx b/awx/ui_next/src/components/Sparkline/StatusIcon.test.jsx
new file mode 100644
index 0000000000..fd47a309c8
--- /dev/null
+++ b/awx/ui_next/src/components/Sparkline/StatusIcon.test.jsx
@@ -0,0 +1,59 @@
+import React from 'react';
+import { mount } from 'enzyme';
+import StatusIcon from './StatusIcon';
+
+describe('StatusIcon', () => {
+ test('renders the successful status', () => {
+ const wrapper = mount();
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__SuccessfulTop')).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__SuccessfulBottom')).toHaveLength(1);
+ });
+ test('renders running status', () => {
+ const wrapper = mount();
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__RunningJob')).toHaveLength(1);
+ });
+ test('renders waiting status', () => {
+ const wrapper = mount();
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__WaitingJob')).toHaveLength(1);
+ });
+ test('renders failed status', () => {
+ const wrapper = mount();
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__FailedTop')).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__FailedBottom')).toHaveLength(1);
+ });
+ test('renders a successful status when host status is "ok"', () => {
+ const wrapper = mount();
+ wrapper.debug();
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__SuccessfulTop')).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__SuccessfulBottom')).toHaveLength(1);
+ });
+ test('renders "failed" host status', () => {
+ const wrapper = mount();
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__FailedTop')).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__FailedBottom')).toHaveLength(1);
+ });
+ test('renders "changed" host status', () => {
+ const wrapper = mount();
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__ChangedTop')).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__ChangedBottom')).toHaveLength(1);
+ });
+ test('renders "skipped" host status', () => {
+ const wrapper = mount();
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__SkippedTop')).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__SkippedBottom')).toHaveLength(1);
+ });
+ test('renders "unreachable" host status', () => {
+ const wrapper = mount();
+ expect(wrapper).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__UnreachableTop')).toHaveLength(1);
+ expect(wrapper.find('StatusIcon__UnreachableBottom')).toHaveLength(1);
+ });
+});
diff --git a/awx/ui_next/src/components/Sparkline/index.js b/awx/ui_next/src/components/Sparkline/index.js
index 2b299b651e..f7b30c0d98 100644
--- a/awx/ui_next/src/components/Sparkline/index.js
+++ b/awx/ui_next/src/components/Sparkline/index.js
@@ -1,3 +1,2 @@
export { default as Sparkline } from './Sparkline';
-export { default as JobStatusIcon } from './JobStatusIcon';
-export { default as HostStatusIcon } from './HostStatusIcon';
+export { default as StatusIcon } from './StatusIcon';
diff --git a/awx/ui_next/src/components/Sparkline/shared/StatusIcon.jsx b/awx/ui_next/src/components/Sparkline/shared/StatusIcon.jsx
deleted file mode 100644
index c02af801b1..0000000000
--- a/awx/ui_next/src/components/Sparkline/shared/StatusIcon.jsx
+++ /dev/null
@@ -1,72 +0,0 @@
-import styled, { keyframes } from 'styled-components';
-
-const Pulse = keyframes`
- from {
- -webkit-transform:scale(1);
- }
- to {
- -webkit-transform:scale(0);
- }
-`;
-
-const Wrapper = styled.div`
- width: 14px;
- height: 14px;
-`;
-
-const WhiteTop = styled.div`
- border: 1px solid #b7b7b7;
- border-bottom: 0;
- background: #ffffff;
-`;
-
-const WhiteBottom = styled.div`
- border: 1px solid #b7b7b7;
- border-top: 0;
- background: #ffffff;
-`;
-
-export const RunningJob = styled(Wrapper)`
- background-color: #5cb85c;
- padding-right: 0px;
- text-shadow: -1px -1px 0 #ffffff, 1px -1px 0 #ffffff, -1px 1px 0 #ffffff,
- 1px 1px 0 #ffffff;
- animation: ${Pulse} 1.5s linear infinite alternate;
-`;
-
-export const WaitingJob = styled(Wrapper)`
- border: 1px solid #d7d7d7;
-`;
-
-export const FinishedJob = styled(Wrapper)`
- flex: 0 1 auto;
- > * {
- width: 14px;
- height: 7px;
- }
-`;
-
-export const SuccessfulTop = styled.div`
- background-color: #5cb85c;
-`;
-export const SuccessfulBottom = styled(WhiteBottom)``;
-
-export const FailedTop = styled(WhiteTop)``;
-export const FailedBottom = styled.div`
- background-color: #d9534f;
-`;
-
-export const UnreachableTop = styled(WhiteTop)``;
-export const UnreachableBottom = styled.div`
- background-color: #ff0000;
-`;
-
-export const ChangedTop = styled(WhiteTop)``;
-export const ChangedBottom = styled.div`
- background-color: #ff9900;
-`;
-
-export const SkippedTop = styled(WhiteTop)``;
-export const SkippedBottom = styled.div`
- background-color: #2dbaba;
-`;
diff --git a/awx/ui_next/src/screens/Job/JobOutput/HostEventModal.jsx b/awx/ui_next/src/screens/Job/JobOutput/HostEventModal.jsx
index 7c826518a1..79aa92a560 100644
--- a/awx/ui_next/src/screens/Job/JobOutput/HostEventModal.jsx
+++ b/awx/ui_next/src/screens/Job/JobOutput/HostEventModal.jsx
@@ -9,7 +9,7 @@ import CodeMirrorInput from '@components/CodeMirrorInput';
import ContentEmpty from '@components/ContentEmpty';
import PropTypes from 'prop-types';
import { DetailList, Detail } from '@components/DetailList';
-import { HostStatusIcon } from '@components/Sparkline';
+import { StatusIcon } from '@components/Sparkline';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import styled from 'styled-components';
@@ -76,7 +76,7 @@ const processEventStatus = event => {
) {
status = 'ok';
}
- // catch the 'changed' case after 'ok', because both can be true
+ // if 'ok' and 'changed' are both true, show 'changed'
if (event.changed) {
status = 'changed';
}
@@ -160,7 +160,7 @@ function HostEventModal({ onClose, hostEvent = {}, isOpen = false, i18n }) {
label={i18n._(t`Host Name`)}
value={
- {hostStatus ? : null}
+ {hostStatus ? : null}
{hostEvent.host_name}
}
diff --git a/awx/ui_next/src/screens/Job/JobOutput/HostEventModal.test.jsx b/awx/ui_next/src/screens/Job/JobOutput/HostEventModal.test.jsx
index 716562ddb6..c67640d7ce 100644
--- a/awx/ui_next/src/screens/Job/JobOutput/HostEventModal.test.jsx
+++ b/awx/ui_next/src/screens/Job/JobOutput/HostEventModal.test.jsx
@@ -128,7 +128,7 @@ describe('HostEventModal', () => {
isOpen
/>
);
- const icon = wrapper.find('HostStatusIcon');
+ const icon = wrapper.find('StatusIcon');
expect(icon.prop('status')).toBe('ok');
expect(icon.find('StatusIcon__SuccessfulTop').length).toBe(1);
expect(icon.find('StatusIcon__SuccessfulBottom').length).toBe(1);
@@ -140,7 +140,7 @@ describe('HostEventModal', () => {
{}} isOpen />
);
- const icon = wrapper.find('HostStatusIcon');
+ const icon = wrapper.find('StatusIcon');
expect(icon.prop('status')).toBe('skipped');
expect(icon.find('StatusIcon__SkippedTop').length).toBe(1);
expect(icon.find('StatusIcon__SkippedBottom').length).toBe(1);
@@ -160,7 +160,7 @@ describe('HostEventModal', () => {
/>
);
- const icon = wrapper.find('HostStatusIcon');
+ const icon = wrapper.find('StatusIcon');
expect(icon.prop('status')).toBe('unreachable');
expect(icon.find('StatusIcon__UnreachableTop').length).toBe(1);
expect(icon.find('StatusIcon__UnreachableBottom').length).toBe(1);
@@ -181,7 +181,7 @@ describe('HostEventModal', () => {
/>
);
- const icon = wrapper.find('HostStatusIcon');
+ const icon = wrapper.find('StatusIcon');
expect(icon.prop('status')).toBe('failed');
expect(icon.find('StatusIcon__FailedTop').length).toBe(1);
expect(icon.find('StatusIcon__FailedBottom').length).toBe(1);