Jetspeed 2
  1. Jetspeed 2
  2. JS2-468

Customizer cannot edit nested layouts.

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0-FINAL, 2.1-dev
    • Fix Version/s: 2.1-dev, 2.1
    • Component/s: Decorations/Themes, Layout
    • Labels:
      None

      Description

      Customization of nested layouts using the columns and tcolumns layout templates is not functional. The page actions used to invoke the Customizer are now page centric, as are access to content used by the Customizer. The Customizer should now operate on the layout tree that belongs to the page, but it is not capable of operating on anything beyond a single multicolumn layout. Also, the interface of the existing Customizer may not be sufficiently intuitive or sophisticated to operate on nested layouts.

      1. snapshot4.png
        18 kB
        Ate Douma
      2. snapshot3.png
        32 kB
        Ate Douma
      3. snapshot2.png
        38 kB
        Ate Douma
      4. snapshot1.png
        32 kB
        Ate Douma

        Activity

        Hide
        Ate Douma added a comment -

        I'm going to provide a solution to the customization of nested layouts by introducing a Page "edit" state.
        And I will get both the columns and the tcolumns based layouts fully in sync again.
        Then, I'm going to extend the Customizer to allow adding (nested) layouts itself.
        And finally, I will provide customization to the customizer itself using the (root) layout decorator.properties.

        Page scoped "edit" state
        ================
        Currently, layout "edit" state is handled through the PortletMode EDIT of the concerning Layout Portlet.
        But, as noted by Randy above, this doesn't really match with the more Page scoped actions from the Customizer.

        Thus, I will introduce a PageEditAccess component (interface) which will provide the current page "edit" state,
        as well as information if the page is allowed to be edited.
        As we already maintain a component called PageActionAccess internally for mapping current page fragments access,
        I will simply extend that component and provide the PageEditAccess features as an interface extension.

        As result of this change, page edit state will become independent of a specific LayoutPortlet PortletMode.
        More specifically, setting a Page in edit state doesn't change any LayoutPortlet PortletMode anymore.

        As a side-effect (but intentionally as I needed this myself anyway) of this, a root LayoutPortlet no longer needs
        to support PortletMode.EDIT (via its portlet.xml definition). If it doesn't support it, it simply means the
        root Layout won't be editable.

        Another page level feature currently tied to the root LayoutPortlet I won't replace yet: Page Help.
        Right now this is, and will remain so, only available when the root LayoutPortlet supports PortletMode.HELP.

        Finally, I'm going to move the last page level action, Adding A Portlet through the popup Portlet Selector, to
        each individual (and editable) Layout. This really is needed to be able to support nested layouts.

        Currently, the PageActionAccess component is initialized in two locations: in the DecoratorValve and in the
        JetspeedPowerTool (legacy usage). I will move the PageActionAccess and the related DecorationAction classes
        to the decoration package as well as remove the legacy code from the JPT (no longer needed).

        Adding Layouts through the Customizer
        =========================
        After getting nested layouts properly working, including moving and deleting both portlets and layouts itself,
        the logical next step was adding (nested) layouts through the Customizer itself.
        Already, the customizer allowed changing a layout type.
        I'm going to remove the "auto change" of the layout type when the user selects a different one in the poplist.
        As result, the same poplist can then be used for both changing the type as adding a new layout (within the
        current one). For this, I'm going to provide two new buttons ("Change" and "Add") after the poplist.

        Side note: The Customizer "bar" now provides a lot of features (if all are enabled that is, see next section
        about customizing below). Besides adding a new Layout, a new Page (for root Layouts only), the "Add a Portlet"
        icon too now has to be provided here. This "+" icon itself really wasn't indicative enough anymore, so I added
        a "Portlet:" label in front of it (see also the screenshot I'll be attaching to this issue).

        Customizing the Customizer
        =================
        Although layouts itself now can be added through the Customizer, too many nested layouts isn't really going to be manageable.
        So by default this is restricted to 2 levels. But this is configurable using the root layout decorator.properties.
        And, other features for the Customizer can be configured (disabled) now likewise.
        The default settings are:

        allow.change.page.theme=true
        allow.change.layout=true
        max.layout.nesting=2
        allow.add.page=true
        allow.add.portlet=true
        allow.change.portlet.decorator=true

        Note: Changing the page theme and adding a page are only going to be provided by the root Layout Customizer anyway.

        Backwards compatibility
        ===============
        The above described changes are many...
        Custom extensions and/or implementations of especially the Layout Portlets and the related layout templates
        (columns.vm and tcolumns.vm) will have to be checked carefully and be upgraded.
        Most important changes will be those to the form fields in the layout templates and the related handling within the
        MultiColumnLayoutPortlet.
        I initially tried to only use the current definitions, but that turned out to be almost impossible and became very
        awkward too. So, you really need to check the template changes (they have become much simpler though...)

        Another change which might impact custom extensions is that the MultiColumnLayoutPortlet won't be delegating "add"
        and "delete" handling of portlets to its parent LayoutPortlet anymore. I did extend the LayoutPorlet to support
        nested layout handling, but the actual usage is only from the MultiColumnLayoutPortlet.

        Show
        Ate Douma added a comment - I'm going to provide a solution to the customization of nested layouts by introducing a Page "edit" state. And I will get both the columns and the tcolumns based layouts fully in sync again. Then, I'm going to extend the Customizer to allow adding (nested) layouts itself. And finally, I will provide customization to the customizer itself using the (root) layout decorator.properties. Page scoped "edit" state ================ Currently, layout "edit" state is handled through the PortletMode EDIT of the concerning Layout Portlet. But, as noted by Randy above, this doesn't really match with the more Page scoped actions from the Customizer. Thus, I will introduce a PageEditAccess component (interface) which will provide the current page "edit" state, as well as information if the page is allowed to be edited. As we already maintain a component called PageActionAccess internally for mapping current page fragments access, I will simply extend that component and provide the PageEditAccess features as an interface extension. As result of this change, page edit state will become independent of a specific LayoutPortlet PortletMode. More specifically, setting a Page in edit state doesn't change any LayoutPortlet PortletMode anymore. As a side-effect (but intentionally as I needed this myself anyway) of this, a root LayoutPortlet no longer needs to support PortletMode.EDIT (via its portlet.xml definition). If it doesn't support it, it simply means the root Layout won't be editable. Another page level feature currently tied to the root LayoutPortlet I won't replace yet: Page Help. Right now this is, and will remain so, only available when the root LayoutPortlet supports PortletMode.HELP. Finally, I'm going to move the last page level action, Adding A Portlet through the popup Portlet Selector, to each individual (and editable) Layout. This really is needed to be able to support nested layouts. Currently, the PageActionAccess component is initialized in two locations: in the DecoratorValve and in the JetspeedPowerTool (legacy usage). I will move the PageActionAccess and the related DecorationAction classes to the decoration package as well as remove the legacy code from the JPT (no longer needed). Adding Layouts through the Customizer ========================= After getting nested layouts properly working, including moving and deleting both portlets and layouts itself, the logical next step was adding (nested) layouts through the Customizer itself. Already, the customizer allowed changing a layout type. I'm going to remove the "auto change" of the layout type when the user selects a different one in the poplist. As result, the same poplist can then be used for both changing the type as adding a new layout (within the current one). For this, I'm going to provide two new buttons ("Change" and "Add") after the poplist. Side note: The Customizer "bar" now provides a lot of features (if all are enabled that is, see next section about customizing below). Besides adding a new Layout, a new Page (for root Layouts only), the "Add a Portlet" icon too now has to be provided here. This "+" icon itself really wasn't indicative enough anymore, so I added a "Portlet:" label in front of it (see also the screenshot I'll be attaching to this issue). Customizing the Customizer ================= Although layouts itself now can be added through the Customizer, too many nested layouts isn't really going to be manageable. So by default this is restricted to 2 levels. But this is configurable using the root layout decorator.properties. And, other features for the Customizer can be configured (disabled) now likewise. The default settings are: allow.change.page.theme=true allow.change.layout=true max.layout.nesting=2 allow.add.page=true allow.add.portlet=true allow.change.portlet.decorator=true Note: Changing the page theme and adding a page are only going to be provided by the root Layout Customizer anyway. Backwards compatibility =============== The above described changes are many... Custom extensions and/or implementations of especially the Layout Portlets and the related layout templates (columns.vm and tcolumns.vm) will have to be checked carefully and be upgraded. Most important changes will be those to the form fields in the layout templates and the related handling within the MultiColumnLayoutPortlet. I initially tried to only use the current definitions, but that turned out to be almost impossible and became very awkward too. So, you really need to check the template changes (they have become much simpler though...) Another change which might impact custom extensions is that the MultiColumnLayoutPortlet won't be delegating "add" and "delete" handling of portlets to its parent LayoutPortlet anymore. I did extend the LayoutPorlet to support nested layout handling, but the actual usage is only from the MultiColumnLayoutPortlet.
        Hide
        Ate Douma added a comment -

        First screenshot showing a page with every feature of the customizer enabled using the default configuration settings.

        psml definition (id's stripped for readability):
        <page id="/_user/user/test.psml" hidden="false">
        <title>test</title>
        <short-title>test</short-title>
        <defaults layout-decorator="tigris" portlet-decorator="tigris"/>
        <fragment type="layout" name="jetspeed-layouts::VelocityTwoColumns2575">
        <fragment type="portlet" name="demo::BookmarkPortlet">
        <property name="row" value="0"/>
        <property name="column" value="0"/>
        </fragment>
        <fragment type="layout" name="jetspeed-layouts::VelocityOneColumn">
        <fragment type="portlet" name="demo::BookmarkPortlet"/>
        <fragment type="layout" name="jetspeed-layouts::VelocityTwoColumns">
        <fragment type="portlet" name="demo::BookmarkPortlet"/>
        <fragment type="portlet" name="demo::BookmarkPortlet">
        <property name="row" value="1"/>
        <property name="column" value="0"/>
        </fragment>
        </fragment>
        </fragment>
        </fragment>
        </page>

        Show
        Ate Douma added a comment - First screenshot showing a page with every feature of the customizer enabled using the default configuration settings. psml definition (id's stripped for readability): <page id="/_user/user/test.psml" hidden="false"> <title>test</title> <short-title>test</short-title> <defaults layout-decorator="tigris" portlet-decorator="tigris"/> <fragment type="layout" name="jetspeed-layouts::VelocityTwoColumns2575"> <fragment type="portlet" name="demo::BookmarkPortlet"> <property name="row" value="0"/> <property name="column" value="0"/> </fragment> <fragment type="layout" name="jetspeed-layouts::VelocityOneColumn"> <fragment type="portlet" name="demo::BookmarkPortlet"/> <fragment type="layout" name="jetspeed-layouts::VelocityTwoColumns"> <fragment type="portlet" name="demo::BookmarkPortlet"/> <fragment type="portlet" name="demo::BookmarkPortlet"> <property name="row" value="1"/> <property name="column" value="0"/> </fragment> </fragment> </fragment> </fragment> </page>
        Hide
        Ate Douma added a comment -

        Second snapshot (snapshot2.png) is a correction for the previous for which I had allow.change.portlet.decorator=false set.
        This one really shows every feature enabled, so really without any custom settings in the (tigris) layout decorator.

        Also corrected psml definition (showing overridden blue-gradient portlet-decorator):
        <page id="/_user/user/test.psml" hidden="false">
        <title>test</title>
        <short-title>test</short-title>
        <defaults layout-decorator="tigris" portlet-decorator="tigris"/>
        <fragment type="layout" name="jetspeed-layouts::VelocityTwoColumns2575">
        <fragment type="portlet" name="demo::BookmarkPortlet">
        <property name="row" value="0"/>
        <property name="column" value="0"/>
        </fragment>
        <fragment type="layout" name="jetspeed-layouts::VelocityOneColumn">
        <fragment type="portlet" name="demo::BookmarkPortlet"/>
        <fragment type="layout" name="jetspeed-layouts::VelocityTwoColumns">
        <fragment type="portlet" name="demo::BookmarkPortlet"/>
        <fragment type="portlet" name="demo::BookmarkPortlet" decorator="blue-gradient">
        <property name="row" value="1"/>
        <property name="column" value="0"/>
        </fragment>
        </fragment>
        </fragment>
        </fragment>
        </page>

        Show
        Ate Douma added a comment - Second snapshot (snapshot2.png) is a correction for the previous for which I had allow.change.portlet.decorator=false set. This one really shows every feature enabled, so really without any custom settings in the (tigris) layout decorator. Also corrected psml definition (showing overridden blue-gradient portlet-decorator): <page id="/_user/user/test.psml" hidden="false"> <title>test</title> <short-title>test</short-title> <defaults layout-decorator="tigris" portlet-decorator="tigris"/> <fragment type="layout" name="jetspeed-layouts::VelocityTwoColumns2575"> <fragment type="portlet" name="demo::BookmarkPortlet"> <property name="row" value="0"/> <property name="column" value="0"/> </fragment> <fragment type="layout" name="jetspeed-layouts::VelocityOneColumn"> <fragment type="portlet" name="demo::BookmarkPortlet"/> <fragment type="layout" name="jetspeed-layouts::VelocityTwoColumns"> <fragment type="portlet" name="demo::BookmarkPortlet"/> <fragment type="portlet" name="demo::BookmarkPortlet" decorator="blue-gradient"> <property name="row" value="1"/> <property name="column" value="0"/> </fragment> </fragment> </fragment> </fragment> </page>
        Hide
        Ate Douma added a comment -

        Third and last snapshot of the same page but with a readonly root layout and
        allow.change.portlet.decorator=false defined in the tigris layout decorator.properties.

        The psml definition with a readonly (no PortletMode EDIT nor HELP support) root layout portlet:
        <page id="/_user/user/test.psml" hidden="false">
        <title>test</title>
        <short-title>test</short-title>
        <defaults layout-decorator="tigris" portlet-decorator="tigris"/>
        <fragment type="layout" name="jetspeed-layouts::VelocityTwoColumns2575NoActions">
        <fragment type="portlet" name="demo::BookmarkPortlet">
        <property name="row" value="0"/>
        <property name="column" value="0"/>
        </fragment>
        <fragment type="layout" name="jetspeed-layouts::VelocityOneColumn">
        <fragment type="portlet" name="demo::BookmarkPortlet"/>
        <fragment type="layout" name="jetspeed-layouts::VelocityTwoColumns">
        <fragment type="portlet" name="demo::BookmarkPortlet"/>
        <fragment type="portlet" name="demo::BookmarkPortlet" decorator="blue-gradient">
        <property name="row" value="1"/>
        <property name="column" value="0"/>
        </fragment>
        </fragment>
        </fragment>
        </fragment>
        </page>

        Show
        Ate Douma added a comment - Third and last snapshot of the same page but with a readonly root layout and allow.change.portlet.decorator=false defined in the tigris layout decorator.properties. The psml definition with a readonly (no PortletMode EDIT nor HELP support) root layout portlet: <page id="/_user/user/test.psml" hidden="false"> <title>test</title> <short-title>test</short-title> <defaults layout-decorator="tigris" portlet-decorator="tigris"/> <fragment type="layout" name="jetspeed-layouts::VelocityTwoColumns2575NoActions"> <fragment type="portlet" name="demo::BookmarkPortlet"> <property name="row" value="0"/> <property name="column" value="0"/> </fragment> <fragment type="layout" name="jetspeed-layouts::VelocityOneColumn"> <fragment type="portlet" name="demo::BookmarkPortlet"/> <fragment type="layout" name="jetspeed-layouts::VelocityTwoColumns"> <fragment type="portlet" name="demo::BookmarkPortlet"/> <fragment type="portlet" name="demo::BookmarkPortlet" decorator="blue-gradient"> <property name="row" value="1"/> <property name="column" value="0"/> </fragment> </fragment> </fragment> </fragment> </page>
        Hide
        Ate Douma added a comment -

        Ok, one more
        A final snapshot of the page when in normal "view" mode.

        Show
        Ate Douma added a comment - Ok, one more A final snapshot of the page when in normal "view" mode.
        Hide
        Ate Douma added a comment -

        All above features are committed.

        Show
        Ate Douma added a comment - All above features are committed.
        Hide
        Ate Douma added a comment -

        Closed again now properly recorded against Fix Version 2.1 as well

        Show
        Ate Douma added a comment - Closed again now properly recorded against Fix Version 2.1 as well

          People

          • Assignee:
            Ate Douma
            Reporter:
            Randy Watler
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development