How to add new menu between HOME and CREATE EVENT and link to External site

Hi Gurus,

I want to add new menu item in indico
How to add new menu between HOME and CREATE EVENT and link to External site.

thanks in advance.

You need to write a plugin for this which uses the signals.menu.items signal to define a new TopMenuItem with a weight between 90 (ā€œCreate Eventā€) and 100 (ā€œHomeā€).

A very basic example for such a plugin would be this:

from indico.core import signals
from indico.core.plugins import IndicoPlugin
from indico.web.menu import TopMenuItem


class MyCustomTopMenuLinkPlugin(IndicoPlugin):
    """My Custom Top Menu Link

    Add a new top menu link.
    """

    def init(self):
        super(MyCustomTopMenuLinkPlugin, self).init()
        self.connect(signals.menu.items, self._extend_top_menu, sender='top-menu')

    def _extend_top_menu(self, sender, **kwargs):
        return TopMenuItem('my-menu-item', 'Title of the item', 'https://your-url', weight=95)

Save this file in a new folder as indico_my_custom_top_menu_link.py, and create a setup.py containing this:

from setuptools import setup
setup()

and a setup.cfg containing this:

[metadata]
name = indico-plugin-my-custom-top-menu-link
version = 2.3
description = Indico plugin that adds a custom top menu link
license = MIT

[options]
py_modules = indico_my_custom_top_menu_link
zip_safe = false
install_requires =
    indico>=2.3.4

[options.entry_points]
indico.plugins =
    my_custom_top_menu_link = indico_my_custom_top_menu_link:MyCustomTopMenuLinkPlugin

Then, from the src folder of an indico development environment, run ./bin/maintenance/build-wheel.py plugin ../path/to/your/custom/plugin/folder

This will build a .whl file in dist/, which you can copy to your indico server, install it using pip install whatever.whl and then you just need to add my_custom_top_menu_link to the PLUGINS list in indico.conf.

Note: I have not tested any of the code above. There may be typos/bugs. Ideally you try it out on a local dev instance first!

PS: It would be nice if someone implemented a more fancy plugin where those custom menu items can be configured in the plugin settings, but if all you need is a custom menu item then this is the way to go. Youā€™ll need to add a setup.py as well though to expose the plugin

1 Like

Thank you so much for the guidance. Tested above code on development server got following error messages:

  1. env not activated.
[indico@localhost ~]$ cd  dev/indico/
[indico@localhost indico]$ cd src/
[indico@localhost src]$ ./bin/maintenance/build-wheel.py plugin /opt/indico/dev/indico/plugins/external_link
Traceback (most recent call last):
  File "./bin/maintenance/build-wheel.py", line 19, in <module>
    import click
ImportError: No module named click
  1. env activated
(env) [indico@localhost src]$ ./bin/maintenance/build-wheel.py plugin /opt/indico/dev/indico/plugins/external_link
Traceback (most recent call last):
  File "./bin/maintenance/build-wheel.py", line 327, in <module>
    cli(obj={})
  File "/opt/indico/dev/indico/env/lib/python2.7/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/opt/indico/dev/indico/env/lib/python2.7/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/opt/indico/dev/indico/env/lib/python2.7/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/opt/indico/dev/indico/env/lib/python2.7/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/opt/indico/dev/indico/env/lib/python2.7/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/opt/indico/dev/indico/env/lib/python2.7/site-packages/click/decorators.py", line 33, in new_func
    return f(get_current_context().obj, *args, **kwargs)
  File "./bin/maintenance/build-wheel.py", line 289, in build_plugin
    clean, output = git_is_clean_plugin()
  File "./bin/maintenance/build-wheel.py", line 167, in git_is_clean_plugin
    rv = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
  File "/usr/lib64/python2.7/subprocess.py", line 575, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['git', 'diff', '--stat', '--color=always']' returned non-zero exit status 129

What happens if you run git diff --stat --color=always manually in the pluginā€™s folder? Any error? Maybe itā€™s not a git repo?

PS: Please paste shell output in triple-backtick fences and not using the quote option. Especially tracebacks are much less readable that wayā€¦

(env) [indico@localhost plugins]$ git diff --stat --color=always
warning: Not a git repository. Use --no-index to compare two paths outside a working tree
usage: git diff --no-index [<options>] <path> <path>

Diff output format options
    -p, --patch           generate patch
    -s, --no-patch        suppress diff output
    -u                    generate patch
    -U, --unified[=<n>]   generate diffs with <n> lines context
    -W, --function-context
                          generate diffs with <n> lines context
    --raw                 generate the diff in raw format
    --patch-with-raw      synonym for '-p --raw'
    --patch-with-stat     synonym for '-p --stat'
    --numstat             machine friendly --stat
    --shortstat           output only the last line of --stat
    -X, --dirstat[=<param1,param2>...]
                          output the distribution of relative amount of changes for each sub-directory

