Skip to content
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

Closed

Conversation

ezr-ondrej
Copy link
Member

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.

@theforeman-bot
Copy link
Member

Issues: #26078

@ares
Copy link
Member

ares commented Feb 19, 2019

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 :-)

Copy link
Member

@amirfefer amirfefer left a 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:

  1. @boaz0 's implementation for patternfly tables is almost done, I think it would be better to use it
  2. Please use our folder structure
  3. 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
  4. 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.

@@ -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');
Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Member

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

app/assets/javascripts/host_edit_interfaces.js Outdated Show resolved Hide resolved
app/assets/javascripts/host_edit_interfaces.js Outdated Show resolved Hide resolved
<th>{__('Actions')}</th>
</tr>
</thead>
<tbody>{this.renderInterfaces(interfaces)}</tbody>
Copy link
Member

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

Copy link
Member Author

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) => {
Copy link
Member

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.


// provider specific
if (typeof window.providerSpecificNICInfo === 'function')
return window.providerSpecificNICInfo($(this.getHiddenFields()));
Copy link
Member

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.

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.

Copy link
Member Author

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.

}

editInterface() {
window.edit_interface(this.props.id);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Member Author

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.

@iNecas
Copy link
Member

iNecas commented Feb 20, 2019

FYI @ezr-ondrej I guess this is the table PR @amirfefer had in mind

@ezr-ondrej ezr-ondrej force-pushed the redux_store_subscribe branch from cc07b43 to b2d83b7 Compare February 27, 2019 17:02
@ezr-ondrej ezr-ondrej force-pushed the redux_store_subscribe branch 2 times, most recently from 9cc4d0f to 702c9eb Compare February 27, 2019 18:27
@ezr-ondrej ezr-ondrej force-pushed the redux_store_subscribe branch from 702c9eb to f1e2e80 Compare February 27, 2019 18:57
@tbrisker tbrisker added the WIP label Mar 10, 2019
@Ron-Lavi
Copy link
Member

what's the status of this PR? thanks

@ezr-ondrej
Copy link
Member Author

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 :)

@tbrisker
Copy link
Member

closing following discussion with @ezr-ondrej. Thanks everyone!

@tbrisker tbrisker closed this Aug 21, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants