Compare commits

...

16 Commits

Author SHA1 Message Date
Christoph Ladurner
8866b87459 release v4.13.0 2025-01-24 14:44:20 +01:00
Christoph Ladurner
3a91743f9b setup: necessary because devs not released 2025-01-24 14:43:45 +01:00
Christoph Ladurner
fa705221dd view: add route for rdm-search
* it is necessary to add it here because the old approach with adding to
  the invenio-search-ui blueprint is not possible anymore since it has
  been changed to a function.
2025-01-24 14:43:45 +01:00
Christoph Ladurner
aa21adb1cf setup: relax upper pins
* the idea is to break early.
2025-01-24 14:43:45 +01:00
Martin Obersteiner
5865f0df54 add default-page for unhandled errors 2024-09-19 10:21:41 +02:00
Martin Obersteiner
4b8d5bee9f guard views/dashboard by tugraz_authenticated 2024-07-08 10:16:38 +02:00
Martin Obersteiner
923d4e8120 fix deprecated before_app_first_request 2024-06-11 13:27:04 +02:00
Christoph Ladurner
049063fd7d release v4.12.9 2024-05-07 10:53:37 +02:00
Christoph Ladurner
4a13f22de4 overview: view publications only if permission 2024-05-07 10:53:01 +02:00
Christoph Ladurner
dac35b2e0e release v4.12.8 2024-03-11 20:20:52 +01:00
Christoph Ladurner
cf5ecfd2f6 ui: add banner to header 2024-03-11 20:20:16 +01:00
Christoph Ladurner
0919760cfd release v4.12.7 2024-02-12 13:34:50 +01:00
Christoph Ladurner
40be6ff4b4 translation: fix typo 2024-02-12 13:34:18 +01:00
Christoph Ladurner
602c4b6523 release v4.12.6 2024-02-02 12:43:31 +01:00
Christoph Ladurner
4a581d6703 fix: error_handler gets 1 parameter 2024-02-02 12:43:11 +01:00
Christoph Ladurner
b426e0cc39 release v4.12.5 2024-02-02 11:21:42 +01:00
13 changed files with 297 additions and 36 deletions

View File

@@ -8,6 +8,41 @@
Changes
=======
Version v4.13.0 (release 2025-01-24)
- setup: necessary because devs not released
- view: add route for rdm-search
- setup: relax upper pins
- add default-page for unhandled errors
- guard views/dashboard by `tugraz_authenticated`
- fix deprecated `before_app_first_request`
Version v4.12.9 (release 2024-05-07)
- overview: view publications only if permission
Version v4.12.8 (release 2024-03-11)
- ui: add banner to header
Version v4.12.7 (release 2024-02-12)
- translation: fix typo
Version v4.12.6 (release 2024-02-02)
- fix: error_handler gets 1 parameter
Version v4.12.5 (release 2024-02-02)
Version v4.12.4 (release 2024-02-02)
- ui: add 423 error page

View File

@@ -10,6 +10,6 @@
from .ext import InvenioThemeTugraz
__version__ = "4.12.4"
__version__ = "4.13.0"
__all__ = ("__version__", "InvenioThemeTugraz")

View File

@@ -0,0 +1,42 @@
// Copyright (C) 2024 Graz University of Technology.
//
// invenio-theme-tugraz is free software; you can redistribute it and/or modify it
// under the terms of the MIT License; see LICENSE file for more details.
import $ from "jquery";
async function generateForm() {
// get email from `/api/me`
let email = "???";
const response = await fetch("/api/me");
if (response.ok) {
const json = await response.json();
email = json?.email || "???";
}
// show form
$.getScript("https://ub-support.tugraz.at/assets/form/form.js", () => {
$("#anchor-unlock-form").ZammadForm({
attributes: [
{},
{ defaultValue: email },
{
defaultValue: `Could you unlock my account (${email}) for research-uploads?`,
// TODO: add to defaultValue once policy on how to get accepted is decided...
},
],
modal: false,
});
// focus first entry of now-shown form
document.getElementById("zammad-form-name-inline").focus();
});
}
$(function () {
// called when DOM is ready
const generateFormElement = document.getElementById("generate-unlock-form");
if (generateFormElement) {
generateFormElement.onclick = generateForm;
}
});

View File

