-
Notifications
You must be signed in to change notification settings - Fork 991
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 #24011 - Add Patternfly bar chart support #5718
Conversation
Issues: #24011 |
@ripcurld @amirfefer |
2d1f6be
to
3a5215a
Compare
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.
Thanks @lizagilman -
I left some inline comments.
What do you think about adding the bar chart functionality to the ChartBox component? then we could use the chartbox component in the metrics page, and by that we keep the consistency from the Statistics page.
donutChartConfig, | ||
donutLargeChartConfig, | ||
barChartConfig, | ||
} from './ChartService.consts'; | ||
|
||
const sizeConfig = { |
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.
It's not a size configuration anymore, could you rename?
@@ -29,6 +34,7 @@ const getChartConfig = ({ | |||
data, config, onclick, id = uuidV1(), | |||
}) => { | |||
const chartConfigForType = sizeConfig[config]; | |||
|
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.
redundant line
@@ -11,7 +11,8 @@ | |||
<div class="col-md-4"> | |||
<div class="stats-well"> | |||
<h4 class="ca" ><%= _('Report Status') %></h4> | |||
<%= flot_bar_chart("status" ,"", _("Number of Events"), status, :class => "statistics-bar")%> | |||
<div id="status_chart" class='metrics-chart'></div> | |||
<%= mount_react_component('BarChart', '#status_chart', {barChartData: status.to_a, label: "Number of Events"}.to_json) %> |
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.
there's another BarChart in the dashboard (run distribution widget)
|
||
data: { ...chartConfig.data, type: 'bar' }, | ||
|
||
legend: { show: true }, |
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.
IMO the legend default should be false
looks odd with only one category
export const barChartConfig = { | ||
...chartConfig, | ||
|
||
data: { ...chartConfig.data, type: 'bar' }, |
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.
Do we have to add type: 'bar'
prop? patternfly BarChart implementation adds it anyway
}, | ||
}, | ||
|
||
categories, |
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.
do we need this here as well?
|
||
columns.unshift(label); | ||
|
||
chartConfig.data.columns = [columns]; |
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.
looks like the data structure doesn't support in groups/stacks
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.
Do you referr to grouped bar chart?
Grouped bar chart expects the following structure: [category1, value1, value2, ...], [category2, value3, value4, ...]
Do we have anywhere data that can be used or manipulated to form this structure?
The 'regular' structure ( (DATA, VALUE) ) is good for the single bar (not grouped) chart, which expects only one value [category, value]
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.
I'm not sure.
@ohadlevy - would we like to support grouped chart?
@@ -52,6 +58,7 @@ const getChartConfig = ({ | |||
...chartConfigForType, | |||
id, | |||
data: { | |||
...chartConfigForType.data, |
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.
I think if we'll remove {type: bar}
from the config object, then we can remove this line.
|
||
columns.unshift(label); | ||
|
||
chartConfig.data.columns = [columns]; |
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.
I have mixed feeling about this. looks like we modify columns property in two different places, if the data is calculated differently from donut chart, maybe it would be better to separate the logic between the two.
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.
I agree, isn't this separation (between the two functions) enough?
data, | ||
onclick, | ||
config = 'regularBar', | ||
noDataMsg = __('No data available'), |
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.
Better to use defaultProps
and Proptypes
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.
thanks @lizagilman
please add yarn.lock
to gitignore
app/helpers/dashboard_helper.rb
Outdated
@@ -67,6 +67,11 @@ def get_overview_json(report, options = {}) | |||
|
|||
def render_run_distribution(hosts, options = {}) | |||
data = count_reports(hosts, options) | |||
puts '*********************************************' |
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.
forgot to delete this
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.
😅
package.json
Outdated
@@ -96,7 +96,7 @@ | |||
"uuid": "^3.0.1" | |||
}, | |||
"scripts": { | |||
"lint": "./node_modules/.bin/eslint -c .eslintrc webpack/ script/ || exit 0", | |||
"lint": "./node_modules/.bin/eslint -c .eslintrc webpack/ script/", |
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.
why?
@@ -29,7 +29,7 @@ export function templateSelected(item) { | |||
$('#storage_volumes .children_fields >.fields').remove(); | |||
$.each(result.volumes, function () { | |||
// Change variable name because 'interface' is a reserved keyword. | |||
this.disk_interface = this['interface']; | |||
this.disk_interface = this.interface; |
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.
well I do find this better syntax, but how does it related?
const BarChart = ({ | ||
data, | ||
onclick, | ||
noDataMsg = __('No data available'), |
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.
could it be defined in the defaultProps
?
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.
I think it could be done when your jed pr (5342) is merged
BarChart.propTypes = { | ||
config: PropTypes.string, | ||
noDataMsg: PropTypes.string, | ||
title: PropTypes.object, |
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.
please use shape
instead of just .object
|
||
const categories = data.map(dataItem => dataItem[0]); | ||
|
||
const columns = data.map(x => x[1]); |
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.
@sharvit This ChartSevice
becomes more and more complex, each render this will invoked, even if nothing changed.
what do you think about moving this logic to a selector (memorized if needed) by connect this component to the store, or its parent.
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.
Can we actually move it into selectors? I think most of the data coming from the data prop and not from the state.
Does it actually lead to performance issue that we must solve in this particular PR?
|
||
columns.unshift(label); | ||
|
||
chartConfig.data.columns = [columns]; |
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.
I'm not sure.
@ohadlevy - would we like to support grouped chart?
const configForType = { | ||
regularDonut: donutChartConfig, | ||
largeDonut: donutLargeChartConfig, | ||
regularBar: barChartConfig, |
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.
IMHO, since there is only one size (regular
) to BarChart
, it is not a good idea to add it to the configForType
(previously sizeConfig
) object.
If we insist on doing that, maybe keep the name sizeConfig
and nested it
:
const sizeConfig = {
donut: {
regular: ...
large: ...
},
bar: {
...
}
}
const getChartConfig = ({
...
type,
config
}) = {
chartConfigForType = sizeConfig[type][config]
...
}
...chartConfig, | ||
size: barChartEnums.SIZE.REGULAR, | ||
|
||
// data: { ...chartConfig.data, }, |
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.
did you forget to uncomment
this? 😃
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.
😅
cb15536
to
2add6cd
Compare
277152f
to
d5d16b7
Compare
app/helpers/dashboard_helper.rb
Outdated
def render_run_distribution(hosts, options = {}) | ||
data = count_reports(hosts, options) | ||
flot_bar_chart("run_distribution", _("Minutes Ago"), _("Number Of Clients"), data, options) | ||
|
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.
Layout/TrailingWhitespace: Trailing whitespace detected.
@amirfefer @ripcurld |
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.
Thanks @lizagilman, looks great
Could you use ChartBox
in the metrics page?
|
||
const BarChart = ({ | ||
data, | ||
onclick, |
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.
some props missing in the proptype
.gitignore
Outdated
@@ -48,3 +48,4 @@ public/webpack | |||
package-lock.json | |||
npm-debug.log | |||
.vscode | |||
yarn.lock |
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.
are you using yarn?
@amirfefer thanks addressed all your comments |
[test foreman] |
@sharvit @amirfefer any other comments here? |
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.
Thanks @lizagilman ! 👍
almost there, few minor issues :)
metricsData: { tableData, tableClasses, total }, | ||
} = props.data; | ||
|
||
const createRow = (metric, i) => ( |
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.
nitpick: please use array destructing here:
const createRow = ([name, value], i) => (
<tr key={i}>
<td className="break-me">{name}</td>
<td>{value}</td>
</tr>
);
type="donut" | ||
chart={{ data: metricsChartData, id: 'report-metrics' }} | ||
title="Report Metrics" | ||
id="report-metrics" |
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.
I didn't find any use of id prop in Chartbox
@@ -79,7 +94,7 @@ class ChartBox extends React.Component { | |||
<Modal.Title>{this.props.title}</Modal.Title> | |||
</Modal.Header> | |||
<Modal.Body> | |||
<Chart {...chartProps} config="large" />; | |||
<Chart {...chartProps} config={this.props.config} /> |
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.
nitpick:
could you extract the props ?
const { config, title, className, status } = this.props
import PropTypes from 'prop-types'; | ||
import componentRegistry from '../componentRegistry'; | ||
|
||
const ComponentWrapper = (props) => { |
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.
index.js
meant for redux containers (connected components), I prefer to use componentWrapper.js
as a name
Plus, shouldn't it be under common
directory?
const { component, componentProps } = props.data; | ||
|
||
if (component === 'ComponentWrapper') { | ||
throw new Error('Cannot wrap componenet wrapper'); |
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.
could you add a test for this
}), | ||
}; | ||
|
||
export default ConfigReports; |
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.
same here (use ConfigReport.js
instead of index.js)
import { translate as __ } from '../../common/I18n'; | ||
import { STATUS } from '../../constants'; | ||
|
||
const ConfigReports = (props) => { |
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.
could you add a snapshot test for this component ?
@amirfefer |
[test katello] |
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.
@lizagilman Works and looks great !
thanks 👍
@tstrachota can we merge? |
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.
I found one issue in code. Otherwise it looks good. I still need to test it live though.
app/helpers/reports_helper.rb
Outdated
@@ -22,6 +22,13 @@ def metric(m) | |||
m.round(4) rescue _("N/A") | |||
end | |||
|
|||
def metrics_table_data(metrics) | |||
metrics.map do |title, value| |
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.
Result of this method is thrown away.
thanks @tstrachota , updated |
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.
I tested this and it works well.
Test failures are unrelated, merging. Thanks @lizagilman ! |
Hey guys, the component wrapper looks really awesome ! though it seem not to work while the component uses Redux my guess is that the I saw that on regular components it works.. so it seems that something happens when involving Redux any tips how to solve this? |
@LaViro |
Tried to pass the unconnected component through componentRegistry and it worked great ! |
To do:
edit:
updated screenshot -