mirror of
https://github.com/ansible/awx.git
synced 2026-05-06 08:57:35 -02:30
adds more filters to dashboard chart
This commit is contained in:
@@ -25,6 +25,12 @@ import LineChart from './shared/LineChart';
|
|||||||
import Count from './shared/Count';
|
import Count from './shared/Count';
|
||||||
import TemplateList from '../../components/TemplateList';
|
import TemplateList from '../../components/TemplateList';
|
||||||
|
|
||||||
|
const StatusSelect = styled(Select)`
|
||||||
|
&& {
|
||||||
|
--pf-c-select__toggle--MinWidth: 165px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const Counts = styled.div`
|
const Counts = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(6, 1fr);
|
grid-template-columns: repeat(6, 1fr);
|
||||||
@@ -57,8 +63,10 @@ const GraphCardActions = styled(CardActions)`
|
|||||||
function Dashboard() {
|
function Dashboard() {
|
||||||
const [isPeriodDropdownOpen, setIsPeriodDropdownOpen] = useState(false);
|
const [isPeriodDropdownOpen, setIsPeriodDropdownOpen] = useState(false);
|
||||||
const [isJobTypeDropdownOpen, setIsJobTypeDropdownOpen] = useState(false);
|
const [isJobTypeDropdownOpen, setIsJobTypeDropdownOpen] = useState(false);
|
||||||
|
const [isJobStatusDropdownOpen, setIsJobStatusDropdownOpen] = useState(false);
|
||||||
const [periodSelection, setPeriodSelection] = useState('month');
|
const [periodSelection, setPeriodSelection] = useState('month');
|
||||||
const [jobTypeSelection, setJobTypeSelection] = useState('all');
|
const [jobTypeSelection, setJobTypeSelection] = useState('all');
|
||||||
|
const [jobStatusSelection, setJobStatusSelection] = useState('all');
|
||||||
const [activeTabId, setActiveTabId] = useState(0);
|
const [activeTabId, setActiveTabId] = useState(0);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -196,6 +204,9 @@ function Dashboard() {
|
|||||||
<SelectOption key="week" value="week">
|
<SelectOption key="week" value="week">
|
||||||
{t`Past week`}
|
{t`Past week`}
|
||||||
</SelectOption>
|
</SelectOption>
|
||||||
|
<SelectOption key="day" value="day">
|
||||||
|
{t`Past 24 hours`}
|
||||||
|
</SelectOption>
|
||||||
</Select>
|
</Select>
|
||||||
<Select
|
<Select
|
||||||
variant={SelectVariant.single}
|
variant={SelectVariant.single}
|
||||||
@@ -222,10 +233,37 @@ function Dashboard() {
|
|||||||
{t`Playbook run`}
|
{t`Playbook run`}
|
||||||
</SelectOption>
|
</SelectOption>
|
||||||
</Select>
|
</Select>
|
||||||
|
<StatusSelect
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
placeholderText={t`Select status`}
|
||||||
|
aria-label={t`Select status`}
|
||||||
|
className="jobStatusSelect"
|
||||||
|
onToggle={setIsJobStatusDropdownOpen}
|
||||||
|
onSelect={(event, selection) => {
|
||||||
|
setIsJobStatusDropdownOpen(false);
|
||||||
|
setJobStatusSelection(selection);
|
||||||
|
}}
|
||||||
|
selections={jobStatusSelection}
|
||||||
|
isOpen={isJobStatusDropdownOpen}
|
||||||
|
>
|
||||||
|
<SelectOption
|
||||||
|
key="all"
|
||||||
|
value="all"
|
||||||
|
>{t`All jobs`}</SelectOption>
|
||||||
|
<SelectOption
|
||||||
|
key="successful"
|
||||||
|
value="successful"
|
||||||
|
>{t`Successful jobs`}</SelectOption>
|
||||||
|
<SelectOption
|
||||||
|
key="failed"
|
||||||
|
value="failed"
|
||||||
|
>{t`Failed jobs`}</SelectOption>
|
||||||
|
</StatusSelect>
|
||||||
</GraphCardActions>
|
</GraphCardActions>
|
||||||
</GraphCardHeader>
|
</GraphCardHeader>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<LineChart
|
<LineChart
|
||||||
|
jobStatus={jobStatusSelection}
|
||||||
height={390}
|
height={390}
|
||||||
id="d3-line-chart-root"
|
id="d3-line-chart-root"
|
||||||
data={jobGraphData}
|
data={jobGraphData}
|
||||||
|
|||||||
@@ -53,4 +53,34 @@ describe('<Dashboard />', () => {
|
|||||||
period: 'month',
|
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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { PageContextConsumer } from '@patternfly/react-core';
|
|||||||
|
|
||||||
import ChartTooltip from './ChartTooltip';
|
import ChartTooltip from './ChartTooltip';
|
||||||
|
|
||||||
function LineChart({ id, data, height, pageContext }) {
|
function LineChart({ id, data, height, pageContext, jobStatus }) {
|
||||||
const { isNavOpen } = pageContext;
|
const { isNavOpen } = pageContext;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
@@ -197,61 +197,68 @@ function LineChart({ id, data, height, pageContext }) {
|
|||||||
vertical.transition().style('opacity', 0);
|
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');
|
const dateFormat = d3.timeFormat('%-m-%-d');
|
||||||
|
|
||||||
// create our successLine circles
|
if (jobStatus !== 'failed') {
|
||||||
svg
|
// Add the success line path.
|
||||||
.selectAll('dot')
|
svg
|
||||||
.data(formattedData)
|
.append('path')
|
||||||
.enter()
|
.data([formattedData])
|
||||||
.append('circle')
|
.attr('class', 'line')
|
||||||
.attr('r', 3)
|
.style('fill', 'none')
|
||||||
.style('stroke', () => colors(1))
|
.style('stroke', () => colors(1))
|
||||||
.style('fill', () => colors(1))
|
.attr('stroke-width', 2)
|
||||||
.attr('cx', d => x(d.DATE))
|
.attr('d', successLine)
|
||||||
.attr('cy', d => y(d.RAN))
|
.call(transition);
|
||||||
.attr('id', d => `success-dot-${dateFormat(d.DATE)}`)
|
|
||||||
.on('mouseover', handleMouseOver)
|
// create our success line circles
|
||||||
.on('mousemove', handleMouseMove)
|
|
||||||
.on('mouseout', handleMouseOut);
|
svg
|
||||||
// create our failLine circles
|
.selectAll('dot')
|
||||||
svg
|
.data(formattedData)
|
||||||
.selectAll('dot')
|
.enter()
|
||||||
.data(formattedData)
|
.append('circle')
|
||||||
.enter()
|
.attr('r', 3)
|
||||||
.append('circle')
|
.style('stroke', () => colors(1))
|
||||||
.attr('r', 3)
|
.style('fill', () => colors(1))
|
||||||
.style('stroke', () => colors(0))
|
.attr('cx', d => x(d.DATE))
|
||||||
.style('fill', () => colors(0))
|
.attr('cy', d => y(d.RAN))
|
||||||
.attr('cx', d => x(d.DATE))
|
.attr('id', d => `success-dot-${dateFormat(d.DATE)}`)
|
||||||
.attr('cy', d => y(d.FAIL))
|
.on('mouseover', handleMouseOver)
|
||||||
.attr('id', d => `fail-dot-${dateFormat(d.DATE)}`)
|
.on('mousemove', handleMouseMove)
|
||||||
.on('mouseover', handleMouseOver)
|
.on('mouseout', handleMouseOut);
|
||||||
.on('mousemove', handleMouseMove)
|
}
|
||||||
.on('mouseout', handleMouseOut);
|
|
||||||
}, [data, height, id]);
|
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(() => {
|
useEffect(() => {
|
||||||
draw();
|
draw();
|
||||||
|
|||||||
Reference in New Issue
Block a user