From 1537b84ec8f25c2e4197b15004e56562ca8dab3b Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Thu, 3 Jun 2021 15:10:21 -0400 Subject: [PATCH] adds more filters to dashboard chart --- .../src/screens/Dashboard/Dashboard.jsx | 38 ++++++ .../src/screens/Dashboard/Dashboard.test.jsx | 30 +++++ .../screens/Dashboard/shared/LineChart.jsx | 115 ++++++++++-------- 3 files changed, 129 insertions(+), 54 deletions(-) diff --git a/awx/ui_next/src/screens/Dashboard/Dashboard.jsx b/awx/ui_next/src/screens/Dashboard/Dashboard.jsx index f8772f5185..950451cbe4 100644 --- a/awx/ui_next/src/screens/Dashboard/Dashboard.jsx +++ b/awx/ui_next/src/screens/Dashboard/Dashboard.jsx @@ -25,6 +25,12 @@ import LineChart from './shared/LineChart'; import Count from './shared/Count'; import TemplateList from '../../components/TemplateList'; +const StatusSelect = styled(Select)` + && { + --pf-c-select__toggle--MinWidth: 165px; + } +`; + const Counts = styled.div` display: grid; grid-template-columns: repeat(6, 1fr); @@ -57,8 +63,10 @@ const GraphCardActions = styled(CardActions)` function Dashboard() { const [isPeriodDropdownOpen, setIsPeriodDropdownOpen] = useState(false); const [isJobTypeDropdownOpen, setIsJobTypeDropdownOpen] = useState(false); + const [isJobStatusDropdownOpen, setIsJobStatusDropdownOpen] = useState(false); const [periodSelection, setPeriodSelection] = useState('month'); const [jobTypeSelection, setJobTypeSelection] = useState('all'); + const [jobStatusSelection, setJobStatusSelection] = useState('all'); const [activeTabId, setActiveTabId] = useState(0); const { @@ -196,6 +204,9 @@ function Dashboard() { {t`Past week`} + + {t`Past 24 hours`} + + { + setIsJobStatusDropdownOpen(false); + setJobStatusSelection(selection); + }} + selections={jobStatusSelection} + isOpen={isJobStatusDropdownOpen} + > + {t`All jobs`} + {t`Successful jobs`} + {t`Failed jobs`} + ', () => { period: 'month', }); }); + test('should render all three line chart filters with correct number of options', async () => { + expect(pageWrapper.find('Select[variant="single"]')).toHaveLength(3); + await act(async () => { + pageWrapper + .find('Select[placeholderText="Select job type"]') + .prop('onToggle')(true); + }); + pageWrapper.update(); + expect(pageWrapper.find('SelectOption')).toHaveLength(4); + await act(async () => { + pageWrapper + .find('Select[placeholderText="Select job type"]') + .prop('onToggle')(false); + pageWrapper + .find('Select[placeholderText="Select period"]') + .prop('onToggle')(true); + }); + pageWrapper.update(); + expect(pageWrapper.find('SelectOption')).toHaveLength(4); + await act(async () => { + pageWrapper + .find('Select[placeholderText="Select period"]') + .prop('onToggle')(false); + pageWrapper + .find('Select[placeholderText="Select status"]') + .prop('onToggle')(true); + }); + pageWrapper.update(); + expect(pageWrapper.find('SelectOption')).toHaveLength(3); + }); }); diff --git a/awx/ui_next/src/screens/Dashboard/shared/LineChart.jsx b/awx/ui_next/src/screens/Dashboard/shared/LineChart.jsx index ddf9d62458..5b84973059 100644 --- a/awx/ui_next/src/screens/Dashboard/shared/LineChart.jsx +++ b/awx/ui_next/src/screens/Dashboard/shared/LineChart.jsx @@ -7,7 +7,7 @@ import { PageContextConsumer } from '@patternfly/react-core'; import ChartTooltip from './ChartTooltip'; -function LineChart({ id, data, height, pageContext }) { +function LineChart({ id, data, height, pageContext, jobStatus }) { const { isNavOpen } = pageContext; // Methods @@ -197,61 +197,68 @@ function LineChart({ id, data, height, pageContext }) { vertical.transition().style('opacity', 0); }; - // Add the successLine path. - svg - .append('path') - .data([formattedData]) - .attr('class', 'line') - .style('fill', 'none') - .style('stroke', () => colors(1)) - .attr('stroke-width', 2) - .attr('d', successLine) - .call(transition); - - // Add the failLine path. - svg - .append('path') - .data([formattedData]) - .attr('class', 'line') - .style('fill', 'none') - .style('stroke', () => colors(0)) - .attr('stroke-width', 2) - .attr('d', failLine) - .call(transition); - const dateFormat = d3.timeFormat('%-m-%-d'); - // create our successLine circles - svg - .selectAll('dot') - .data(formattedData) - .enter() - .append('circle') - .attr('r', 3) - .style('stroke', () => colors(1)) - .style('fill', () => colors(1)) - .attr('cx', d => x(d.DATE)) - .attr('cy', d => y(d.RAN)) - .attr('id', d => `success-dot-${dateFormat(d.DATE)}`) - .on('mouseover', handleMouseOver) - .on('mousemove', handleMouseMove) - .on('mouseout', handleMouseOut); - // create our failLine circles - svg - .selectAll('dot') - .data(formattedData) - .enter() - .append('circle') - .attr('r', 3) - .style('stroke', () => colors(0)) - .style('fill', () => colors(0)) - .attr('cx', d => x(d.DATE)) - .attr('cy', d => y(d.FAIL)) - .attr('id', d => `fail-dot-${dateFormat(d.DATE)}`) - .on('mouseover', handleMouseOver) - .on('mousemove', handleMouseMove) - .on('mouseout', handleMouseOut); - }, [data, height, id]); + if (jobStatus !== 'failed') { + // Add the success line path. + svg + .append('path') + .data([formattedData]) + .attr('class', 'line') + .style('fill', 'none') + .style('stroke', () => colors(1)) + .attr('stroke-width', 2) + .attr('d', successLine) + .call(transition); + + // create our success line circles + + svg + .selectAll('dot') + .data(formattedData) + .enter() + .append('circle') + .attr('r', 3) + .style('stroke', () => colors(1)) + .style('fill', () => colors(1)) + .attr('cx', d => x(d.DATE)) + .attr('cy', d => y(d.RAN)) + .attr('id', d => `success-dot-${dateFormat(d.DATE)}`) + .on('mouseover', handleMouseOver) + .on('mousemove', handleMouseMove) + .on('mouseout', handleMouseOut); + } + + if (jobStatus !== 'successful') { + // Add the failed line path. + svg + .append('path') + .data([formattedData]) + .attr('class', 'line') + .style('fill', 'none') + .style('stroke', () => colors(0)) + .attr('stroke-width', 2) + .attr('d', failLine) + .call(transition); + + // create our failed line circles + + svg + .selectAll('dot') + .data(formattedData) + .enter() + .append('circle') + .attr('r', 3) + .style('stroke', () => colors(0)) + .style('fill', () => colors(0)) + .attr('cx', d => x(d.DATE)) + .attr('cy', d => y(d.FAIL)) + .attr('id', d => `fail-dot-${dateFormat(d.DATE)}`) + .on('mouseover', handleMouseOver) + .on('mousemove', handleMouseMove) + .on('mouseout', handleMouseOut); + } + }, [data, height, id, jobStatus]); useEffect(() => { draw();