From 4be7cf66ecb09761dd2f8266a7b48d19ebecdbf5 Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Wed, 5 Feb 2020 19:57:55 -0500 Subject: [PATCH 1/3] Add host status bar --- .../src/screens/Job/JobOutput/JobOutput.jsx | 7 +- .../Job/JobOutput/shared/HostStatusBar.jsx | 88 +++++++++++++++++++ .../JobOutput/shared/HostStatusBar.test.jsx | 52 +++++++++++ .../screens/Job/JobOutput/shared/index.jsx | 1 + 4 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.jsx create mode 100644 awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.test.jsx diff --git a/awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx b/awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx index 15775c56ec..30e9eed05f 100644 --- a/awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx +++ b/awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx @@ -1,3 +1,4 @@ +import React, { Component } from 'react'; import styled from 'styled-components'; import { AutoSizer, @@ -7,16 +8,15 @@ import { List, } from 'react-virtualized'; -import React, { Component } from 'react'; import { CardBody } from '@components/Card'; - -import { JobsAPI } from '@api'; import ContentError from '@components/ContentError'; import ContentLoading from '@components/ContentLoading'; import JobEvent from './JobEvent'; import JobEventSkeleton from './JobEventSkeleton'; import PageControls from './PageControls'; import HostEventModal from './HostEventModal'; +import { HostStatusBar } from './shared'; +import { JobsAPI } from '@api'; const OutputHeader = styled.div` font-weight: var(--pf-global--FontWeight--bold); @@ -306,6 +306,7 @@ class JobOutput extends Component { /> )} {job.name} + props.color || 'inherit'}; + flex-grow: ${props => props.count || 0}; +`; + +const TooltipContent = styled.div` + align-items: center; + display: flex; + + span.pf-c-badge { + margin-left: 10px; + } +`; + +const HostStatusBar = ({ i18n, counts = {} }) => { + const noData = Object.keys(counts).length === 0; + const hostStatus = { + ok: { + color: '#92D400', + label: i18n._(t`OK`), + }, + dark: { + color: '#470000', + label: i18n._(t`Unreachable`), + }, + failures: { + color: '#C9190B', + label: i18n._(t`Failed`), + }, + changed: { + color: '#F0AB00', + label: i18n._(t`Changed`), + }, + skipped: { + color: '#73BCF7', + label: i18n._(t`Skipped`), + }, + }; + + const barSegments = Object.keys(hostStatus).map(key => { + const count = counts[key] || 0; + return ( + + {hostStatus[key].label} + {count} + + } + > + + + ); + }); + + if (noData) { + return ( + + + + + + ); + } + + return {barSegments}; +}; + +export default withI18n()(HostStatusBar); diff --git a/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.test.jsx b/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.test.jsx new file mode 100644 index 0000000000..d7629c6041 --- /dev/null +++ b/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.test.jsx @@ -0,0 +1,52 @@ +import React from 'react'; +import { mountWithContexts } from '@testUtils/enzymeHelpers'; +import { HostStatusBar } from '.'; + +describe('', () => { + let wrapper; + const mockCounts = { + ok: 5, + skipped: 1, + }; + + beforeEach(() => { + wrapper = mountWithContexts(); + }); + + afterEach(() => { + wrapper.unmount(); + }); + + test('initially renders without crashing', () => { + expect(wrapper.length).toBe(1); + }); + + test('should render five bar segments', () => { + expect(wrapper.find('HostStatusBar__BarSegment').length).toBe(5); + }); + + test('tooltips should display host status and count', () => { + const tooltips = wrapper.find('TooltipContent'); + const expectedContent = [ + { label: 'OK', count: 5 }, + { label: 'Unreachable', count: 0 }, + { label: 'Failed', count: 0 }, + { label: 'Changed', count: 0 }, + { label: 'Skipped', count: 1 }, + ]; + + tooltips.forEach((tooltip, index) => { + expect(tooltip.text()).toEqual( + `${expectedContent[index].label}${expectedContent[index].count}` + ); + }); + }); + + test('empty host counts should display tooltip and one bar segment', () => { + wrapper = mountWithContexts(); + expect(wrapper.find('HostStatusBar__BarSegment').length).toBe(1); + expect(wrapper.find('TooltipContent').text()).toEqual( + 'Host status information for this job is unavailable.' + ); + }); +}); diff --git a/awx/ui_next/src/screens/Job/JobOutput/shared/index.jsx b/awx/ui_next/src/screens/Job/JobOutput/shared/index.jsx index d0edeb8e1f..58c72834e9 100644 --- a/awx/ui_next/src/screens/Job/JobOutput/shared/index.jsx +++ b/awx/ui_next/src/screens/Job/JobOutput/shared/index.jsx @@ -2,3 +2,4 @@ export { default as JobEventLine } from './JobEventLine'; export { default as JobEventLineToggle } from './JobEventLineToggle'; export { default as JobEventLineNumber } from './JobEventLineNumber'; export { default as JobEventLineText } from './JobEventLineText'; +export { default as HostStatusBar } from './HostStatusBar'; From 028a0a9279c07733ca67f2ccbb43b2272fcd187d Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Thu, 6 Feb 2020 11:21:14 -0500 Subject: [PATCH 2/3] Adjust host status colors --- .../Job/JobOutput/shared/HostStatusBar.jsx | 22 +++++++++---------- .../JobOutput/shared/HostStatusBar.test.jsx | 6 ++--- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.jsx b/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.jsx index beda720f6a..1fec162adb 100644 --- a/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.jsx +++ b/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.jsx @@ -30,24 +30,24 @@ const HostStatusBar = ({ i18n, counts = {} }) => { const noData = Object.keys(counts).length === 0; const hostStatus = { ok: { - color: '#92D400', + color: '#4CB140', label: i18n._(t`OK`), }, - dark: { - color: '#470000', - label: i18n._(t`Unreachable`), - }, - failures: { - color: '#C9190B', - label: i18n._(t`Failed`), + skipped: { + color: '#73BCF7', + label: i18n._(t`Skipped`), }, changed: { color: '#F0AB00', label: i18n._(t`Changed`), }, - skipped: { - color: '#73BCF7', - label: i18n._(t`Skipped`), + failures: { + color: '#C9190B', + label: i18n._(t`Failed`), + }, + dark: { + color: '#8B8D8F', + label: i18n._(t`Unreachable`), }, }; diff --git a/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.test.jsx b/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.test.jsx index d7629c6041..c1fae8c6a0 100644 --- a/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.test.jsx +++ b/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.test.jsx @@ -29,10 +29,10 @@ describe('', () => { const tooltips = wrapper.find('TooltipContent'); const expectedContent = [ { label: 'OK', count: 5 }, - { label: 'Unreachable', count: 0 }, - { label: 'Failed', count: 0 }, - { label: 'Changed', count: 0 }, { label: 'Skipped', count: 1 }, + { label: 'Changed', count: 0 }, + { label: 'Failed', count: 0 }, + { label: 'Unreachable', count: 0 }, ]; tooltips.forEach((tooltip, index) => { From d250dd0cd60c28aa58f451660c9eb1696ae29729 Mon Sep 17 00:00:00 2001 From: Marliana Lara Date: Thu, 6 Feb 2020 13:34:58 -0500 Subject: [PATCH 3/3] Adjust ansi colors to complement the host status bar --- awx/ui_next/src/screens/Job/JobOutput/JobEvent.jsx | 8 ++++---- awx/ui_next/src/screens/Job/JobOutput/JobEvent.test.jsx | 2 +- awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx | 2 +- .../src/screens/Job/JobOutput/shared/HostStatusBar.jsx | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/awx/ui_next/src/screens/Job/JobOutput/JobEvent.jsx b/awx/ui_next/src/screens/Job/JobOutput/JobEvent.jsx index 769ccf42a4..f94e0ed12d 100644 --- a/awx/ui_next/src/screens/Job/JobOutput/JobEvent.jsx +++ b/awx/ui_next/src/screens/Job/JobOutput/JobEvent.jsx @@ -18,12 +18,12 @@ const ansi = new Ansi({ stream: true, colors: { 0: '#000', - 1: '#A00', - 2: '#080', - 3: '#F0AD4E', + 1: '#A30000', + 2: '#486B00', + 3: '#795600', 4: '#00A', 5: '#A0A', - 6: '#0AA', + 6: '#004368', 7: '#AAA', 8: '#555', 9: '#F55', diff --git a/awx/ui_next/src/screens/Job/JobOutput/JobEvent.test.jsx b/awx/ui_next/src/screens/Job/JobOutput/JobEvent.test.jsx index 5ea70b8e47..21de9847e2 100644 --- a/awx/ui_next/src/screens/Job/JobOutput/JobEvent.test.jsx +++ b/awx/ui_next/src/screens/Job/JobOutput/JobEvent.test.jsx @@ -53,7 +53,7 @@ describe('', () => { expect( lineText .html() - .includes('ok: [localhost]') + .includes('ok: [localhost]') ).toBe(true); }); diff --git a/awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx b/awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx index 30e9eed05f..b3beae759b 100644 --- a/awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx +++ b/awx/ui_next/src/screens/Job/JobOutput/JobOutput.jsx @@ -23,7 +23,7 @@ const OutputHeader = styled.div` `; const OutputWrapper = styled.div` - background-color: #fafafa; + background-color: #ffffff; display: flex; flex-direction: column; font-family: monospace; diff --git a/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.jsx b/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.jsx index 1fec162adb..d6e47092e9 100644 --- a/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.jsx +++ b/awx/ui_next/src/screens/Job/JobOutput/shared/HostStatusBar.jsx @@ -46,7 +46,7 @@ const HostStatusBar = ({ i18n, counts = {} }) => { label: i18n._(t`Failed`), }, dark: { - color: '#8B8D8F', + color: '#8F4700', label: i18n._(t`Unreachable`), }, };