diff --git a/hypha/apply/dashboard/templates/dashboard/dashboard.html b/hypha/apply/dashboard/templates/dashboard/dashboard.html index 6f228a04e3b5697de26763442aac33bbe871bf95..512e79bb32af07109f3dced0725ed4356726825e 100644 --- a/hypha/apply/dashboard/templates/dashboard/dashboard.html +++ b/hypha/apply/dashboard/templates/dashboard/dashboard.html @@ -36,20 +36,35 @@ <div class="stat-block__view">{% trans "View" %}</div> {% endif %} </a> - <a href="#active-projects" class="stat-block__item border shadow-sm"> - <p class="stat-block__number">{{ projects.count }}</p> - <p class="stat-block__text">{% trans "Live projects under your management" %}</p> - {% if projects.count %} - <div class="stat-block__view">{% trans "View" %}</div> + {% if PROJECTS_ENABLED %} + <a href="#active-projects" class="stat-block__item border shadow-sm"> + <p class="stat-block__number">{{ projects.count }}</p> + <p class="stat-block__text">{% trans "Live projects under your management" %}</p> + {% if projects.count %} + <div class="stat-block__view">{% trans "View" %}</div> + {% endif %} + </a> + <a href="#active-invoices" class="stat-block__item border shadow-sm"> + <p class="stat-block__number">{{ active_invoices.count }}</p> + <p class="stat-block__text">{% trans "Requests for invoices requiring your attention" %}</p> + {% if active_invoices.count %} + <div class="stat-block__view">{% trans "View" %}</div> + {% endif %} + </a> + {% else %} + {% if my_flagged.table.data %} + <a href="#submissions-flagged" class="stat-block__item border shadow-sm"> + <p class="stat-block__number">{{ my_flagged.table.rows|length }}</p> + <p class="stat-block__text">Your flagged submissions</p> + </a> {% endif %} - </a> - <a href="#active-invoices" class="stat-block__item border shadow-sm"> - <p class="stat-block__number">{{ active_invoices.count }}</p> - <p class="stat-block__text">{% trans "Requests for invoices requiring your attention" %}</p> - {% if active_invoices.count %} - <div class="stat-block__view">{% trans "View" %}</div> + {% if my_reviewed.table.data %} + <a href="#my-review" class="stat-block__item border shadow-sm"> + <p class="stat-block__number">{{ my_reviewed.table.rows|length }}</p> + <p class="stat-block__text">Your previous reviews</p> + </a> {% endif %} - </a> + {% endif %} </div> </div> @@ -67,14 +82,14 @@ {% include "funds/includes/round-block.html" with can_export=can_export closed_rounds=rounds.closed open_rounds=rounds.open title="Your rounds and labs" page_type='dashboard' %} {% endif %} - {% if paf_for_review.count %} + {% if PROJECTS_ENABLED and paf_for_review.count %} <div id="paf_for_review" class="wrapper wrapper--bottom-space"> <h4 class="heading heading--normal">{% trans "PAFs for review" %}</h4> {% render_table paf_for_review.table %} </div> {% endif %} - {% if projects.table.data %} + {% if PROJECTS_ENABLED and projects.table.data %} <div id="active-projects" class="wrapper wrapper--bottom-space"> {% trans "Your projects" as project_heading %} {% include "funds/includes/table_filter_and_search.html" with filter=projects.filterset filter_action=projects.url search_term=search_term search_action=projects.url search_placeholder="projects" use_search=True use_batch_actions=False heading="Your projects" %} @@ -85,11 +100,10 @@ <a href="{{ projects.url }}?lead={{ request.user.pk }}">{% trans "Show all" %}</a> </div> {% endif %} - </div> {% endif %} - {% if active_invoices.count %} + {% if PROJECTS_ENABLED and active_invoices.count %} <div id="active-invoices" class="wrapper wrapper--bottom-space"> <h4 class="heading heading--normal">{% trans "Active Invoices" %}</h4> {% render_table active_invoices.table %} diff --git a/hypha/apply/utils/templatetags/apply_tags.py b/hypha/apply/utils/templatetags/apply_tags.py index 06b19b8415cfc2cbbaca6b5dae8374082cf50a69..726f21037f2868a743d3ed63d4e0966e82b03d61 100644 --- a/hypha/apply/utils/templatetags/apply_tags.py +++ b/hypha/apply/utils/templatetags/apply_tags.py @@ -3,6 +3,8 @@ from django import template from django.conf import settings from django.template.defaultfilters import stringfilter +from hypha.core.navigation import get_primary_navigation_items + register = template.Library() @@ -38,3 +40,8 @@ def truncatechars_middle(value, arg): return value else: return "{}...{}".format(value[: ln // 2], value[-((ln + 1) // 2) :]) + + +@register.simple_tag +def primary_navigation_items(user): + return get_primary_navigation_items(user) diff --git a/hypha/core/navigation.py b/hypha/core/navigation.py index 2e77ea2683b773ea6f1aad5d50db175c44b429ec..d951d782e8656989b591143c5b7f185b29f4c2e0 100644 --- a/hypha/core/navigation.py +++ b/hypha/core/navigation.py @@ -1,43 +1,48 @@ +import copy +import functools +import importlib + from django.conf import settings +from django.core.exceptions import PermissionDenied from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ -nav_items = [ +DEFAULT_NAV_ITEMS = [ { "title": _("My Dashboard"), "url": reverse_lazy("dashboard:dashboard"), - "permission_method": "has_dashboard_access", + "permission_method": "hypha.apply.users.decorators.has_dashboard_access", }, { "title": _("Submissions"), # kind of basic url to figure out active tab "url": reverse_lazy("apply:submissions:overview"), - "permission_method": "is_apply_staff_or_reviewer_required", + "permission_method": "hypha.apply.users.decorators.is_apply_staff_or_reviewer_required", "sub_items": [ { "title": _("All Submissions"), "url": reverse_lazy("apply:submissions:list"), - "permission_method": "is_apply_staff_or_reviewer_required", + "permission_method": "hypha.apply.users.decorators.is_apply_staff_or_reviewer_required", }, { "title": _("Staff Assignments"), "url": reverse_lazy("apply:submissions:staff_assignments"), - "permission_method": "is_apply_staff", + "permission_method": "hypha.apply.users.decorators.is_apply_staff", }, { "title": _("Reviews"), "url": reverse_lazy("apply:submissions:reviewer_leaderboard"), - "permission_method": "is_apply_staff", + "permission_method": "hypha.apply.users.decorators.is_apply_staff", }, { "title": _("Results"), "url": reverse_lazy("apply:submissions:result"), - "permission_method": "is_apply_staff", + "permission_method": "hypha.apply.users.decorators.is_apply_staff", }, { "title": _("Staff flagged"), "url": reverse_lazy("apply:submissions:staff_flagged"), - "permission_method": "is_apply_staff", + "permission_method": "hypha.apply.users.decorators.is_apply_staff", }, ], }, @@ -45,33 +50,73 @@ nav_items = [ "title": _("Projects"), # kind of basic url to figure out active tab "url": reverse_lazy("apply:projects:overview"), - "permission_method": "is_apply_staff_or_finance_or_contracting", + "permission_method": "hypha.apply.users.decorators.is_apply_staff_or_finance_or_contracting", "sub_items": [ { "title": _("All Projects"), "url": reverse_lazy("apply:projects:all"), - "permission_method": "is_apply_staff_or_finance_or_contracting", + "permission_method": "hypha.apply.users.decorators.is_apply_staff_or_finance_or_contracting", }, { "title": _("Invoices"), "url": reverse_lazy("apply:projects:invoices"), - "permission_method": "is_apply_staff_or_finance", + "permission_method": "hypha.apply.users.decorators.is_apply_staff_or_finance", }, { "title": _("Reports"), "url": reverse_lazy("apply:projects:reports:all"), - "permission_method": "is_apply_staff_or_finance", + "permission_method": "hypha.apply.users.decorators.is_apply_staff_or_finance", }, ], }, ] -if settings.APPLY_NAV_MENU_ITEMS: - nav_items = settings.APPLY_NAV_MENU_ITEMS +def _check_permission(user, method: str) -> bool: + """Resolve the method path and check if the user has permission. + + Args: + user: user object + method: import path to the method to check permission + + Returns: + bool: True if user has permission, False otherwise + """ + module = importlib.import_module(method.rsplit(".", 1)[0]) + method = method.rsplit(".", 1)[1] + try: + return getattr(module, method)(user) + except PermissionDenied: + return False + + +@functools.cache +def get_primary_navigation_items(user): + """Get the primary navigation items based on user permissions.""" + original_nav_items = copy.deepcopy( + settings.APPLY_NAV_MENU_ITEMS or DEFAULT_NAV_ITEMS + ) + + nav_items = [] + + for item in original_nav_items: + nav_item = item.copy() + + if item["title"] == "Projects" and not settings.PROJECTS_ENABLED: + continue + + if item["title"] == "Submissions" and settings.APPLY_NAV_SUBMISSIONS_ITEMS: + nav_item["sub_items"] = settings.APPLY_NAV_SUBMISSIONS_ITEMS -if settings.APPLY_NAV_SUBMISSIONS_ITEMS: - nav_items[1]["sub_items"] = settings.APPLY_NAV_SUBMISSIONS_ITEMS + if not _check_permission(user, nav_item["permission_method"]): + continue + if sub_items := nav_item.get("sub_items"): + nav_item["sub_items"] = list( + filter( + lambda x: _check_permission(user, x["permission_method"]), + sub_items, + ) + ) + nav_items.append(nav_item) -if settings.APPLY_NAV_PROJECTS_ITEMS: - nav_items[2]["sub_items"] = settings.APPLY_NAV_PROJECTS_ITEMS + return nav_items diff --git a/hypha/core/templates/core/navigation/primarynav-apply.html b/hypha/core/templates/core/navigation/primarynav-apply.html index 176b4e8f11c310a45423f37c18f66bbaf96384e5..e7fec3ba7a53c0a25fe64e8259f3d04fde133f6c 100644 --- a/hypha/core/templates/core/navigation/primarynav-apply.html +++ b/hypha/core/templates/core/navigation/primarynav-apply.html @@ -1,8 +1,9 @@ -{% load i18n applynav_tags heroicons %} +{% load i18n apply_tags heroicons %} + {% if request.user.is_authenticated %} <nav role="navigation" aria-label="Primary" class="w-full"> <ul class="nav nav--primary" role="menubar"> - {% apply_nav_items request.user as nav_items %} + {% primary_navigation_items request.user as nav_items %} {% for item in nav_items %} <li class="nav__item" role="presentation" diff --git a/hypha/core/templatetags/applynav_tags.py b/hypha/core/templatetags/applynav_tags.py deleted file mode 100644 index 64e6fe0b61d77049220b1f00132ca660ce9d2119..0000000000000000000000000000000000000000 --- a/hypha/core/templatetags/applynav_tags.py +++ /dev/null @@ -1,40 +0,0 @@ -import copy - -from django import template -from django.core.exceptions import PermissionDenied - -from hypha.apply.users import decorators - -from ..navigation import nav_items - -register = template.Library() - - -def has_permission(user, method): - try: - if getattr(decorators, method)(user): - return True - return False - except PermissionDenied: - return False - except Exception: - # just to handle unknown exceptions - return False - - -@register.simple_tag -def apply_nav_items(user): - temp_nav = copy.deepcopy(nav_items) - item_count = 0 - for item in nav_items: - item_count = +1 - removed = False - if not has_permission(user, item["permission_method"]): - temp_nav.remove(item) - removed = True - item_count = -1 - if not removed and "sub_items" in item.keys(): - for sub_item in item["sub_items"]: - if not has_permission(user, sub_item["permission_method"]): - temp_nav[item_count]["sub_items"].remove(sub_item) - return temp_nav