From c8644a10455639e575742d0722477de67e610f5a Mon Sep 17 00:00:00 2001 From: Guillaume Viger Date: Tue, 7 May 2024 13:17:41 -0400 Subject: [PATCH 1/3] membership-requests [#855]: waiting flow: add community-membership-request discussion page - add necessary template variable - add style - generalize header macro membership-requests [#855]: waiting flow: dashboard --- .../communities_ui/views/communities.py | 27 ++++++++++++++++--- .../community_dashboard.html | 4 +-- .../community-invitation/user_dashboard.html | 4 +-- .../user_dashboard.html | 26 ++++++++++++++++++ .../macros/request_header.html | 4 +-- .../theme/elements/input.overrides | 3 ++- 6 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-membership-request/user_dashboard.html diff --git a/invenio_app_rdm/communities_ui/views/communities.py b/invenio_app_rdm/communities_ui/views/communities.py index ba501d9ac..0a6d16332 100644 --- a/invenio_app_rdm/communities_ui/views/communities.py +++ b/invenio_app_rdm/communities_ui/views/communities.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # Copyright (C) 2019-2024 CERN. -# Copyright (C) 2019-2022 Northwestern University. +# Copyright (C) 2019-2024 Northwestern University. # Copyright (C) 2022 TU Wien. # # Invenio App RDM is free software; you can redistribute it and/or modify it @@ -9,6 +9,7 @@ """Request views module.""" from flask import abort, g, redirect, request, url_for +from invenio_communities.proxies import current_communities from invenio_communities.views.communities import ( HEADER_PERMISSIONS, render_community_theme_template, @@ -26,17 +27,22 @@ def communities_detail(pid_value, community, community_ui): """Community detail page.""" permissions = community.has_permissions_to(HEADER_PERMISSIONS) endpoint = "/api/communities/{pid_value}/records" + members_service = current_communities.service.members return render_community_theme_template( "invenio_communities/records/index.html", theme=community_ui.get("theme", {}), - community=community, - community_ui=community_ui, + community=community_ui, # Pass permissions so we can disable partially UI components # e.g Settings tab permissions=permissions, active_community_header_menu_item="search", endpoint=endpoint.format(pid_value=community.to_dict()["id"]), + associated_request_id=( + members_service.get_pending_request_id_if_any( + g.identity.id, community.id + ) + ) ) @@ -96,6 +102,9 @@ def communities_home(pid_value, community, community_ui): "hits" ] + members_service = current_communities.service.members + + return render_community_theme_template( "invenio_communities/details/home/index.html", theme=community_ui.get("theme", {}), @@ -103,6 +112,11 @@ def communities_home(pid_value, community, community_ui): permissions=permissions, records=records_ui, metrics=metrics, + associated_request_id=( # in case public + members_service.get_pending_request_id_if_any( + g.identity.id, community.id + ) + ) ) @@ -115,14 +129,19 @@ def community_static_page(pid_value, community, community_ui, **kwargs): try: page = current_pages_service.read_by_url(g.identity, request.path).to_dict() - except PageNotFoundError: abort(404) + members_service = current_communities.service.members + return render_community_theme_template( page["template_name"], theme=community_ui.get("theme", {}), page=page, community=community_ui, permissions=permissions, + associated_request_id=( # in case public + members_service.get_pending_request_id_if_any( + g.identity.id, community.id) + ) ) diff --git a/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-invitation/community_dashboard.html b/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-invitation/community_dashboard.html index a49d96ff8..6b8deb3b2 100644 --- a/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-invitation/community_dashboard.html +++ b/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-invitation/community_dashboard.html @@ -8,7 +8,7 @@ #} {% set title = invenio_request.title %} {% extends "invenio_requests/details/index.html" %} -{% from "invenio_requests/macros/request_header.html" import invitation_request_header %} +{% from "invenio_requests/macros/request_header.html" import member_request_header %} {% set active_community_header_menu_item = 'members' %} {% set active_members_menu_item = 'invitations' %} @@ -16,7 +16,7 @@ {% block request_header %} {% set back_button_url = url_for("invenio_communities.invitations", pid_value=invenio_request.created_by.community) %} {{ - invitation_request_header( + member_request_header( back_button_url=back_button_url, back_button_text=_("Back to invitations"), request=invenio_request diff --git a/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-invitation/user_dashboard.html b/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-invitation/user_dashboard.html index 79d8d70e9..0e56a863c 100644 --- a/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-invitation/user_dashboard.html +++ b/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-invitation/user_dashboard.html @@ -8,13 +8,13 @@ #} {% set title = invenio_request.title %} {% extends "invenio_requests/details/index.html" %} -{% from "invenio_requests/macros/request_header.html" import invitation_request_header %} +{% from "invenio_requests/macros/request_header.html" import member_request_header %} {% block request_header %} {% set back_button_url = url_for("invenio_app_rdm_users.requests") %} {{ - invitation_request_header( + member_request_header( back_button_url=back_button_url, back_button_text=_("Back to requests"), request=invenio_request, diff --git a/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-membership-request/user_dashboard.html b/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-membership-request/user_dashboard.html new file mode 100644 index 000000000..869f70e78 --- /dev/null +++ b/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-membership-request/user_dashboard.html @@ -0,0 +1,26 @@ +{# -*- coding: utf-8 -*- + + This file is part of Invenio. + Copyright (C) 2022 CERN. + Copyright (C) 2024 Northwestern University. + + 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. +#} +{% set title = invenio_request.title %} +{% extends "invenio_requests/details/index.html" %} +{% from "invenio_requests/macros/request_header.html" import member_request_header %} + + +{% block request_header %} + {{ + member_request_header( + back_button_url=url_for("invenio_app_rdm_users.requests"), + back_button_text=_("Back to requests"), + request=invenio_request, + accepted=request_is_accepted + ) + }} +{% endblock %} + +{% set active_dashboard_menu_item = 'requests' %} diff --git a/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/macros/request_header.html b/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/macros/request_header.html index 557b05837..dc6110521 100644 --- a/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/macros/request_header.html +++ b/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/macros/request_header.html @@ -1,8 +1,8 @@ {%- from "invenio_app_rdm/records/macros/creatibutors.html" import show_creatibutors %} -{% macro invitation_request_header(back_button_url=None, back_button_text=None, request=None, accepted=False) %} +{% macro member_request_header(back_button_url=None, back_button_text=None, request=None, accepted=False) %} {# - Renders the member invitation request header block with: + Renders the member invitation/membership request header block with: - a back button - a `View community` button, when accepted - the request's title diff --git a/invenio_app_rdm/theme/assets/semantic-ui/less/invenio_app_rdm/theme/elements/input.overrides b/invenio_app_rdm/theme/assets/semantic-ui/less/invenio_app_rdm/theme/elements/input.overrides index eccc9fb2d..1dbcc92d1 100644 --- a/invenio_app_rdm/theme/assets/semantic-ui/less/invenio_app_rdm/theme/elements/input.overrides +++ b/invenio_app_rdm/theme/assets/semantic-ui/less/invenio_app_rdm/theme/elements/input.overrides @@ -2,7 +2,8 @@ Invenio App RDM Input Overrides ***********************************************/ -.input.invitation-searchbar { +.input.invitation-searchbar, +.input.member-requests-searchbar { width: 100%; } From ce9406997fd054a0b300d3af28f019e9ee6d0fd1 Mon Sep 17 00:00:00 2001 From: Guillaume Viger Date: Fri, 26 Jul 2024 09:01:29 -0400 Subject: [PATCH 2/3] membership-request [#855]: configure notification builders --- invenio_app_rdm/config.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/invenio_app_rdm/config.py b/invenio_app_rdm/config.py index 1e28d6f81..2cf923df1 100644 --- a/invenio_app_rdm/config.py +++ b/invenio_app_rdm/config.py @@ -45,6 +45,11 @@ CommunityInvitationDeclineNotificationBuilder, CommunityInvitationExpireNotificationBuilder, CommunityInvitationSubmittedNotificationBuilder, + CommunityMembershipRequestAcceptNotificationBuilder, + CommunityMembershipRequestCancelNotificationBuilder, + CommunityMembershipRequestDeclineNotificationBuilder, + CommunityMembershipRequestExpireNotificationBuilder, + CommunityMembershipRequestSubmittedNotificationBuilder, ) from invenio_notifications.backends import EmailNotificationBackend from invenio_rdm_records.notifications.builders import ( @@ -1320,6 +1325,12 @@ def github_link_render(record): community_notifications.SubCommunityCreate.type: community_notifications.SubCommunityCreate, community_notifications.SubCommunityAccept.type: community_notifications.SubCommunityAccept, community_notifications.SubCommunityDecline.type: community_notifications.SubCommunityDecline, + # Community membership request + CommunityMembershipRequestAcceptNotificationBuilder.type: CommunityMembershipRequestAcceptNotificationBuilder, + CommunityMembershipRequestCancelNotificationBuilder.type: CommunityMembershipRequestCancelNotificationBuilder, + CommunityMembershipRequestDeclineNotificationBuilder.type: CommunityMembershipRequestDeclineNotificationBuilder, + CommunityMembershipRequestExpireNotificationBuilder.type: CommunityMembershipRequestExpireNotificationBuilder, + CommunityMembershipRequestSubmittedNotificationBuilder.type: CommunityMembershipRequestSubmittedNotificationBuilder, } """Notification builders.""" From 77aa1b745c1a5e1e4e4d41bf9c845244fbfdae93 Mon Sep 17 00:00:00 2001 From: Guillaume Viger Date: Mon, 29 Jul 2024 15:30:56 -0400 Subject: [PATCH 3/3] membership-requests [#855]: add discussion page in community dashboard [+] - also fix top menu to display "Members" --- .../community_dashboard.html | 38 +++++++++++++++++++ invenio_app_rdm/requests_ui/views/requests.py | 30 ++++++++++++--- 2 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-membership-request/community_dashboard.html diff --git a/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-membership-request/community_dashboard.html b/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-membership-request/community_dashboard.html new file mode 100644 index 000000000..b4e3e4bed --- /dev/null +++ b/invenio_app_rdm/requests_ui/templates/semantic-ui/invenio_requests/community-membership-request/community_dashboard.html @@ -0,0 +1,38 @@ +{# -*- coding: utf-8 -*- + + This file is part of Invenio. + Copyright (C) 2022 CERN. + Copyright (C) 2024 Northwestern University + + 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. +#} +{% set title = invenio_request.title %} +{% extends "invenio_requests/details/index.html" %} +{% from "invenio_requests/macros/request_header.html" import member_request_header %} + +{% set active_community_header_menu_item = 'members' %} +{% set active_members_menu_item = 'membership_requests' %} + +{% block request_header %} + {{ + member_request_header( + back_button_url=url_for("invenio_communities.membership_requests", pid_value=invenio_request.receiver.community), + back_button_text=_("Back to membership requests"), + request=invenio_request + ) + }} +{% endblock %} + + +{% block settings_body %} +
+ {% block request_body %} + {{ super() }} + {% endblock request_body %} +
+{% endblock %} + +{% block page_body %} + {{ super.super() }} +{% endblock page_body %} diff --git a/invenio_app_rdm/requests_ui/views/requests.py b/invenio_app_rdm/requests_ui/views/requests.py index 34d39ceda..0d29771c7 100644 --- a/invenio_app_rdm/requests_ui/views/requests.py +++ b/invenio_app_rdm/requests_ui/views/requests.py @@ -12,7 +12,10 @@ from flask import g, render_template from flask_login import current_user, login_required from invenio_communities.config import COMMUNITIES_ROLES -from invenio_communities.members.services.request import CommunityInvitation +from invenio_communities.members.services.request import ( + CommunityInvitation, + MembershipRequestRequestType, +) from invenio_communities.proxies import current_identities_cache from invenio_communities.subcommunities.services.request import SubCommunityRequest from invenio_communities.utils import identity_cache_key @@ -240,8 +243,11 @@ def community_dashboard_request_view(request, community, community_ui, **kwargs) is_draft_submission = request_type == CommunitySubmission.type_id is_record_inclusion = request_type == CommunityInclusion.type_id - is_member_invitation = request_type == CommunityInvitation.type_id is_subcommunity_request = request_type == SubCommunityRequest.type_id + types_of_member_requests = [ + CommunityInvitation.type_id, + MembershipRequestRequestType.type_id, + ] request_is_accepted = request["status"] == AcceptAction.status_to permissions = community.has_permissions_to( @@ -277,9 +283,23 @@ def community_dashboard_request_view(request, community, community_ui, **kwargs) include_deleted=False, ) - elif is_member_invitation: - if not permissions["can_search_invites"]: - raise PermissionDeniedError() + elif request_type in types_of_member_requests: + permissions = community.has_permissions_to( + [ + "update", + "read", + "search_requests", + "members_search_public", + "search_invites", + "search_membership_requests", + ] + ) + if request_type == CommunityInvitation.type_id: + if not permissions["can_search_invites"]: + raise PermissionDeniedError() + else: # is a membership request + if not permissions["can_search_membership_requests"]: + raise PermissionDeniedError() return render_community_theme_template( f"invenio_requests/{request_type}/community_dashboard.html",