-
Notifications
You must be signed in to change notification settings - Fork 8.2k
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
removes the angular dependency from tag cloud #15779
removes the angular dependency from tag cloud #15779
Conversation
a9c669e
to
cf280b2
Compare
constructor(node, vis) { | ||
this._containerNode = node; | ||
|
||
const nodeContens = document.createElement('div'); |
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.
nit: nodeContents
is misspelled
this._resize(); | ||
} | ||
|
||
await this._renderComplete$.take(1).toPromise(); |
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.
Observables don't start "listening" until they are subscribed to, which is being done by the .toPromise
call. If the renderComplete
event was fired before we got to this line, then this isn't going to do what we want.
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.
For each render() call, we're only interested in the first render-complete-call starting after line 59. Do we need to subscribe to that observable up front, or at the start of the method, or in the constructor when we create it?
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.
If the renderComplete
is only (and always) called after line 59 then the current approach should work.
@ppisljar still failing test, but could benefit from first look already |
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 small comments, but i really like the fact we are getting rid of angular! :)
|
||
const nodeContens = document.createElement('div'); | ||
nodeContens.innerHTML = ` | ||
<div class="tagcloud-vis"> |
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.
extract into html file and import it ?
if (!this._bucketAgg) { | ||
return; | ||
} | ||
const aggConfigResult = new AggConfigResult(this._bucketAgg, false, event, event); |
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.
this is now changed in master to use the bucket.createFilter and API.addFilters
const truncatedMessage = this._containerNode.querySelector('.tagcloud-truncated-message'); | ||
const incompleteMessage = this._containerNode.querySelector('.tagcloud-incomplete-message'); | ||
|
||
if (!this._vis.aggs[0] || !this._vis.aggs[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.
extract this condition to a new variable hasAggsDefined
so its easier to read ?
} | ||
|
||
const data = response.tables[0]; | ||
this._bucketAgg = data.columns[0].aggConfig; |
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.
get the agg from vis.aggs
instead of data ?
cf280b2
to
1eb7214
Compare
rebasing |
1fc584e
to
61c6a7e
Compare
} | ||
|
||
const bucketName = this._containerNode.querySelector('.tagcloud-custom-label'); | ||
bucketName.innerHTML = `${this._vis.aggs[0].makeLabel()} - ${this._vis.aggs[1].makeLabel()}`; |
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.
use textContent instead of innerHTML
71ad1bf
to
5de2935
Compare
jenkins, test this |
@@ -0,0 +1,121 @@ | |||
import TagCloud from './tag_cloud'; | |||
import tagCloudContainer from './tag_cloud_container.html'; |
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 made you choose to manually specify the container's html that is then modified using DOM methods/attributes as opposed to using React? This seems like it'd be a lot easier if we used React, and then we wouldn't have to manually ensure that we weren't opening ourselves up to XSS by ensure we're using the correct attributes on the elements themselves, and it'd be done automatically for us.
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.
Couple reasons imho:
What would React offer beyond adding another abstraction? What's the attack vector here that React would solve? The template is static content.
The async nature of the visualization is wrapped cleanly in the async .render()
call instead of wrapping this in a React component and then having to work around it.
We recommend that community users use the createBaseVisualization
since it is the most straightforward one (and the most simple interface to maintain). I think we should eat our own dogfood in a couple of places, here as good a place as any.
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 we should change that suggestion to use createBaseVisualization
with kibana 6.3 and suggest to use createReactVisualization
. and limit usage of createBaseVisualization
only for when visualization is based on some other rendering library (like d3 or leaflet).
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.
^ very much disagree :)
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 would React offer beyond adding another abstraction? What's the attack vector here that React would solve? The template is static content.
We're using node.textContent
appropriately below when setting the label, but if we were to set innerHtml
we open ourselves up to a potential XSS vulnerability (based on where the data comes from).
Additionally, we're dynamically setting styling throughout based on parameters when React provides a clear way to do so.
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.
dangerouslySetInnerHtml
is just as dangerous :)
i think with tagcloud (if going react way) we would need to rewrite whole tagcloud library. If the goal is getting rid of angular i think this current approach is good enough.
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 we should not at all impose a rendering-technology on our community developers. This almost as a matter of principle. We are not creating flexible interfaces when users need to follow the implementation-detail of the day. It used to be angular in Kibana, now it is React. Those are decisions that make sense for us (enforcing consistent tooling, enforcing consistent L&F ...), but have much less relevance for outside users.
Also, we need to really determine what the added value React brings as a wrapper for a Visualization-plugin. IMO this is very little for 80% of the visualizations. A visualization, almost by definition, is going to be not something textual or vanilla DOM-like and will rely on some other visualization library, that will introduce SVG, canvas, GL, clever use of HTML, ... What is React offering beyond a templating engine for that? Visualizations also should be a lot more asynchronous and stateful, so we can make efficient use of the DOM and animations. React doesn't really help with that, because those implementation details of how to do that efficiently will depend very much from visualization to visualization.
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.
btw: not saying we shouldn't rewrite this in react, just justificating my LGTM :)
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.
dangerouslySetInnerHtml is just as dangerous :)
Agreed, but we wouldn't need that here. We could grab the ref
and pass it to the TagCloud and let it do it's thing. It doesn't mean that the TagCloud itself couldn't do some nasty stuff, but at least the code that we currently "own" would get the default security mechanisms.
Also, we need to really determine what the added value React brings as a wrapper for a Visualization-plugin.
As soon as we end up straying from standard HTML elements, I agree with you. However, in this situation a templating language for HTML is exactly what we need.
I'm all for us getting rid of AngularJS, but I'm not following why we're doing all this manually in this situation. Using React here would be less code, more consistent with the current direction and more secure by default.
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.
My comment regarding the discussion can be found in the general PR comments :-)
hey @timroes, can you review too? need decision on whether we should use React here or not. thx! |
Before reviewing this, I also want to share my 2 cents regarding the React discussion. I think we shouldn't put any recommendations on the community, what they are using, so they can use base, React, etc. whatever they want - maybe we can get rid of the Angular one at some point, since the digest cycle is really causing troubles. Regarding what we should use and why to build the templates: I would totally agree with Brandon here, and think we gain a lot of benefit of using React also for some smaller things like that. container.innerHTML = `<div class="foo">
<div class="content">${vis.name}</div>
</div> That example above can accidentally happen rather early. If you would use React, you would usually have written that as: return (<div className="foo">
<div className="content">{ vis.name }</div>
</div>); and everything would be fine. Of course you can also create the same problem if you rewrite it to: return (<div className="foo">
<div className="content" dangerouslySetInnerHtml={vis.name}></div>
</div>); But it's way more unlikely that this will happen "by accident" as the above one. Also as soon as we have something like a loop of element or an condition, we usually already gain a lot of benefits from using React. For example if we look at the metrics visualization. By using React there, we suddenly don't clear the container on every render, and create elements within a loop again, but by using React there for the loop and the rendering, we basically just update the DOM with the stuff that actually changes... even if our render method is called way more often (which in our current infrastructure is the case). So by changing Metrics and Markdown Vis to React, we basically got from updating the DOM nearly every render approach with a handful of DOM nodes, to basically no update if it's not absolutely required. Also let's not talk about, how imperformant So my rule of thumb would be (for our visualizations, whether or not we recommend that to the community, I don't mind atm): As long as we need to create more than 1 or 2 elements, that need to be nested together, and for sure as soon as we have conditions or loops in there, let's use React for it. We will be safer and way more performant. If we just attach one canvas element and draw in this, or just one DOM node, that we pass to d3 (or something else), I am fine using Vanilla JS for it. So regarding this PR and the different error messages, I would second Brandon's opinion and would rather use React for that, since this would make line 50 to 76 imho way better readable and thus maintainable, and also more performant, since we wouldn't need to use |
c7c9ff1
to
036c277
Compare
💚 Build Succeeded |
add unit tests for Visualization interface
2c71f1a
to
ada0c89
Compare
rebasing with master broke this PR. please discard latest. |
💔 Build Failed |
reverting this back to the react way of setting the label and feedback message. linting rules prevent setting of .innerHTML directly. |
💚 Build Succeeded |
jenkins, test this |
💚 Build Succeeded |
- Implements tag_cloud as a Base Visualization - Use React for labels - Introduce screenshot comparison unit tests
Removes the angular dependency from tag cloud.