-
Notifications
You must be signed in to change notification settings - Fork 994
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
[WIP] Fixes #26078 - interface table in react #6490
Conversation
Issues: #26078 |
16fc933
to
cc07b43
Compare
In general, I like the direction. The interface form is extended by REX plugin, so we'll need to wait until slot/fill is done. But I suppose @theforeman/ui-ux or anyone else can start looking 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.
@ezr-ondrej Thanks for this great contribution 👍
few general feedback:
- @boaz0 's implementation for patternfly tables is almost done, I think it would be better to use it
- Please use our folder structure
- We need to have a better way for invoking legacy functions in react component, IMHO this approach
(using the window object for calling functions) mix the react with legacy in a way that bugs might occur and makes it harder to understand and maintain, especially if we wish to deprecate parts of it someday.
Using redux can be a solution, so a react component can invoke an action that change a specific part of the store, which a legacy function can observe. with this approach we can keep our react code and legacy code isolated, but still affect each other - we do have a re-design task for the host creation in our roadmap (Host creation wizard), however I think it should be planned well before the implementation, according to up to date mocks and user stories.
app/assets/javascripts/host_edit.js
Outdated
@@ -5,6 +5,8 @@ $(document).on('AddedClass', function(event, link){load_puppet_class_parameters( | |||
|
|||
function update_nics(success_callback) { | |||
var data = serializeForm().replace('method=patch', 'method=post'); | |||
tfm.reactMounter.unmount('#interfaceListWrapper'); |
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.
Maybe I missed something but is it necessary to unmount the component ? how about changing its data and by that forcing re-render?
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 is not necessary, but the dom is going to be gone, after this method is done.
So I thought it would be nice to clean up.
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 dom is going to be gone, unmount
will be invoked automatically here
<th>{__('Actions')}</th> | ||
</tr> | ||
</thead> | ||
<tbody>{this.renderInterfaces(interfaces)}</tbody> |
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
object should be bind, you can use bindMethods
helper function
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 sure? I thought it is necessary just in callbacks, this is not callback, it is ordinary call.
} | ||
} | ||
|
||
const mapStateToProps = (state, ownProps) => { |
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 split the component logic and the redux wrapper.
The component's folder strucutre should look like:
webpack/assets/javascripts/react_app/components/<Compoment-name>
├── <Compoment-name>Actions.js
├── <Compoment-name>Reducer.js
├── <Compoment-name>.fixtures.js
├── <Compoment-name>.scss.js // if needed
├── <Compoment-name>.js
├── index.js // the redux connected file
└── __tests__
├── <Compoment-name>Actions.test.js
├── <Compoment-name>Reducer.test.js
├── <Compoment-name>.test.js
├── integration.test.js
└── __snapshots__
├── All snapshot files (created automatlicy by `npm test -- -u`)
for a good example you can have a look on Layout
or BreadcrumbsBar
components.
webpack/assets/javascripts/react_app/components/hosts/interfaces/InterfaceRow/index.js
Outdated
Show resolved
Hide resolved
webpack/assets/javascripts/react_app/components/hosts/interfaces/InterfaceRow/index.js
Outdated
Show resolved
Hide resolved
|
||
// provider specific | ||
if (typeof window.providerSpecificNICInfo === 'function') | ||
return window.providerSpecificNICInfo($(this.getHiddenFields())); |
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 looks like an anti-pattern, note that this element is a dom element, while react uses the virtual dom.
so mixing these elements inside a react component may lead to some errors (for instance, the real dom element could not be exist while the component is re-rendered).
IMO we need to find a better solution for calling legacy functions inside a react component, because with this way it would much more complicated remove old code.
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, this is an anti-pattern and creates technical debt. I like @amirfefer's suggestion of using redux to communicate between jquery and react.
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 can clearly see that it is an anti-pattern :) I just am not sure what to do about it, I can shove it in the webpack, to look more clean. But the method is in the window, because the technical debt from past. I am all for moving it in the webpack, but it will throw away the support to be extendible by more providers the same way it was - basically it will throw the API support. And I am not sure till what level we can do that 🤔 I was thinking about some deprecations, but I don't know what is the best way to do this thinks in the future.
I will try to talk about it with @amirfefer, but I don't feel like it should be addressed in this PR.
webpack/assets/javascripts/react_app/components/hosts/interfaces/InterfaceRow/index.js
Outdated
Show resolved
Hide resolved
} | ||
|
||
editInterface() { | ||
window.edit_interface(this.props.id); |
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.
ditto
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.
solved through setting up the interface editing
property and if that is true, we open the modal window from the legacy code.
FYI @ezr-ondrej I guess this is the table PR @amirfefer had in mind |
cc07b43
to
b2d83b7
Compare
9cc4d0f
to
702c9eb
Compare
702c9eb
to
f1e2e80
Compare
what's the status of this PR? thanks |
Still in WIP. But if @amirfefer, @LaViro or/and @sharvit would like to have serious discussion about this one next week, I have some time on Friday and I could push it to a "hackable" state. Just ping me if that is the case :) |
closing following discussion with @ezr-ondrej. Thanks everyone! |
I have tried to unwrap the mess we got in the host form.
This could have been the first step. I tried to be not-so intrusive and keep as much as possible untouched, but with bringing some improvements.
Interfaces table is already react component, but otherwise form stays the same.
The interfaces data are stored in redux and all the changes are made through redux action calls.
Changes are written to the interfaces hidden forms by observing the store.
To consider:
Any comments are welcome.