|
| 1 | +# Change Menus |
| 2 | + |
| 3 | +For navigation, InvenioRDM uses *menu*s. For example, one such menu is at the |
| 4 | +top of the dashboard shown to users on their personal page (with submenus |
| 5 | +*Uploads*, *Communities*, and *Requests*): |
| 6 | + |
| 7 | +Menus are configurable in the following ways: |
| 8 | + |
| 9 | +- which submenus to show |
| 10 | +- what title-text to show in those submenus |
| 11 | +- which endpoint to request when clicking them |
| 12 | +- how to dynamically show/hide them (e.g. depending on currently logged-in user) |
| 13 | + |
| 14 | +## Configurable Properties |
| 15 | + |
| 16 | +All submenus share the following properties. |
| 17 | +Properties of existing submenus can be overridden, |
| 18 | +properties of newly added submenus can be freely chosen. |
| 19 | + |
| 20 | +| Name | Example values | Notes | |
| 21 | +|----------------|--------------------------------------|-----------------------------------------------------| |
| 22 | +| `endpoint` | `"invenio_app_rdm_users.uploads"` | flask-endpoint requested when clicking this submenu | |
| 23 | +| `order` | `1`, `2`, `10`, `-1`, `1.5` | lower ordered submenus are shown further left | |
| 24 | +| `text` | `_("Uploads")`, `_("Communities")` | title-text shown on submenus | |
| 25 | +| `visible_when` | `flask_menu.menu.CONDITION_TRUE` | when to show this submenu<br />- must be of type `callable[[], bool]`<br />- `CONDITION_TRUE` is just a named `lambda: True`<br />- use `CONDITION_FALSE` to hide a submenu | |
| 26 | +| ... | ... | in addtion to the above properties, all arguments for `flask_menu.menu:MenuNode.register` are configurable | |
| 27 | + |
| 28 | +For an example consider the user-dashboard pictured above. |
| 29 | +Its *Uploads* submenu has the following default configuration: |
| 30 | +```python |
| 31 | +{ |
| 32 | + "endpoint": "invenio_app_rdm_users.uploads", |
| 33 | + "order": 1, # small number as to show this submenu left-most |
| 34 | + "text": _("Uploads"), |
| 35 | + "visible_when": flask_menu.menu.CONDITION_TRUE, # always show this submenu |
| 36 | + ..., # advanced configuration properties omitted for brevity |
| 37 | +} |
| 38 | +``` |
| 39 | + |
| 40 | +## Add new submenus to existing menu |
| 41 | + |
| 42 | +Existing menus can be extended by custom-configured submenus. |
| 43 | +To add a new submenu to an existing menu: |
| 44 | + |
| 45 | +1. get the name of the to-be-added-to menu from the [list of menus](#list-of-menus) |
| 46 | + For example, the user-dashboard is named `"dashboard"` (most names of menus/submenus are straightforward). |
| 47 | +2. write a function that registers the new submenu |
| 48 | + ```python |
| 49 | + # ext.py # ext.py is commonly used, you may use another file though |
| 50 | + |
| 51 | + from flask_menu import current_menu |
| 52 | + from invenio_i18n import lazy_gettext as _ # for translations |
| 53 | + |
| 54 | + def finalize_app(): |
| 55 | + # get the user-dashboard menu via its name "dashboard": |
| 56 | + user_dashboard_menu = current_menu.submenu("dashboard") |
| 57 | + |
| 58 | + # register a new submenu to the user-dashboard: |
| 59 | + user_dashboard_menu.register( |
| 60 | + "name-of-submenu", |
| 61 | + endpoint="my_blueprint.my_endpoint", |
| 62 | + order=4, # the three already existing submenus have `order` 1 through 3 |
| 63 | + text=_("Title of new Submenu"), # could also use an untranslated bare string |
| 64 | + # note: could add other properties here, otherwise their default is used |
| 65 | + # note: `visible_when` defaults to always visible |
| 66 | + ) |
| 67 | + |
| 68 | + ... # could .register more submenus here (or do so in another package) |
| 69 | + ``` |
| 70 | +3. have the endpoint `invenio_base.finalize_app` point at your function |
| 71 | + This will make your function be called at the app-finalization build-step. |
| 72 | + For example, when using setuptools' `setup.cfg` with your python-package, add: |
| 73 | + ```ini |
| 74 | + # setup.cfg |
| 75 | + |
| 76 | + [options.entry_points] |
| 77 | + invenio_base.finalize_app = |
| 78 | + my_package_name = my_package_name.ext:finalize_app |
| 79 | + ``` |
| 80 | + |
| 81 | +!!! info "For entrypoints to take effect" |
| 82 | + For entrypoint changes to be picked up, you will need to reinstall the python package. |
| 83 | + *This is necessary even if the package is installed editably!* |
| 84 | + |
| 85 | +!!! info "Have you tried to turn it off and on again?" |
| 86 | + After entrypoint changes were picked up, |
| 87 | + you will further need to restart the server for changes to take effect: |
| 88 | + ```shell |
| 89 | + <CTRL+C> |
| 90 | + invenio-cli run |
| 91 | + ``` |
| 92 | + |
| 93 | +## Modify existing submenus |
| 94 | + |
| 95 | +The defaults of submenus' properties are selectively overridable via config-variables. |
| 96 | +To modify an existing submenu's properties: |
| 97 | + |
| 98 | +1. find the name of the corresponding override-variable in the [list of menus](#list-of-menus) |
| 99 | + For example, the override-variable for the user-dashboard is named `USER_DASHBOARD_MENU_OVERRIDES`. |
| 100 | +2. find the name of the to-be-overridden submenu in that same [list of menus](#list-of-menus) |
| 101 | + For example, the user-dashboard has a submenu for communities. |
| 102 | + This submenu is named (obviously enough) `"communities"`. |
| 103 | +3. add to your `invenio.cfg`: |
| 104 | + ```python |
| 105 | + # invenio.cfg |
| 106 | + |
| 107 | + from flask_menu.menu import CONDITION_FALSE |
| 108 | + |
| 109 | + USER_DASHBOARD_MENU_OVERRIDES = { |
| 110 | + "communities": { |
| 111 | + "visible_when": CONDITION_FALSE, |
| 112 | + # other properties will be left unchanged |
| 113 | + } |
| 114 | + # other submenus will be left unchanged |
| 115 | + } |
| 116 | + ``` |
| 117 | + |
| 118 | +The above example hides the *Communities* submenu from the user-dashboard menu |
| 119 | +by overriding its `visible_when` property. |
| 120 | +For other overridable properties see [configurable properties](#configurable-properties). |
| 121 | + |
| 122 | +!!! info "Have you tried to turn it off and on again?" |
| 123 | + You will need to restart the server for changes to take effect: |
| 124 | + ```shell |
| 125 | + <CTRL+C> |
| 126 | + invenio-cli run |
| 127 | + ``` |
| 128 | + |
| 129 | +!!! warning "On overriding user-added submenus: DON'T" |
| 130 | + Currently, (sub)menu-overrides are adopted at app-finalization. |
| 131 | + Users adding their own submenus (as described above) is also done at app-finalization. |
| 132 | + Hence attempting to override submenus added by (other) users depends on |
| 133 | + loading order of app-finalization entrypoints and might break anytime. |
| 134 | + |
| 135 | +## List of menus |
| 136 | + |
| 137 | +The following list of menus is non-exhaustive. |
| 138 | +Not all menus are overridable, but all menus can be extended by additional submenus. |
| 139 | + |
| 140 | +| Image | Description | Name of menu and its submenus | Name of override-variable | |
| 141 | +|-------|-------------|-------------------------------|---------------------------| |
| 142 | +|  | Dashboard on user's personal page | `"dashboard"`<br />├─`"uploads"`<br />├─`"communities"`<br /> └─`"requests"` | `USER_DASHBOARD_MENU_OVERRIDES` | |
| 143 | +|  | Dashboard on communities page | `"communities"`<br />├─`"home"`<br />├─`"search"`<br />├─`"requests"`<br />├─`"submit"`<br />├─`"members"`<br />├─`"settings"`<br />├─`"curation_policy"`<br />└─`"about"` | No associated override-variable | |
| 144 | +|  | User settings menu | `"settings"`<br />├─`"profile"`<br />├─`"change_password"`<br />├─`"security"`<br />├─`"notifications"`<br />├─`"oauthclient"`<br />└─`"applications"` | No associated override-variable | |
0 commit comments