@@ -177,3 +177,7 @@ pre {
.ui.equal.height .ui.segment {
height: 100%;
}
.ui.flashed.message.manage {
text-align: center;
}

View File

@@ -35,10 +35,16 @@ THEME_TUGRAZ_PRODUCTION = False
has to be 'INVENIO_THEME_TUGRAZ_PRODUCTION'.
"""
THEME_TUGRAZ_SUPPORT_EMAIL = ""
"""Shown as contact-info on default error-page."""
# Invenio-theme
# ============
# See https://invenio-theme.readthedocs.io/en/latest/configuration.html
#
THEME_500_TEMPLATE = "invenio_theme_tugraz/default_error.html"
"""Used for any internal server errors and uncaught exceptions."""
THEME_LOGO = "images/tug_logo.png"
"""TU Graz logo"""

View File

@@ -8,8 +8,12 @@
"""invenio module for TUGRAZ theme."""
from flask_login import login_required
from invenio_i18n import lazy_gettext as _
from invenio_records_marc21.ui.theme import current_identity_can_view
from . import config
from .views import index, locked
from .views import index, locked, require_tugraz_authenticated
class InvenioThemeTugraz(object):
@@ -29,6 +33,10 @@ class InvenioThemeTugraz(object):
app.register_error_handler(423, locked)
@app.context_processor
def inject_visibility():
return {"can_view_marc21": current_identity_can_view()}
app.extensions["invenio-theme-tugraz"] = self
def init_config(self, app):
@@ -36,3 +44,53 @@ class InvenioThemeTugraz(object):
for k in dir(config):
if k.startswith("INVENIO_THEME_TUGRAZ_") or k.startswith("THEME_TUGRAZ_"):
app.config.setdefault(k, getattr(config, k))
def finalize_app(app):
"""Finalize app."""
modify_user_dashboard(app)
guard_view_functions(app)
def modify_user_dashboard(app):
"""Modify user dashboard."""
root_menu = app.extensions["menu"].root_node
user_dashboard_menu = root_menu.submenu("dashboard")
user_dashboard_menu.submenu("overview").register(
"invenio_theme_tugraz.overview",
text=_("Overview"),
order=0,
)
root_menu.submenu("actions.deposit").register(
"invenio_theme_tugraz.overview",
_("My dashboard"),
order=1,
)
def guard_view_functions(app):
"""Guard view-functions against unauthenticated access."""
endpoints_to_guard = [
"invenio_app_rdm_users.communities",
"invenio_app_rdm_users.requests",
"invenio_app_rdm_users.uploads",
]
for endpoint in endpoints_to_guard:
view_func = app.view_functions.get(endpoint)
if not view_func:
continue
# decorate view-func
# same as if view-func were defined with:
# @login_required
# @require_tugraz_authenticated_user
view_func = login_required(
require_tugraz_authenticated(
view_func,
),
)
app.view_functions[endpoint] = view_func

View File

@@ -0,0 +1,21 @@
{#
Copyright (C) 2024 Graz University of Technology.
invenio-theme-tugraz is free software; you can redistribute it and/or
modify it under the terms of the MIT License; see LICENSE file for more
details.
#}
{% extends config.THEME_ERROR_TEMPLATE %}
{% block message %}
<h1> {{ _('Internal server error') }} </h1>
<p>
{{ _(
'Please contact <a href="mailto:{support_email}">our support</a>
to let us know about this error.'
).format(support_email=config.THEME_TUGRAZ_SUPPORT_EMAIL)
}}
</p>
{# TODO: provide g.sentry_event_id here once sentry is configured, cf. invenio_theme/500.html #}
{% endblock message %}

View File

@@ -15,6 +15,11 @@
<div>
<header>
{%- block site_banner %}
{% from 'invenio_banners/banner.html' import banner %}
{{ banner() }}
{%- endblock site_banner %}
{%- block navbar %}
<nav>
{%- block navbar_header %}

View File

@@ -11,6 +11,11 @@
{%- set active_dashboard_menu_item = "overview" %}
{%- set title = _("Overview") %}
{% block javascript %}
{{ super() }}
{{ webpack['invenio-theme-tugraz-unlock.js'] }}
{% endblock javascript %}
{%- block page_body %}
{%- block user_dashboard_header %}
{% include "invenio_app_rdm/users/header.html" %}
@@ -19,8 +24,9 @@
<div class="ui container rel-mt-2">
<h2>Overview</h2>
<div class="ui five column stackable grid overview">
{% if is_tugraz_authenticated %}
{# 3 columns: Research-Uploads, Communities, and Requests #}
<div class="column">
<div class="ui segment" style="height: 480px">
<h2>{{ _("Research Results") }}</h2>
@@ -54,6 +60,47 @@
</div>
</div>
</div>
{% else %} {# not is_tugraz_authenticated #}
{# 1 column: greyed out Research-Uploads #}
<div class="column">
{# a modal's HTML can be placed anywhere, so I placed it here, right before it's used #}
<div class="ui small modal" id="tugraz-unlock-modal">
<div class="header">{{ _("On unlocking research uploads") }}</div>
<div class="content">
<p>
{{ _('To ensure a well-curated repository, new users need to get unlocked
before being allowed to upload. Once unlocked, you can upload your research,
request its inclusion in a community, generate a DOI for it, and publish it.') }}
{# TODO: extra lines on policy about who gets accepted how for Research-Uploads #}
</p>
<div id="anchor-unlock-form"> {# will be replaced with ZammadForm when generating it #}
<button class="ui fluid button" onclick="
$('#tugraz-unlock-modal')
.modal('hide')"
>Got it!</button>
<button id="generate-unlock-form" class="ui fluid button">
{{ _("Request unlocking") }}
</button>
</div>
</div>
</div>
{# actual column contents start here #}
<div class="ui disabled segment" style="height: 480px">
<h2>{{ _("Research Results") }}</h2>
<div class="ui left floated image" style="cursor: pointer" onclick="
$('#tugraz-unlock-modal')
.modal('show')"
>
<img width="400px" alt="Research Results" src="{{ url_for("static", filename="images/diamond.svg") }}">
</div>
<div class="ui right floated text">
{{ _("Overview: Description for research results") }}
</div>
</div>
</div>
{% endif %}
{% if can_view_marc21 %}
<div class="column">
<div class="ui segment" style="height: 480px">
<h2>{{ _("Publications") }}</h2>
@@ -65,6 +112,7 @@
</div>
</div>
</div>
{% endif %}
<div class="column">
<div class="ui segment" style="height: 480px">
<h2>{{ _("Educational Resources") }}</h2>

View File

@@ -9,7 +9,7 @@ msgstr ""
"Project-Id-Version: invenio-theme-tugraz 1.0.4\n"
"Report-Msgid-Bugs-To: mojib.wali@tugraz.at\n"
"POT-Creation-Date: 2024-02-02 10:08+0100\n"
"PO-Revision-Date: 2024-02-02 10:09+0100\n"
"PO-Revision-Date: 2024-02-09 22:25+0100\n"
"Last-Translator: \n"
"Language-Team: de <LL@li.org>\n"
"Language: de\n"
@@ -240,7 +240,7 @@ msgstr "Um die Schriftgröße zu ändern."
#: invenio_theme_tugraz/templates/invenio_theme_tugraz/navbar.html:17
#: invenio_theme_tugraz/templates/invenio_theme_tugraz/overview.html:26
msgid "Research Results"
msgstr "Forschungsergebenisse"
msgstr "Forschungsergebnisse"
#: invenio_theme_tugraz/templates/invenio_theme_tugraz/frontpage_overview.html:16
#, fuzzy

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020-2024 Graz University of Technology.
# Copyright (C) 2020-2025 Graz University of Technology.
#
# invenio-theme-tugraz is free software; you can redistribute it and/or
# modify it under the terms of the MIT License; see LICENSE file for more
@@ -8,14 +8,12 @@
"""invenio module for TUGRAZ theme."""
from functools import wraps
from typing import Dict
from flask import Blueprint, g, render_template
from flask import Blueprint, current_app, g, redirect, render_template, url_for
from flask_login import current_user, login_required
from flask_menu import current_menu
from invenio_i18n import lazy_gettext as _
# from invenio_rdm_records.resources.serializers import UIJSONSerializer
from invenio_rdm_records.proxies import current_rdm_records
from invenio_records_global_search.resources.serializers import (
GlobalSearchJSONSerializer,
)
@@ -32,6 +30,46 @@ blueprint = Blueprint(
)
@blueprint.route("/records/search")
def records_search():
"""Search page ui.
With this route it is possible to override the default route
"/search" to get to the rdm-records search. The default route will
be overriden by the global search with changing the
SEARCH_UI_SEARCH_TEMPLATE variable to the value
"invenio_records_global_search/search/search.html" in the
invenio.cfg file.
"""
return render_template("invenio_app_rdm/records/search.html")
def current_identity_is_tugraz_authenticated() -> bool:
"""Checks whether current identity has tugraz-authentication.
NOTE: Default permission-policy has no field for `tugraz_authenticated`.
Should the field not exist, the service checks against admin-permissions instead.
You probably meant to configure a custom permission-policy.
"""
rdm_service = current_rdm_records.records_service
return rdm_service.check_permission(g.identity, "tugraz_authenticated")
def require_tugraz_authenticated(view_func):
"""Decorator for guarding view-functions against unauthenticated users.
Redirects un-authenticated users to their personal dashboard's overview.
"""
@wraps(view_func)
def decorated_view(*args, **kwargs):
if not current_identity_is_tugraz_authenticated():
return redirect(url_for("invenio_theme_tugraz.overview"))
return view_func(*args, **kwargs)
return decorated_view
@blueprint.route("/me/overview")
@login_required
def overview():
@@ -39,8 +77,10 @@ def overview():
url = current_user_resources.users_service.links_item_tpl.expand(
g.identity, current_user
)["avatar"]
is_tugraz_authenticated = current_identity_is_tugraz_authenticated()
return render_template(
"invenio_theme_tugraz/overview.html",
is_tugraz_authenticated=is_tugraz_authenticated,
user_avatar=url,
)
@@ -60,22 +100,16 @@ def cast_to_dict(attr_dict):
return AttrDict.to_dict(attr_dict)
@blueprint.before_app_first_request
def modify_user_dashboard():
"""Modify user dashboard."""
user_dashboard_menu = current_menu.submenu("dashboard")
def default_error_handler(e: Exception):
"""Called when an otherwise unhandled error occurs."""
# TODO: use sentry here once it's configured
# information we might want to log for debugging the error:
# - `flask.request`, a proxy to the current http-request in which the error occured
# - `flask.session`, a proxy to the current http-session
# - `e`, the passed-in exception
# to get proxied-to objects: `flask.request._get_current_object()`
user_dashboard_menu.submenu("overview").register(
"invenio_theme_tugraz.overview",
text=_("Overview"),
order=0,
)
current_menu.submenu("actions.deposit").register(
"invenio_theme_tugraz.overview",
_("My dashboard"),
order=1,
)
return render_template(current_app.config["THEME_500_TEMPLATE"]), 500
def ui_blueprint(app):
@@ -84,6 +118,9 @@ def ui_blueprint(app):
blueprint.add_url_rule(routes["index"], view_func=index)
# base case for any otherwise unhandled exception
app.register_error_handler(Exception, default_error_handler)
return blueprint
@@ -102,6 +139,6 @@ def index():
)
def locked():
def locked(e):
"""Error page for status locked."""
return render_template("invenio_theme_tugraz/423.html")

View File

@@ -17,9 +17,10 @@ theme = WebpackThemeBundle(
entry={
"invenio-theme-tugraz-theme": "./less/invenio_theme_tugraz/theme.less",
"invenio-theme-tugraz-js": "./js/invenio_theme_tugraz/theme.js",
"invenio-theme-tugraz-unlock": "./js/invenio_theme_tugraz/unlock.js",
},
dependencies={
# add any additional npm dependencies here...
"jquery": "^3.2.1", # zammad-form, semantic-ui's modals
},
)
},

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2020-2024 Graz University of Technology.
# Copyright (C) 2020-2025 Graz University of Technology.
#
# invenio-theme-tugraz is free software; you can redistribute it and/or
# modify it under the terms of the MIT License; see LICENSE file for more
@@ -25,28 +25,30 @@ classifiers =
Programming Language :: Python
Topic :: Internet :: WWW/HTTP :: Dynamic Content
Topic :: Software Development :: Libraries :: Python Modules
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
Development Status :: 3 - Alpha
[options]
include_package_data = True
packages = find:
python_requires = >=3.9
python_requires = >=3.12
zip_safe = False
install_requires =
invenio-assets>=2.0.0
invenio-i18n>=1.3.1
invenio_config_tugraz>=0.11.0
invenio_records_global_search>=0.0.1
invenio_records_marc21>=0.21.0
[options.extras_require]
tests =
invenio-app>=1.3.4,<1.4.0
invenio-search[opensearch2]>=2.1.0,<3.0.0
invenio-app>=1.3.4,<2.0.0
invenio-previewer>=2.2.0
invenio-rdm-records<17.0.0
invenio-search[opensearch2]>=2.1.0
pytest<8.0.0
pytest-black-ng>=0.4.0
pytest-invenio>=2.1.0,<3.0.0
pytest-invenio>=2.1.0
Sphinx>=4.5.0
[options.entry_points]
@@ -60,6 +62,8 @@ invenio_assets.webpack =
invenio_theme_tugraz_theme = invenio_theme_tugraz.webpack:theme
invenio_config.module =
invenio_theme_tugraz = invenio_theme_tugraz.config
invenio_base.finalize_app =
invenio_theme_tugraz = invenio_theme_tugraz.ext:finalize_app
[aliases]
test = pytest