-
Notifications
You must be signed in to change notification settings - Fork 95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes #37122 - Update system status chart in job invocations detail page #871
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
.job-invocation-detail-page-section { | ||
$chart_size: 105px; | ||
|
||
.chart-donut { | ||
height: $chart_size; | ||
width: $chart_size; | ||
margin-bottom: 10px; | ||
} | ||
|
||
.chart-legend { | ||
height: $chart_size; | ||
min-width: 270px; | ||
|
||
.legend-title { | ||
font-weight: bold; | ||
font-size: var(--pf-global--FontSize--sm); | ||
margin-left: 8px; | ||
margin-bottom: 0; | ||
} | ||
|
||
.pf-c-description-list { | ||
margin-left: 8px; | ||
margin-top: 8px; | ||
|
||
.pf-c-description-list__term .pf-c-description-list__text { | ||
font-weight: normal; | ||
} | ||
} | ||
} | ||
|
||
.pf-c-divider { | ||
max-height: $chart_size; | ||
} | ||
|
||
.job-overview { | ||
height: $chart_size; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { translate as __, sprintf } from 'foremanReact/common/I18n'; | ||
import { | ||
ChartDonut, | ||
ChartLabel, | ||
ChartLegend, | ||
ChartTooltip, | ||
} from '@patternfly/react-charts'; | ||
import { | ||
DescriptionList, | ||
DescriptionListTerm, | ||
DescriptionListGroup, | ||
DescriptionListDescription, | ||
FlexItem, | ||
Text, | ||
} from '@patternfly/react-core'; | ||
import { | ||
global_palette_green_500 as successedColor, | ||
global_palette_red_100 as failedColor, | ||
global_palette_blue_300 as inProgressColor, | ||
global_palette_black_600 as canceledColor, | ||
global_palette_black_500 as emptyChartDonut, | ||
} from '@patternfly/react-tokens'; | ||
import DefaultLoaderEmptyState from 'foremanReact/components/HostDetails/DetailsCard/DefaultLoaderEmptyState'; | ||
import './JobInvocationDetail.scss'; | ||
|
||
const JobInvocationSystemStatusChart = ({ | ||
data, | ||
isAlreadyStarted, | ||
formattedStartDate, | ||
}) => { | ||
const { | ||
succeeded, | ||
failed, | ||
pending, | ||
cancelled, | ||
total, | ||
total_hosts: totalHosts, // includes scheduled | ||
} = data; | ||
const chartData = [ | ||
{ title: __('Succeeded:'), count: succeeded, color: successedColor.value }, | ||
{ title: __('Failed:'), count: failed, color: failedColor.value }, | ||
{ title: __('In Progress:'), count: pending, color: inProgressColor.value }, | ||
{ title: __('Canceled:'), count: cancelled, color: canceledColor.value }, | ||
]; | ||
const chartDonutTitle = () => { | ||
if (total > 0) return `${succeeded.toString()}/${total}`; | ||
if (totalHosts > 0) return `0/${totalHosts}`; | ||
return '0'; | ||
}; | ||
const chartSize = 105; | ||
const [legendWidth, setLegendWidth] = useState(270); | ||
|
||
// Calculates chart legend width based on its content | ||
useEffect(() => { | ||
const legendContainer = document.querySelector('.chart-legend'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand it today, but probably would be best to add a comment on why its needed for future us :) |
||
if (legendContainer) { | ||
const rectElement = legendContainer.querySelector('rect'); | ||
if (rectElement) { | ||
const rectWidth = parseFloat(rectElement.getAttribute('width')); | ||
setLegendWidth(rectWidth); | ||
} | ||
} | ||
}, [isAlreadyStarted, data]); | ||
|
||
return ( | ||
<> | ||
<FlexItem className="chart-donut"> | ||
<ChartDonut | ||
allowTooltip | ||
constrainToVisibleArea | ||
data={ | ||
total > 0 | ||
? chartData.map(d => ({ | ||
label: sprintf(__(`${d.title} ${d.count} hosts`)), | ||
y: d.count, | ||
})) | ||
: [{ label: sprintf(__(`Scheduled: ${totalHosts} hosts`)), y: 1 }] | ||
} | ||
colorScale={ | ||
total > 0 ? chartData.map(d => d.color) : [emptyChartDonut.value] | ||
} | ||
labelComponent={ | ||
<ChartTooltip pointerLength={0} constrainToVisibleArea /> | ||
} | ||
title={chartDonutTitle} | ||
titleComponent={ | ||
// inline style overrides PatternFly default styling | ||
<ChartLabel style={{ fontSize: '20px' }} /> | ||
} | ||
subTitle={__('Systems')} | ||
subTitleComponent={ | ||
// inline style overrides PatternFly default styling | ||
<ChartLabel | ||
style={{ fontSize: '12px', fill: canceledColor.value }} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be in a css file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@MariaAga is the comment There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah! i approved it, and have to merge permissions in plugins, only @adamruzicka can merge here:) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't want to merge with outstanding comments in case this was still unresolved |
||
/> | ||
} | ||
padding={{ | ||
bottom: 0, | ||
left: 0, | ||
right: 0, | ||
top: 0, | ||
}} | ||
width={chartSize} | ||
height={chartSize} | ||
/> | ||
</FlexItem> | ||
<FlexItem className="chart-legend"> | ||
<Text ouiaId="legend-title" className="legend-title"> | ||
{__('System status')} | ||
</Text> | ||
{isAlreadyStarted ? ( | ||
<ChartLegend | ||
orientation="vertical" | ||
itemsPerRow={2} | ||
gutter={25} | ||
rowGutter={7} | ||
padding={{ left: 15 }} | ||
data={chartData.map(d => ({ | ||
name: `${d.title} ${d.count}`, | ||
symbol: { type: 'circle' }, | ||
}))} | ||
colorScale={chartData.map(d => d.color)} | ||
width={legendWidth} | ||
height={chartSize} | ||
/> | ||
) : ( | ||
<DescriptionList> | ||
<DescriptionListGroup> | ||
<DescriptionListTerm>{__('Scheduled at:')}</DescriptionListTerm> | ||
<DescriptionListDescription> | ||
{formattedStartDate || <DefaultLoaderEmptyState />} | ||
</DescriptionListDescription> | ||
</DescriptionListGroup> | ||
</DescriptionList> | ||
)} | ||
</FlexItem> | ||
</> | ||
); | ||
}; | ||
|
||
JobInvocationSystemStatusChart.propTypes = { | ||
data: PropTypes.object.isRequired, | ||
isAlreadyStarted: PropTypes.bool.isRequired, | ||
formattedStartDate: PropTypes.string, | ||
}; | ||
|
||
JobInvocationSystemStatusChart.defaultProps = { | ||
formattedStartDate: undefined, | ||
}; | ||
|
||
export default JobInvocationSystemStatusChart; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between
total
andtotalHosts
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
total
represents the combined count of succeeded, failed, pending, and canceled, whereastotalHosts
also includes those currently scheduled in the future.