diff --git a/docs/customize/look-and-feel/img/communities-dashboard.png b/docs/customize/look-and-feel/img/communities-dashboard.png new file mode 100644 index 00000000..7e04b1c7 Binary files /dev/null and b/docs/customize/look-and-feel/img/communities-dashboard.png differ diff --git a/docs/customize/look-and-feel/img/settings-menu.png b/docs/customize/look-and-feel/img/settings-menu.png new file mode 100644 index 00000000..76a4950c Binary files /dev/null and b/docs/customize/look-and-feel/img/settings-menu.png differ diff --git a/docs/customize/look-and-feel/img/user-dashboard.png b/docs/customize/look-and-feel/img/user-dashboard.png new file mode 100644 index 00000000..68a2902a Binary files /dev/null and b/docs/customize/look-and-feel/img/user-dashboard.png differ diff --git a/docs/customize/look-and-feel/menus.md b/docs/customize/look-and-feel/menus.md new file mode 100644 index 00000000..bf68026d --- /dev/null +++ b/docs/customize/look-and-feel/menus.md @@ -0,0 +1,144 @@ +# Change Menus + +For navigation, InvenioRDM uses *menu*s. For example, one such menu is at the +top of the dashboard shown to users on their personal page (with submenus +*Uploads*, *Communities*, and *Requests*): +![User's personal dashboard with three tabs labeled (left-to-right) "Uploads", "Communities", and "Requests"](./img/user-dashboard.png) +Menus are configurable in the following ways: + +- which submenus to show +- what title-text to show in those submenus +- which endpoint to request when clicking them +- how to dynamically show/hide them (e.g. depending on currently logged-in user) + +## Configurable Properties + +All submenus share the following properties. +Properties of existing submenus can be overridden, +properties of newly added submenus can be freely chosen. + +| Name | Example values | Notes | +|----------------|--------------------------------------|-----------------------------------------------------| +| `endpoint` | `"invenio_app_rdm_users.uploads"` | flask-endpoint requested when clicking this submenu | +| `order` | `1`, `2`, `10`, `-1`, `1.5` | lower ordered submenus are shown further left | +| `text` | `_("Uploads")`, `_("Communities")` | title-text shown on submenus | +| `visible_when` | `flask_menu.menu.CONDITION_TRUE` | when to show this submenu
- must be of type `callable[[], bool]`
- `CONDITION_TRUE` is just a named `lambda: True`
- use `CONDITION_FALSE` to hide a submenu | +| ... | ... | in addtion to the above properties, all arguments for `flask_menu.menu:MenuNode.register` are configurable | + +For an example consider the user-dashboard pictured above. +Its *Uploads* submenu has the following default configuration: +```python +{ + "endpoint": "invenio_app_rdm_users.uploads", + "order": 1, # small number as to show this submenu left-most + "text": _("Uploads"), + "visible_when": flask_menu.menu.CONDITION_TRUE, # always show this submenu + ..., # advanced configuration properties omitted for brevity +} +``` + +## Add new submenus to existing menu + +Existing menus can be extended by custom-configured submenus. +To add a new submenu to an existing menu: + +1. get the name of the to-be-added-to menu from the [list of menus](#list-of-menus) + For example, the user-dashboard is named `"dashboard"` (most names of menus/submenus are straightforward). +2. write a function that registers the new submenu + ```python + # ext.py # ext.py is commonly used, you may use another file though + + from flask_menu import current_menu + from invenio_i18n import lazy_gettext as _ # for translations + + def finalize_app(): + # get the user-dashboard menu via its name "dashboard": + user_dashboard_menu = current_menu.submenu("dashboard") + + # register a new submenu to the user-dashboard: + user_dashboard_menu.register( + "name-of-submenu", + endpoint="my_blueprint.my_endpoint", + order=4, # the three already existing submenus have `order` 1 through 3 + text=_("Title of new Submenu"), # could also use an untranslated bare string + # note: could add other properties here, otherwise their default is used + # note: `visible_when` defaults to always visible + ) + + ... # could .register more submenus here (or do so in another package) + ``` +3. have the endpoint `invenio_base.finalize_app` point at your function + This will make your function be called at the app-finalization build-step. + For example, when using setuptools' `setup.cfg` with your python-package, add: + ```ini + # setup.cfg + + [options.entry_points] + invenio_base.finalize_app = + my_package_name = my_package_name.ext:finalize_app + ``` + +!!! info "For entrypoints to take effect" + For entrypoint changes to be picked up, you will need to reinstall the python package. + *This is necessary even if the package is installed editably!* + +!!! info "Have you tried to turn it off and on again?" + After entrypoint changes were picked up, + you will further need to restart the server for changes to take effect: + ```shell + + invenio-cli run + ``` + +## Modify existing submenus + +The defaults of submenus' properties are selectively overridable via config-variables. +To modify an existing submenu's properties: + +1. find the name of the corresponding override-variable in the [list of menus](#list-of-menus) + For example, the override-variable for the user-dashboard is named `USER_DASHBOARD_MENU_OVERRIDES`. +2. find the name of the to-be-overridden submenu in that same [list of menus](#list-of-menus) + For example, the user-dashboard has a submenu for communities. + This submenu is named (obviously enough) `"communities"`. +3. add to your `invenio.cfg`: + ```python + # invenio.cfg + + from flask_menu.menu import CONDITION_FALSE + + USER_DASHBOARD_MENU_OVERRIDES = { + "communities": { + "visible_when": CONDITION_FALSE, + # other properties will be left unchanged + } + # other submenus will be left unchanged + } + ``` + +The above example hides the *Communities* submenu from the user-dashboard menu +by overriding its `visible_when` property. +For other overridable properties see [configurable properties](#configurable-properties). + +!!! info "Have you tried to turn it off and on again?" + You will need to restart the server for changes to take effect: + ```shell + + invenio-cli run + ``` + +!!! warning "On overriding user-added submenus: DON'T" + Currently, (sub)menu-overrides are adopted at app-finalization. + Users adding their own submenus (as described above) is also done at app-finalization. + Hence attempting to override submenus added by (other) users depends on + loading order of app-finalization entrypoints and might break anytime. + +## List of menus + +The following list of menus is non-exhaustive. +Not all menus are overridable, but all menus can be extended by additional submenus. + +| Image | Description | Name of menu and its submenus | Name of override-variable | +|-------|-------------|-------------------------------|---------------------------| +| ![User's personal dashboard with three tabs labeled (left-to-right) "Uploads", "Communities", and "Requests"](./img/user-dashboard.png) | Dashboard on user's personal page | `"dashboard"`
├─`"uploads"`
├─`"communities"`
└─`"requests"` | `USER_DASHBOARD_MENU_OVERRIDES` | +| ![Communities dashboard with its 6 default tabs](./img/communities-dashboard.png) | Dashboard on communities page | `"communities"`
├─`"home"`
├─`"search"`
├─`"requests"`
├─`"submit"`
├─`"members"`
├─`"settings"`
├─`"curation_policy"`
└─`"about"` | No associated override-variable | +| ![User-settings menu with its 5 default entries](./img/settings-menu.png) | User settings menu | `"settings"`
├─`"profile"`
├─`"change_password"`
├─`"security"`
├─`"notifications"`
├─`"oauthclient"`
└─`"applications"` | No associated override-variable | diff --git a/mkdocs.yml b/mkdocs.yml index 3fa4adff..7e363259 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -52,6 +52,7 @@ nav: - Change logo: "customize/look-and-feel/logo.md" - Change templates: "customize/look-and-feel/templates.md" - Change theme: "customize/look-and-feel/theme.md" + - Change menus: "customize/look-and-feel/menus.md" - Authentication: "customize/authentication.md" - Sending emails: "customize/emails.md" - Search: