Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "global: remove breadcrumbs" #384

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@
"https://docs.python.org/": None,
"flask": ("http://flask.pocoo.org/docs/latest/", None),
"flask_menu": ("https://flask-menu.readthedocs.io/en/latest/", None),
"flask_breadcrumbs": ("https://flask-breadcrumbs.readthedocs.io/en/latest/", None),
"invenio_assets": ("https://invenio-assets.readthedocs.io/en/latest/", None),
}

Expand Down
39 changes: 35 additions & 4 deletions invenio_theme/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.

r"""Standard Bootstrap based theme for Invenio.

Check failure on line 10 in invenio_theme/__init__.py

View workflow job for this annotation

GitHub Actions / Tests (3.7, pypi)

[doctest] invenio_theme

Check failure on line 10 in invenio_theme/__init__.py

View workflow job for this annotation

GitHub Actions / Tests (3.8, pypi)

[doctest] invenio_theme

Check failure on line 10 in invenio_theme/__init__.py

View workflow job for this annotation

GitHub Actions / Tests (3.9, pypi)

[doctest] invenio_theme

Invenio-Theme mainly consits of:

Expand All @@ -15,9 +15,9 @@
<https://getbootstrap.com/>`_ HTML, CSS and JS framework.
- `Error handlers` - for showing user-friendly 401, 402, 404, and 500 error
pages.
- `Menu` - for basic site navigation using `Flask-Menu
<https://flask-menu.readthedocs.io/>`_

- `Menu and breadcrumbs` - for basic site navigation using `Flask-Menu
<https://flask-menu.readthedocs.io/>`_ and `Flask-Breadcrumbs
<https://flask-breadcrumbs.readthedocs.io/>`_.


Initialization
Expand Down Expand Up @@ -151,7 +151,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~
The header template (``invenio_theme/header.html``) is reponsible for rendering
the navigation bar (including logo, search bar, menu and login/sign up
buttons) and flash messages
buttons), flash messages and the breadcrumbs.

Change the template by updating
:data:`invenio_theme.config.THEME_HEADER_TEMPLATE`.
Expand All @@ -165,6 +165,8 @@
* ``flashmessages`` - Displays small notification messages such as
"Successfully logged in."

* ``breadcrumbs`` - Displays the breadcrumbs.

Header login section template
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The header login template (``invenio_theme/header_login.html``) is responsible
Expand Down Expand Up @@ -437,6 +439,33 @@

To read more about the creation and usage of menus, see :mod:`~flask_menu`.

Breadcrumbs
~~~~~~~~~~~
Breadcrumbs works similar to menus, just use the
:func:`~flask_breadcrumbs.register_breadcrumb` instead.

>>> from flask_breadcrumbs import register_breadcrumb

Using this decorator, you can specify the position of the view in a
hierarchical manner, as well as the title in the breadcrumb. By default, the
current breadcrumb is displayed inside the ``page_header`` block in the base
template.

>>> @app.route('/part1')
... @register_breadcrumb(app, '.', 'Index')
... def part1():
... return ""
>>> @app.route('/part2')
... @register_breadcrumb(app, '.p2', 'Part 2')
... def part2():
... return ""
>>> @app.route('/part3')
... @register_breadcrumb(app, '.p2.p3', 'Part 3')
... def part3():
... return ""

To learn more about the usage of breadcrumbs, see :mod:`~flask_breadcrumbs`.

User settings
~~~~~~~~~~~~~
If your module allows your users to configure some settings, you can provide
Expand All @@ -459,6 +488,8 @@

menu.submenu(".settings.item1").register("settings_item_1", "Item 1", order=2)
@app.route('/settings/')
@register_breadcrumb(app, '.settings', 'Settings page')
@register_menu(app, 'settings.item1', 'Item 1', order=2)
def settings_item_1():
return render_template('invenio_foo/foo_settings.html')

Expand Down
3 changes: 3 additions & 0 deletions invenio_theme/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@
THEME_SEARCH_ENDPOINT = "/search"
"""The endpoint for the search bar."""

THEME_BREADCRUMB_ROOT_ENDPOINT = ""
"""The endpoint for the Home view in the breadcrumbs."""

THEME_SITENAME = _("Invenio")
"""The name of the site to be used on the header and as a title."""

Expand Down
42 changes: 41 additions & 1 deletion invenio_theme/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

"""Invenio standard theme."""

from flask import Blueprint
from flask_breadcrumbs import Breadcrumbs
from flask_menu import Menu

from . import config
Expand All @@ -24,7 +26,9 @@ def __init__(self, app=None, **kwargs):
:param app: An instance of :class:`~flask.Flask`.
:param \**kwargs: Keyword arguments are passed to ``init_app`` method.
"""
self.app = None
self.menu_ext = Menu()
self.menu = None
self.breadcrumbs = Breadcrumbs()

if app:
self.app = app
Expand All @@ -40,6 +44,42 @@ def init_app(self, app, **kwargs):
self.menu_ext = Menu(app)

app.context_processor(lambda: {"current_theme_icons": self.icons})
# Initialize extensions
self.menu_ext.init_app(app)
self.menu = app.extensions["menu"]
self.breadcrumbs.init_app(app)

# Register blueprint in order to register template and static folder.
app.register_blueprint(
Blueprint(
"invenio_theme",
__name__,
template_folder="templates",
static_folder="static",
)
)

# Register frontpage blueprint if enabled.
if app.config["THEME_FRONTPAGE"]:
app.register_blueprint(blueprint)

# Initialize breadcrumbs.
item = self.menu.submenu("breadcrumbs")
item.register(app.config["THEME_BREADCRUMB_ROOT_ENDPOINT"], _("Home"))

# Register errors handlers.
app.register_error_handler(401, unauthorized)
app.register_error_handler(403, insufficient_permissions)
app.register_error_handler(404, page_not_found)
app.register_error_handler(429, too_many_requests)
app.register_error_handler(500, internal_error)

# Register context processor
@app.context_processor
def _theme_icon_ctx_processor():
from invenio_theme.proxies import current_theme_icons

return dict(current_theme_icons=current_theme_icons)

# Save reference to self on object
app.extensions["invenio-theme"] = self
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ python_requires = >=3.7
zip_safe = False
install_requires =
Flask-Menu>=1.0.0
Flask-Breadcrumbs>=0.4.0
invenio-assets>=1.2.7
invenio-base>=1.2.5
invenio-i18n>=2.0.0
Expand Down
1 change: 1 addition & 0 deletions tests/test_invenio_theme.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@

def test_init(app):
"""Initialization."""
InvenioTheme(app)

Check failure on line 37 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.7, pypi)

test_init RuntimeError: Flask application is already initialized.

Check failure on line 37 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.8, pypi)

test_init RuntimeError: Flask application is already initialized.

Check failure on line 37 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.9, pypi)

test_init RuntimeError: Flask application is already initialized.
assert "THEME_SITENAME" in app.config


def test_init_app(app):
"""Initialization."""
theme = InvenioTheme()
theme.init_app(app)

Check failure on line 44 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.7, pypi)

test_init_app RuntimeError: Flask application is already initialized.

Check failure on line 44 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.8, pypi)

test_init_app RuntimeError: Flask application is already initialized.

Check failure on line 44 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.9, pypi)

test_init_app RuntimeError: Flask application is already initialized.
assert "THEME_SITENAME" in app.config


Expand All @@ -53,7 +53,7 @@
{% block javascript %}{% endblock %}
"""

InvenioTheme(app)

Check failure on line 56 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.7, pypi)

test_render_template RuntimeError: Flask application is already initialized.

Check failure on line 56 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.8, pypi)

test_render_template RuntimeError: Flask application is already initialized.

Check failure on line 56 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.9, pypi)

test_render_template RuntimeError: Flask application is already initialized.
InvenioAssets(app)
with app.test_request_context():
assert render_template_string(test_tpl)
Expand Down Expand Up @@ -83,7 +83,7 @@
"trackingcode",
"body_inner",
]
InvenioTheme(app)

Check failure on line 86 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.7, pypi)

test_page_template_blocks RuntimeError: Flask application is already initialized.

Check failure on line 86 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.8, pypi)

test_page_template_blocks RuntimeError: Flask application is already initialized.

Check failure on line 86 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.9, pypi)

test_page_template_blocks RuntimeError: Flask application is already initialized.
InvenioAssets(app)

with app.test_request_context():
Expand All @@ -106,7 +106,7 @@
"page_footer",
"panel_content",
]
InvenioTheme(app)

Check failure on line 109 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.7, pypi)

test_cover_template_blocks RuntimeError: Flask application is already initialized.

Check failure on line 109 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.8, pypi)

test_cover_template_blocks RuntimeError: Flask application is already initialized.

Check failure on line 109 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.9, pypi)

test_cover_template_blocks RuntimeError: Flask application is already initialized.
InvenioAssets(app)

with app.test_request_context():
Expand All @@ -123,7 +123,7 @@
"""

blocks = ["page_body", "settings_menu", "settings_content", "settings_form"]
InvenioTheme(app)

Check failure on line 126 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.7, pypi)

test_settings_template_blocks RuntimeError: Flask application is already initialized.

Check failure on line 126 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.8, pypi)

test_settings_template_blocks RuntimeError: Flask application is already initialized.

Check failure on line 126 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.9, pypi)

test_settings_template_blocks RuntimeError: Flask application is already initialized.
InvenioAssets(app)

with app.test_request_context():
Expand All @@ -140,11 +140,12 @@
"brand",
"navbar_inner",
"navbar_right",
"breadcrumbs",
"flashmessages",
"navbar_nav",
"navbar_search",
]
InvenioTheme(app)

Check failure on line 148 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.7, pypi)

test_header_template_blocks RuntimeError: Flask application is already initialized.

Check failure on line 148 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.8, pypi)

test_header_template_blocks RuntimeError: Flask application is already initialized.

Check failure on line 148 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.9, pypi)

test_header_template_blocks RuntimeError: Flask application is already initialized.
InvenioAssets(app)
with app.test_request_context():
assert_template_blocks("invenio_theme/header.html", blocks)
Expand All @@ -170,7 +171,7 @@
"""Render default page."""
return render_template_string(base_tpl)

InvenioTheme(app)

Check failure on line 174 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.7, pypi)

test_html_lang RuntimeError: Flask application is already initialized.

Check failure on line 174 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.8, pypi)

test_html_lang RuntimeError: Flask application is already initialized.

Check failure on line 174 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.9, pypi)

test_html_lang RuntimeError: Flask application is already initialized.
InvenioAssets(app)

with app.test_client() as client:
Expand All @@ -187,7 +188,7 @@
def test_frontpage_not_exists(app):
"""Test the frontpage that doesn't exist."""
# Before configure the frontpage
InvenioTheme(app)

Check failure on line 191 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.7, pypi)

test_frontpage_not_exists RuntimeError: Flask application is already initialized.

Check failure on line 191 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.8, pypi)

test_frontpage_not_exists RuntimeError: Flask application is already initialized.

Check failure on line 191 in tests/test_invenio_theme.py

View workflow job for this annotation

GitHub Actions / Tests (3.9, pypi)

test_frontpage_not_exists RuntimeError: Flask application is already initialized.
InvenioAssets(app)
with app.test_client() as client:
response = client.get("/")
Expand Down
Loading