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

Slots in Volto #1430

Closed
sneridagh opened this issue Apr 27, 2020 · 10 comments
Closed

Slots in Volto #1430

sneridagh opened this issue Apr 27, 2020 · 10 comments

Comments

@sneridagh
Copy link
Member

We need to increase the "insertion points" in Volto by using something close to Plone Viewlets/Portlets/Macros. I would run from these names, and go for something more generic and not Plone-ish, to avoid confusion. I suggest to use "slots".

Macros-ish:
#1424

Viewlet-ish:
https://github.com/eea/volto-addons/tree/master/src/Viewlets

Portlet-ish?

We need to find time to discuss this.

@sneridagh
Copy link
Member Author

#1397

@tiberiuichim
Copy link
Contributor

tiberiuichim commented Apr 28, 2020

I like "Slots".

I think portlets are a different story and, for their use case, they're unavoidable. They have database storage, can be configured TTW and they have inheritance. Whatever system would be created to replace them would just reimplement portlet storage and definitions.

Let's take a simple use case: the website editor wants to add a static text notification in a section of a website. Right now, in classic Plone, all he has to do is create a new Static Text portlet and it will be inherited in that section (subfolders, etc). There's no way to have this in Volto right now.

The implementation I had in mind for the so-called "viewlets" was that they would allow a centralized place to register <Portal> components. Nicola's proposal requires to customize (jbot style) the macro file, while my sketched proposal was to say "just declare what Portal nodes you want on a particular route, and I'll render them for you". If I were to extend my implementation, the configuration for the Slots would look something like this:

 config.slots = {
     aboveDocumentTitle: [
         { path: '/', component: ForestMetadata }
     ]
}

And then, in the appropriate places, a component would be inserted like:

<SlotRenderer name="aboveDocumentTitle" />

An addon would add a new slot insertion such as:

config.slots.aboveDocumentTitle.push({path:'/', component: ExtraComponent})

@sneridagh
Copy link
Member Author

aboveDocumentTitle oh man, are we doing this again, isn't it? 😀 I like it.

@nzambello I implemented <AppExtras /> component to support whatever you want to put before the body is closed (GAnalytics, Matomo, etc...) Shadowing that would allow integrators to put whatever in that component. But if we want to go further (so we want to allow the addons system to use that "slot" and append things there, more than overriding them) we will be on the right track.

However, I would like to discuss this in depth because I still see some use cases, where a simple solution might be ok. Let's schedule a meeting to talk about this!

Regarding portlets I like to see them more like Viewlets that can be configured and the config stored. When one say Viewlets, one can say blocks :) I fiddled around with the concept, and works pretty well, I even created a BlocksRenderer wrapper to be able to instantiate blocks anywhere in the site. The only thing is to know where the info is going to be stored.

@tiberiuichim
Copy link
Contributor

aboveDocumentTitle

I've mentioned it because it's the only viewlet that I can name by heart, and even then I don't think I got the name right.

Let's take a simple use case: I have a behavior called IExtendedMetadata whatever. It has several tagging and metadata fields that are used for to group and semantically decorate content. I can enable this behavior on several content types, including some that are block-powered. Next, I want a box with this metadata to appear on all pages that have these fields. Sure, I can shadow DefaultView.jsx and insert my component there, but that means that I will have to maintain that customized file. I can mostly achieve the same using Portals, but I still need a way to trigger the rendering of these Portal components and conditionally rendering portals is tricky.

@sneridagh
Copy link
Member Author

@tiberiuichim I like the idea and the implementation! Implementations change over time, but good ideas/concepts don’t. So I’m +1 to bring the slots conceptualization in the same way of Plone Viewlets.

@tiberiuichim
Copy link
Contributor

There's also old #16 which suggests looking at react-fill-slots. I've looked at it, it's an old library by now and I think outdated by today's standards. I also don't think there's a need for it if we use the system described above.

