Skip to content

Conversation

@amirfefer
Copy link
Member

Work In Progress

This PR is written according to this design
ezgif com-video-to-gif

In this demonstration I've added <Fill> component in katello subscription details page, and a <Slot> in the upper left bar:

        <Fill id="test">
          <Nav navbar pullLeft className="navbar-iconic">
            <Button style={{ marginTop: '15px' }} bsStyle="primary"> Extenable Button !</Button>
          </Nav>
        </Fill>

@theforeman-bot
Copy link
Member

Issues: #25756

@amirfefer
Copy link
Member Author

amirfefer commented Dec 26, 2018

UPDATE: a slot can handle multiple Fills components, the rendering order will be by weights:
screenshot from 2018-12-26 18-31-17

Copy link
Member

@ohadlevy ohadlevy left a comment

Choose a reason for hiding this comment

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

Looks like a good start! I've added a few comments inline, plus there is an empty reducer file.


const components = {};

export const registerComponent = (SlotId, key, component, weight) => {
Copy link
Member

Choose a reason for hiding this comment

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

would register/unregister (or add/remove etc) are enough? I think the component should already part of the context, e.g. when you are using it:

import { add, remove } from './ExtendableRegistery';

}
};

export const getComponent = id =>
Copy link
Member

Choose a reason for hiding this comment

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

maybe worth comparing with the ruby implementation for menus e.g. at https://github.com/theforeman/foreman/blob/develop/app/registries/menu/manager.rb

class Fill extends React.Component {
componentDidMount() {
const { children, registerFillComponent, id, weight, fillId } = this.props;
debugger;
Copy link
Member

Choose a reason for hiding this comment

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

oops

removeRegisteredComponent(id, fillId);
}
render() {
return <div />;
Copy link
Member

Choose a reason for hiding this comment

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

TODO?

@glekner
Copy link
Contributor

glekner commented Dec 27, 2018

This is amazing!

Would be great to have an option to give props to <Fill /> instead of JSX.
I guess this means every Slot will need to have a default Fill in it that can receive props for it to be customizable.

@amirfefer
Copy link
Member Author

amirfefer commented Dec 31, 2018

Great idea @glekner !
As you suggested, a Fill can contain JSX or plain object as props, with this logic plugins may totally override a slot or just modify the props.

Props way

// plugin
<Fill id='slot-id' fillId='some-id' overrideProps={{ text: 'this text given by a prop' }} /> 
// foreman core
const Wrapper = ({ text }) => <div>{text}</div>; 
<Slot id='slot-id'>
  <Wrapper text='some default text' />
</Slot>

JSX way

// plugin
<Fill id='slot-id' fillId='some-id'> 
  <div> some text </ div>
</ Fill>
// foreman core
<Slot id='slot-id'>
 default children // can be empty
</Slot>


export const remove = (SlotId, key) => {
if (components[SlotId]) {
components[SlotId].forEach((item, index) => {
Copy link
Contributor

@xprazak2 xprazak2 Jan 2, 2019

Choose a reason for hiding this comment

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

nit: have you considered using filter?

Copy link
Member Author

Choose a reason for hiding this comment

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

filter creates a new array, while using splice the removing process is in place.
we can use filter and splice, having something like:

obj.splice(0, obj.length, ...obj.filter(item => item.key !== key))

Copy link
Contributor

@sharvit sharvit left a comment

Choose a reason for hiding this comment

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

Awesome work @amirfefer 🥇

componentWillUnmount() {
const { id, removeRegisteredComponent, fillId } = this.props;

removeRegisteredComponent(id, fillId);
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: unregisterFillComponent?

if (isValidElement(object)) {
return cloneElement(object, props);
}
return cloneElement(children, object);
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't you keep the old props? return cloneElement(children, { ...props, ...object });

export const reducers = { extends: reducer };

// export connected component
export default connect(
Copy link
Contributor

Choose a reason for hiding this comment

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

should be added into component registry, same for Slot

@@ -0,0 +1,7 @@
module ExtendableComponentsHelper
def slot(slot_id, multi=false)

Choose a reason for hiding this comment

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

Layout/SpaceAroundEqualsInParameterDefault: Surrounding space missing in default value assignment.

@@ -0,0 +1,24 @@
import { REGISTER_FILL, REMOVE_FILLED_COMPONENT } from './FillConstants';
import { add, remove } from './ExtendableRegistery';
Copy link
Contributor

Choose a reason for hiding this comment

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

Google knows only the version without 'e', could you rename please?


case REMOVE_FILLED_COMPONENT:
return state.setIn(
['RegisteredComponent', payload.slotId, payload.fillId],
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as comment on the other end.

</div>
</div>

<%= slot('about-footer-slot', true) %>
Copy link
Contributor

Choose a reason for hiding this comment

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

Needs to be inside div#about tag, so it does not show all the way down:

@waldenraines
Copy link

@amirfefer can you rebase this so I can test it out please?

@amirfefer
Copy link
Member Author

I'm closing this PR because I opened another one
#6849

@amirfefer amirfefer closed this Jun 18, 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.

9 participants