Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info

This documentation is still a work-in-progress.
Pending PR: https://github.com/DSpace/dspace-angular/pull/3994


The menu sections will be generated by multiple “Providers” which will each add a section or list of related sections. These providers will then be added to the list of providers per menu defined in the app.menus.ts file.

export const MENUS = buildMenuStructure({  
  [MenuID.PUBLIC]: [  
    CommunityListMenuProvider,  
    BrowseMenuProvider,  
    StatisticsMenuProvider,  
  ],  
  [MenuID.ADMIN]: [  
    NewMenuProvider,  
    EditMenuProvider,  
    ... 
    SystemWideAlertMenuProvider,  
  ],  
  [MenuID.DSO_EDIT]: [  
    DsoOptionMenuProvider.withSubs([  
      SubscribeMenuProvider.onRoute(  
        MenuRoute.SIMPLE_COMMUNITY_PAGE,  
        MenuRoute.SIMPLE_COLLECTION_PAGE,  
      ),  
      ...
      ClaimMenuProvider.onRoute(  
        MenuRoute.SIMPLE_ITEM_PAGE,  
        MenuRoute.FULL_ITEM_PAGE,  
      ),  
    ]),  
  ],  
});

This approach makes it way more intuitive to see what kind of sections there are and to add new sections in between already existing ones.

This new version fully removes the old way of adding route based data (e.g. statistics) and replaces it with a new way where you can easily add routes to specified providers and/or retrieve route data in the provider to be used for its sections. It also adds support to separately define a parent sections with various child sections. The latter will be mostly useful for creating sections on the DSO pages where you can now separately define the parent section through a provider and then add child providers for the various different sections.

For example, in the current implementation all the buttons on the DSO pages have been added to a single parent parent section resulting in a single button on the DSO pages with the relevant sections in the dropdown. In case sections need to be moved, the provider can simply be moved to a different location such as before the provider responsible for providing the button (DsoOptionMenuProvider).

Finally, since the menus have been moved from the resolvers to the InitService, the menus will not delay the page from loading when the menu sections need some time. The menus will simply appear when they are fully loaded. To prevent "blinking" when changing pages, the sections that need to be added/removed are all done at the same time.

The following properties can be set on the level of a provider when creating a new one:

  • shouldPersistOnRouteChange - When true, the sections of this provider will be retained when swapping routes. This is useful for route independent menus such as the community-list link, browse options and admin sidebar menu sections

    • This is by default set on true.

    • The default behaviour is overwritten when the onRoute static method is used, or the AbstractRouteContextMenuProvider is extended, then it is automatically set to false since the section are dependent on the route. See below for more information.

  • alwaysRenderExpandable - When true, this will render the sections of this provider as something that is expected to be expandable and have children. When a section of this provider has no children, it will be hidden. When false, the section will always be rendered, even if no children are visible.

    • This is by default set to false.

    • The default value will be set to true when AbstractExpandableMenuProvider is extended and will be applied to the top section for this provider.

    • Example of a manual overwrite can be found in DsoOptionMenuProvider. This is done to ensure the "option" button is hidden when no entries are present in the dropdown.

The sections still contain the same configuration properties as before the refactor, however a lot of the properties will be already set by the providers. There are however some parts that still need to be provided per sections:

  • visible - Whether the section should be visible. This is most often determined based on an authorization call

  • model - The model on how the section needs to be rendered (text, link, function etc)

  • icon (optional) - The icon to be rendered with the section if necessary.

The following properties can also be set on the sections to overwrite the default behaviour added by the provider:

  • active - This is by default set to true and indicates the section is active

  • shouldPersistOnRouteChange - By default this will be set to the same value as the corresponding property in the provider. It can be set on the section in case the provider behaviour needs to be overwritten.

  • alwaysRenderExpandable - By default this will be set to the same value as the corresponding property in the provider. It can be set on the section in case the behaviour needs to be overwritten.

The following two properties can also be set but should be avoided since these are set automatically and may cause confusion when overwritten manually:

  • id - This will be set automatically when the providers are processed based on the menu and its index in the list of providers and its index in the list of sections in the provider.

    • The id can be manually set when needed to interact with this menu, however, you can also use one of the methods present to retrieve the automatic id instead by using the getAutomatedSectionId method which takes the relative index of the section inside the provider as argument. When extending the AbstractExpandableMenuProvider provider, the following two methods can be used instead: getAutomatedSectionIdForTopSection and getAutomatedSectionIdForSubsection where the latter also takes the relative index of the sub section inside the provider. An example of where one of these methods is used, is in the

  • parentID - This will be set automatically when the AbstractExpandableMenuProvider or the withSubs method is used. It is advised to use one of these two options to add parent and child menu sections. In other cases, the parentID can be set in combination with the id to make sure they match, however, great care needs to be taken when doing this.

To make it easier to create new providers, several "helper" providers have been created that will pre-configure some aspects of the provider and two static methods can be used on any type of provider to change the behaviour of the provider.

The following two methods can be added to a provider when defining it in the app.menus.ts file:

onRoute
To allow people to easily determine routes on which they want to add the sections from this provider, a new route ID has been added to various routes. All of the existing route IDs can be found in MenuRoute . These IDs can then be added to the route in the following way:

{
  path: '',
  component: ThemedCommunityPageComponent,
  pathMatch: 'full',
  data: {
    menuRoute: MenuRoute.SIMPLE_COMMUNITY_PAGE,
  },
}


On a provider, the onRoute static method can be used which takes a list of route IDs as argument and will only add menus on the routes which contain the provided route ID in its route data.

The shouldPersistOnRouteChange will be automatically set to false since the sections of this provider depends on the route.

withSubs
This method takes a list of child providers as argument.

When this method is called on a provider, this provider will act as a parent provider to all the child providers that have been provided as argument. The parentID will be automatically set for all the child providers.

When using the withSubs method, avoid adding multiple sections to the parent provider since this can cause unnecessary confusion. In case multiple sections have been added to the parent, the sub provider sections will be added to the first section

Note:
These two methods are mutually exclusive. In case you would want to combine the withSubs and onRoute, the onRoute method can instead be used on the child providers. If alwaysRenderExpandable is set to true for the parent provider, the section will be hidden when no child sections are visible!

The following abstract providers have been added that can be extended to more easily create certain menu section structures.

The following abstract providers exist:

AbstractRouteContextMenuProvider<T>
This provider contains some extra support to retrieve information from the route through the use of additional (abstract) methods:

  • getRouteContext should be implemented to retrieve the object of type <T> you want from the route.

  • getSectionsForContext should be implemented to create the sections. This method will already provide the object retrieved by getRouteContext to make the section creation more easy.

  • isApplicable is a method that can be used to further distinguish whether the sections of this provider should be created for the object of type <T>. This method returns true by default.

DSpaceObjectPageMenuProvider
This provider extends the AbstractRouteContextMenuProvider with <T> being a DSpaceObject. It can be extended to easily create sections for various DSpace objects or a specific kind of DSpace objects.

The provider already implemented the getRouteContext to retrieve the DSpace object from the route data (route.data.dso). When implementing the getSectionsForContext method, the DSpace object present in the route object will be provided so it can be used to easily create the sections.

The provider extends isApplicable to return true only when a DSpace object was retrieved from the route. This can be further extended though in case only a specific type or entity needs to be supported.

AbstractExpandableMenuProvider
This provider contains support to easily create an expandable section with subsections.

It adds two abstract methods to be implemented:

  • getTopSection - Should return the menu section to act like the top section

  • getSubSections - Should return the list of sub menu sections for the parent

The provider will then combine these sections and assign the correct parent IDs to the children. To manually interact with the ids of the parent and the child sections, the following two methods have been added to retrieve the sections:

  • getAutomatedSectionIdForTopSection - Retrieves the ID of the top section

  • getAutomatedSectionIdForSubsection - Retrieves the ID for a child section. If no argument is provided, the ID of the first child is retrieved. If a different section ID needs to be retrieved, a relative index of the child section can be provided.

The main idea of adding new sections to the existing menus is to separate the sections into different providers and then list these providers in the app.menus.ts file. Multiple sections can be provided by a single provider, but this should only be done if those sections are related to each other and are easy to add to the same provider, e.g. NewMenuProvider which contains the "New" section in the admin side bar and all its children. However, the various DSO pages have their menus split over separate providers, using the .withSubs method. In case more menus need to be added in the future, they can be easily added to the already existing dropdown, or added as separate buttons.

Below the practical steps are explained on how to migrate the sections.

Choose how you want to migrate a section or a couple of sections that belong together, what helper provider you want to start from and what static methods you want to use if any.

For example:

Do you have just one section without route dependent info?
-> Extend the basic AbstractMenuProvider class. See SystemWideAlertMenuProvider for an example of this.

Do you have a simple expandable list without route dependent info?
-> Extend the AbstractExpandableMenuProvider. See ImportMenuProvider for an example of this.

Do you have a more complex expandable list with route dependent sections that need to be displayed on the DSpace object pages?
-> Create a separate parent provider extending the DSpaceObjectPageMenuProvider. Use the .withSubs method on this provider and create separate child providers that can also extend DSpaceObjectPageMenuProvider provider. On the child providers, the onRoute method can be used to determine on what routes these should be present.
See the DsoOptionMenuProvider and its children for an example of this.

After having determined what abstract provider to start from, you can check if you need to overwrite some of the default properties of the provider that will be used for all sections added in this provider (shouldPersistOnRouteChange and alwaysRenderExpandable).

For example, in the DsoOptionMenuProvider, the alwaysRenderExpandable is set to true since the parent menu should be hidden when none of the children are present on the route.

Next, the relevant "getSections" method needs to be implemented (e.g. getSections, getSectionsForContext, getTopSection and getSubSections, ... )

These methods should return and observable of section(s). It is advised to only add the minimal information for the sections since a lot of the information will be automatically set.

The following properties are required:

  • visible

  • model

  • icon

The following can be set if the behaviour of the provider needs to be overwritten on section level:

  • alwaysRenderExpandable

  • shouldPersistOnRouteChange

Avoid manually setting the parentID and id properties!
The parentID will be set automatically when using .withSubs or AbstractExpandableMenuProvider. Use the getAutomatedSectionId or getAutomatedSectionIdForTopSection/getAutomatedSectionIdForSubsection methods when interactions are needed with a specific menu.
See ClaimMenuProvider for an example of the usage of getAutomatedSectionId.

The final step is to add the new provider to the list of providers in the app.menus.ts file. The position of the provider will determine the order of display in the actual menu.