@sneridagh sneridagh linked a pull request May 31, 2020 that will close this issue
@sneridagh
Copy link
Member Author

sneridagh commented Oct 30, 2020

Had a rethought about it and a conversation with @tiberiuichim I'll try to summarize what we spoke about:

  • Have insertion points more than one-time overridable/shadowed-able components
  • This insertion points can be populated with
    • Blocks
    • "portlet"-ish components (navigation component)
    • Arbitrary slot-ish components from the Volto registry, parameterized
  • Three layers of customization, can sum or override:
    • Per config (statically, per path, inheritable)
    • Per backend (user defined, stored in the object, like portlets)
    • Portalled, via insertion points
  • The insertion point should have a hook where other components can populate some piece of code there, via portals

I see slots more than an evolution of the portlet paradigm, but a merge between Viewlets Managers and Portlets Managers, all at once. The slots could not only contain user parameterizable (persistent config and data) components (mainly blocks) but also static context aware components (aka viewlets) assigned to a place (slot) in the layout. Inheritance/block/per content type/group are still valid and valuable use cases. The ability to pre-define the slots per content type (like the new Volto blocks layout per content type feature) is also a nice to have. Some portlet use case are still capital i.e. navigation portlet.

The portlet engine can still be the foundation of the slots, even in the most simple form (create a portlet that can hold JSON to store the slot blocks.

Example: Doormat
We would like to have an user customizable Doormat (footer slot) that contains columns with Blocks (text, images or any other block). These blocks would need to be saved somewhere and be inherited to all the content tree.

Example: Typical aside portlets slots
We would like an user to be able to add and arrange blocks side by side to the content, in a vertical fashion. We should also be able to add a navigation "portlet". From where they are set, they are inherited to children objects.

(add more examples here)

To improve and avoid the shadowing hell we could also make the most of the basic Volto "Viwelets" to have a viewlet manager where you can add or remove components:

Example: App.jsx
One end up by overriding App.jsx for adding components in the layout. We should avoid that by using more specific organization (Footer, TopHeader, etc) then add/remove things from there via slots definitions.

@tiberiuichim
Copy link
Contributor

Further discussions:

  • we go for a separate plone implementation, based on annotation storage. We'll need a new endpoint and expand
  • we'll want to reuse blocks as "Slot components". Maybe have a "slottable" setting if we want to exclude some
  • there will be global slots components and "local" slot components. The global slots can be registered separately the same way as blocks, and you can declare in your project the "slots layout +data" for the slots.
  • Once you add a "local slot component" to a context, it creates a copy of the "global layout". In the edit component, the global slots will be "locked", but you'll be able to reorder the "slots components". Nice to have, to be able to "unlock" a global component and edit it "locally".
  • On global layout change we'll do a bit of "conflict resolution", basically identifying where to insert, in the final output, the slots that were added globally. In any case, once an editor sees an order that seems "wrong" in a certain context, they can just fix it for that context.

@perret123
Copy link

perret123 commented Feb 16, 2023

I would like to be able to add "Slots" only to specific Views which are bound to specific Content Types.

I think it would be quite nice if I could do something like the following in a View-File:

  <div id="page-document" className="ui container viewwrapper eduproduct-view">
       <div class="ui two grid">
          <div class="column left" style={{ flex: '1' }}>
             <RenderBlocks content={content} slotKey="mainContent"  />
           </div>
           <div class="column right" style={{ flex: '0 0 100px' }}>
              <RenderBlocks content={content} slotKey="sidebar"  />
           </div>
       </div>
   </div>

In this example, in the Editing-UI, the content editors could use two "lanes" of blocks instead of only one.

What do you think about this?

Probably it would also be nice to restrict the use of block-types for different "slot-keys".

If this is already somehow possible with Volto and I just missed it, please advice :-) Thank you :)

@davisagli
Copy link
Member

Done in #5775

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging a pull request may close this issue.

6 participants