git init to create one. You may also want to consider putting your plugig on github (can also be a private repo) so you have a backup of it and keep track of your changes.

(env) [indico@localhost plugins]$ git init
hint: Using ā€˜masterā€™ as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch
hint:
hint: Names commonly chosen instead of ā€˜masterā€™ are ā€˜mainā€™, ā€˜trunkā€™ and
hint: ā€˜developmentā€™. The just-created branch can be renamed via this command:
hint:
hint: git branch -m
Initialized empty Git repository in /opt/indico/dev/indico/plugins/.git/
(env) [indico@localhost plugins]$ git diff --stat --color=always

Iā€™d rather do it inside the external_link folderā€¦ especially if plugins contains anything else.

Anyway having a repo is all you need. The build script has a switch to skip the check if everything is committed so use that (itā€™s listed in --help) for now; if you want to actually keep the plugin code in a repo, check some beginner documentation on git online (explaining git would be way out of scope here)

Thanks for the advises but I am confused how will it solve the error messages shown while trying to install the script unless I make changes to the python code.

PS: uploaded the code on Github. https://github.com/batpurev/indico_external_link

the build script checks if there are no uncommitted changes, and that check fails if there is no git repo (we should fix that of course ;))

please help me how to fix it. I am complete new comer here thanks.

I would expect this to work now that the git command wonā€™t failā€¦

change the folder name to match with github name? like indico_external_link

(env) [indico@localhost src]$ ./bin/maintenance/build-wheel.py plugin /opt/indico/dev/indico/plugins/external_link
plugin has no assets
plugin has no translations
cleaning build dirs
building wheel
Error: build failed
running bdist_wheel
running build
running build_py
creating build
error: could not create ā€˜buildā€™: Permission denied

(env) [indico@localhost src]$

any chance one of the folders are owned by root instead of your normal user?

1 Like

yes it was owned by root changing it to indico:apache made it. No errors now.

(env) [indico@localhost src]$ ./bin/maintenance/build-wheel.py plugin /opt/indico/dev/indico/plugins/external_link
plugin has no assets
plugin has no translations
cleaning build dirs
building wheel
cleaning build dirs
(env) [indico@localhost src]$

What is the right way to add it in indico.conf? /opt/indico/etc/indico.conf

I did following and restarted the services systemctl restart uwsgi.service httpd.service indico-celery.service

STATIC_FILE_METHOD = ā€˜xsendfileā€™
PLUGINS my_custom_top_menu_link

but got

Internal Server Error

PLUGINS = {'my_custom_top_menu_link'}
1 Like

Error persists.
my conf file:

General settings

SQLALCHEMY_DATABASE_URI = ā€˜postgresql:///indicoā€™
SECRET_KEY = ā€˜a\x84\xa1\x87K\nG\x18jT\xcb\xb2\x8a\xab\xa8 \xfd\x85\xec\xe93\x95\xc7\xd6\xff\x0er\x0c"\xa7\x10\x1dā€™
BASE_URL = ā€˜https://10.10.10.108ā€™
CELERY_BROKER = ā€˜redis://127.0.0.1:6379/0ā€™
REDIS_CACHE_URL = ā€˜redis://127.0.0.1:6379/1ā€™
CACHE_BACKEND = ā€˜redisā€™
DEFAULT_TIMEZONE = ā€˜America/New_Yorkā€™
DEFAULT_LOCALE = ā€˜en_GBā€™
ENABLE_ROOMBOOKING = True
CACHE_DIR = ā€˜/opt/indico/cacheā€™
TEMP_DIR = ā€˜/opt/indico/tmpā€™
LOG_DIR = ā€˜/opt/indico/logā€™
STORAGE_BACKENDS = {ā€˜defaultā€™: ā€˜fs:/opt/indico/archiveā€™}
ATTACHMENT_STORAGE = ā€˜defaultā€™

Email settings

SMTP_SERVER = (ā€˜127.0.0.1ā€™, 25)
SMTP_USE_TLS = False
SMTP_LOGIN = ā€˜ā€™
SMTP_PASSWORD = ā€˜ā€™
SUPPORT_EMAIL = ā€˜aaa@gmail.comā€™
PUBLIC_SUPPORT_EMAIL = ā€˜aaa@gmail.comā€™
NO_REPLY_EMAIL = ā€˜noreply@gmail.comā€™

STATIC_FILE_METHOD = ā€˜xsendfileā€™
PLUGINS = {ā€˜my_custom_top_menu_linkā€™}

got following error message:

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.

Try running indico shell; this should show you the actual error you got. Also, indico setup list-plugins will show you the names of your installed plugins.

You did pip install it? Just to clarify:

  • if you want to test the plugin locally, you do pip install -e ../path/to/plugins/external_link
  • if you want to install the wheel you built on your production indico instance, then you copy the .whl file and use pip install NAME.whl

which of these is triple back ticks?