/
Technical Approach to have Menu Configuration flexible

Technical Approach to have Menu Configuration flexible

Overview

The goal is to implement a flexible and configurable menu that can be displayed in a specified order based on configuration settings. Currently, the order of menu entries (both top-level and sub-level) is determined by the sequence in which openIMIS modules are loaded on the frontend. This configuration will be integrated into a larger global configuration that is loaded during app initialization. Moreover, the functionality should allow the creation of entirely new menu entries. However, submenus can only be linked to existing ones that are predefined within the application, ensuring consistency with the application’s internal structure.

The aim is to enhance the current implementation of menu entry population by introducing a new property called POSITION for both the MainMenuComponent and individual menu entries (referred to as submenus). Currently, the order of menu entries cannot be modified by non-technical users; only technical users can adjust it by altering the order of modules in the openimis.json file (assembly frontend - openimis-fe_js). The proposed change will enable non-technical implementers to configure the menu order easily and intuitively. Additionally, the functionality will include the possibility to create entirely new menu entries, while submenus can only be linked to existing ones within the application, ensuring seamless integration.

Strategy

  1. Component MainMenuCompoment (Openimis-fe-core_js)

  • The additional property should be added. It might be called ‘menuId’

    class MainMenuContribution extends Component {  state = {    expanded: false,    anchorRef: React.createRef(),  }; <......>  MainMenuContribution.propTypes = {   header: PropTypes.string.isRequired,   entries: PropTypes.array.isRequired,   history: PropTypes.object.isRequired,   // additional property after applying the idea   menuId: PropTypes.object.isRequired, };
  • Above, the definition of this component is provided. Header: Contains all information about the main menu entry that will be added to the navigation bar. Entries: Represents all subitems of the main menu element (see the "Entries" section below).

  • Components are typically added to the application through contribution points. In index.js, the appropriate contribution should be declared as follows:'core.MainMenu': [GrievanceMainMenu],

  • In 'core.MainMenu', the MainMenu component is added to the entire list of menu items that are processed within the RequireAuth.js component (see further details in another section related to this).

  • Examples of extensions of the MainMenuComponent can be found in applications such as 'GrievanceMainMenu'.

  • In 'core.MainMenu', the MainMenu component is added to the entire list of menu items that are processed within the RequireAuth.js component (see further details in another section related to this).

  • Examples of extensions of the MainMenuComponent can be found in applications such as 'GrievanceMainMenu'.

  • To establish a connection between id from the configuration file and the source code, additional adjustments should be implemented in each MainMenu entry, such as ClaimMainMenu. Here's an example of how it should be structured:

return (      <MainMenuContribution        {...this.props}        header={formatMessage(this.props.intl, "claim", "mainMenu")}        icon={<ScreenShare />}        entries={entries}        menuId="ClaimMainMenu"      /> );
  1. Entries array (all modules)

  • An entry is defined with a root, along with associated permissions and an icon that represents the type of functionality it provides.

  • Structure after change:

  • The new sorting mechanism based on the position field should be implemented before processing the display of elements. This logic must be applied prior to the existing expression responsible for rendering elements in the MainMenuComponent.

  • Moreover, we need to relocate some entries and assign ids from specific MainMenu definitions into the index.js file of their respective modules. This will allow them to be globally accessible via the modules manager, enabling the flexibility to move subitems from one MainMenu to another. For example, in the claim module's index.js.

    "claim.MainMenu": [ { text: <FormattedMessage module="claim" id="menu.healthFacilityClaims" />, icon: <Keyboard />, route: "/claim/healthFacilities", id: "claim.healthFacilityClaims", filter: (rights) => rights.some((r) => r >= RIGHT_CLAIMREVIEW && r <= RIGHT_PROCESS), }, { text: <FormattedMessage module="claim" id="menu.reviews" />, icon: <Assignment />, route: "/claim/reviews", id: "claim.reviews", filter: (rights) => rights.some((r) => r >= RIGHT_CLAIMREVIEW && r <= RIGHT_PROCESS), }, ],
  • Additionally, a filter must also be added to ensure permissions are correctly applied, allowing menu items to be displayed only for users with specific roles.

  1. RequireAuth.js (openimis-fe-core_js)

  • Currently, on line 320, the main menu items are added through a contribution point.

  • MAIN_MENU_CONTRIBUTION_KEY=core.MainMenu

  • The goal is to introduce a new component called MainMenuBar (within openimis-fe_core), which will handle the preprocessing of all loaded main menu items. This component will be responsible for sorting the menu items based on their position property before rendering them. Moreover here the new menu entry could be created when there is no matching ids of menu.

  • Render is processed by this code:

  • <Here rendering> should be replaced by this line:

  • The new Navbar component should be integrated into RequireAuth as a replacement for the existing code responsible for displaying menu items. This will streamline the handling of menu item processing and ensure they are sorted based on their position property.

  • Please keep in mind the necessary adjustments for rendering when the MenuLeft=True option is enabled in the configuration.

  1. Structure of Config for prioritization of items in menu: 

  • the exact name of the menu component must be specified, and the position should be assigned as a numeric value (e.g., 1, 2, 3, 4, etc.).

  • When the id does not match an existing MainMenu component, a new menu entry must be created to ensure proper integration and functionality. This allows for the dynamic addition of menu entries when no matching component is found.

  • For Menu Entries: The same structure and approach should be applied to menu entries.

  • Code Implementation: In the code, ensure prioritization is applied based on the configuration integer like position: 1.

  • We should compare the string name of the component instead of the object itself, as comparing objects may not produce the expected results. Therefore, we need to make changes at the index.js level in each module where we attach a specific MainMenu to the core.MainMenu contribution, such as:

where name matches the id from configuration.

  1. Additional function in modulesManager.js in openimis-fe_js (assembly) 

  • getMenuEntries() { <To-impplement> } -The implementation should be added here. The function will be responsible for fetching all menu entries within the system. Ideally, it should retrieve all keys containing .MainMenu except for core.MainMenu and extract the values from those keys. Based on this collection, we should generate a list of available entries within the system.

Summary - what need to do in achieve goal

  1. Define Configuration Structure:
    Design the structure of the configuration to store menu priorities at the database level. Ensure this configuration is exposed to the frontend through the backend using GraphQL.

  1. Add Position Properties:
    Introduce a position property for both MainMenuComponent and menu entries (submenus).

  2. Add menuId property for MainMenuContribution: Introduce a menuId property for MainMenuComponent in order to link config with existing MainMenu’s definitions.

  3. Update MainMenuContribution Logic:
    Modify the logic in the MainMenuContribution component to process menu entries and subitems based on the new position property. Implement sorting logic accordingly.

  4. Adjust Logic in RequireAuth.js:
    Revise the RequireAuth.js file to include a new component responsible for sorting menu contributions (called MainMenu). Ensure all contributions are loaded only after the sorting operation. Extend this logic to handle submenu items within entries arrays too and make them flexible in terms of moving between different MainMenu entries.

  5. Integrate Position Configuration:
    Implement logic to process priorities from the configuration and compare them to user-defined values (by string). 

  6. Add Mechanism to pull all entries: mechanism need to be added to pull all entries to enable moving them between various MainMenu entries.

  7. Documentation : Ensure that all mechanisms related to configuring priorities and the sorting logic are thoroughly explained in all relevant documentation. This includes the user guide, technical documentation such as the README file, and the openIMIS wiki on Confluence. Providing clear and comprehensive details in these resources will help users and developers understand and implement the functionality effectively.

  8. Testing:
    Thoroughly test the solution across various scenarios to ensure correct behavior and reliability

 

Did you encounter a problem or do you have a suggestion?

Please contact our Service Desk



This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. https://creativecommons.org/licenses/by-sa/4.0/