From 0984972b0509530c1ecf6887b3484c256862f64c Mon Sep 17 00:00:00 2001 From: Hugh Rundle Date: Sat, 2 Oct 2021 12:30:48 +1000 Subject: [PATCH] group membership invitations - fix display of group information on user and group pages - send, receive, accept and reject invitations --- bookwyrm/templates/groups/members.html | 1 + .../templates/groups/suggested_users.html | 2 +- bookwyrm/templates/groups/user_groups.html | 4 +- bookwyrm/templates/notifications.html | 13 +++- .../snippets/add_to_group_button.html | 16 ++--- .../snippets/join_invitation_buttons.html | 16 +++++ bookwyrm/templates/user/groups.html | 6 +- bookwyrm/templates/user/layout.html | 3 +- bookwyrm/views/__init__.py | 2 +- bookwyrm/views/group.py | 68 +++++++------------ 10 files changed, 72 insertions(+), 59 deletions(-) create mode 100644 bookwyrm/templates/snippets/join_invitation_buttons.html diff --git a/bookwyrm/templates/groups/members.html b/bookwyrm/templates/groups/members.html index a08e73b9..3ee27db6 100644 --- a/bookwyrm/templates/groups/members.html +++ b/bookwyrm/templates/groups/members.html @@ -20,6 +20,7 @@ Manager {% endif %} + {% include 'snippets/add_to_group_button.html' with user=member group=group minimal=True %} {% if member.mutuals %}

diff --git a/bookwyrm/templates/groups/suggested_users.html b/bookwyrm/templates/groups/suggested_users.html index 6323ffbe..ce5eab6d 100644 --- a/bookwyrm/templates/groups/suggested_users.html +++ b/bookwyrm/templates/groups/suggested_users.html @@ -37,7 +37,7 @@ {% endfor %} {% else %} - No users found for {{ query }} + No potential members found for "{{ query }}" {% endif %} diff --git a/bookwyrm/templates/groups/user_groups.html b/bookwyrm/templates/groups/user_groups.html index f99abc69..ef69a5a4 100644 --- a/bookwyrm/templates/groups/user_groups.html +++ b/bookwyrm/templates/groups/user_groups.html @@ -3,7 +3,8 @@ {% load interaction %}

- {% for group in groups %} + {% for membership in memberships %} + {% with group=membership.group %}
@@ -31,5 +32,6 @@
+ {% endwith %} {% endfor %} diff --git a/bookwyrm/templates/notifications.html b/bookwyrm/templates/notifications.html index ae5cd67b..8dba38c6 100644 --- a/bookwyrm/templates/notifications.html +++ b/bookwyrm/templates/notifications.html @@ -42,7 +42,7 @@ {% elif notification.notification_type == 'REPLY' %} - {% elif notification.notification_type == 'FOLLOW' or notification.notification_type == 'FOLLOW_REQUEST' %} + {% elif notification.notification_type == 'FOLLOW' or notification.notification_type == 'FOLLOW_REQUEST' or notification.notification_type == 'INVITE' or notification.notification_type == 'ACCEPT' %} {% elif notification.notification_type == 'BOOST' %} @@ -122,6 +122,17 @@ {% else %} {% blocktrans with book_path=notification.related_list_item.book.local_path book_title=notification.related_list_item.book.title list_path=notification.related_list_item.book_list.local_path list_name=notification.related_list_item.book_list.name %} suggested adding {{ book_title }} to your list "{{ list_name }}"{% endblocktrans %} {% endif %} + {% elif notification.notification_type == 'INVITE' %} + {% if notification.related_group %} + {% blocktrans with group_name=notification.related_group.name group_path=notification.related_group.local_path %} invited you to join the group {{ group_name }} {% endblocktrans %} +
+ {% include 'snippets/join_invitation_buttons.html' with group=notification.related_group %} +
+ {% endif %} + {% elif notification.notification_type == 'ACCEPT' %} + {% if notification.related_group %} + {% blocktrans with group_name=notification.related_group.name group_path=notification.related_group.local_path %} accepted an invitation to join your group "{{ group_name }}"{% endblocktrans %} + {% endif %} {% endif %} {% elif notification.related_import %} {% url 'import-status' notification.related_import.id as url %} diff --git a/bookwyrm/templates/snippets/add_to_group_button.html b/bookwyrm/templates/snippets/add_to_group_button.html index 7febe2b1..dd3b93c3 100644 --- a/bookwyrm/templates/snippets/add_to_group_button.html +++ b/bookwyrm/templates/snippets/add_to_group_button.html @@ -24,22 +24,22 @@ Remote User {% endif %} -
+ {% csrf_token %} - {% if group|is_invited:user %} + {% if not group|is_member:user %} {% else %} + {% if show_username %} + {% blocktrans with username=user.localname %}Remove @{{ username }}{% endblocktrans %} + {% else %} + {% trans "Remove" %} + {% endif %} + {% endif %}
diff --git a/bookwyrm/templates/snippets/join_invitation_buttons.html b/bookwyrm/templates/snippets/join_invitation_buttons.html new file mode 100644 index 00000000..46c4071d --- /dev/null +++ b/bookwyrm/templates/snippets/join_invitation_buttons.html @@ -0,0 +1,16 @@ +{% load i18n %} +{% load bookwyrm_group_tags %} +{% if group|is_invited:request.user %} +
+
+ {% csrf_token %} + + +
+
+ {% csrf_token %} + + +
+
+{% endif %} diff --git a/bookwyrm/templates/user/groups.html b/bookwyrm/templates/user/groups.html index 2735a5b8..9c91fb18 100644 --- a/bookwyrm/templates/user/groups.html +++ b/bookwyrm/templates/user/groups.html @@ -24,7 +24,7 @@ {% block panel %}
-
- {% include 'snippets/pagination.html' with page=user_groups path=path %} + {% include 'snippets/pagination.html' with page=user.memberships path=path %}
{% endblock %} diff --git a/bookwyrm/templates/user/layout.html b/bookwyrm/templates/user/layout.html index a1a5289d..c4ef2d8e 100755 --- a/bookwyrm/templates/user/layout.html +++ b/bookwyrm/templates/user/layout.html @@ -4,6 +4,7 @@ {% load utilities %} {% load markdown %} {% load layout %} +{% load bookwyrm_group_tags %} {% block title %}{{ user.display_name }}{% endblock %} @@ -75,7 +76,7 @@ {% trans "Lists" %} {% endif %} - {% if is_self or user.bookwyrm_groups %} + {% if is_self or user|has_groups %} {% url 'user-groups' user|username as url %} {% trans "Groups" %} diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index fb9e72bc..930fdfcd 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -32,7 +32,7 @@ from .follow import follow, unfollow from .follow import accept_follow_request, delete_follow_request from .get_started import GetStartedBooks, GetStartedProfile, GetStartedUsers from .goal import Goal, hide_goal -from .group import BookwyrmGroup, UserGroups, FindUsers, invite_member, remove_member, uninvite_member, accept_membership, reject_membership +from .group import BookwyrmGroup, UserGroups, FindUsers, invite_member, remove_member, accept_membership, reject_membership from .import_data import Import, ImportStatus from .inbox import Inbox from .interaction import Favorite, Unfavorite, Boost, Unboost diff --git a/bookwyrm/views/group.py b/bookwyrm/views/group.py index 09bb0dca..60ca8d21 100644 --- a/bookwyrm/views/group.py +++ b/bookwyrm/views/group.py @@ -57,11 +57,11 @@ class UserGroups(View): def get(self, request, username): """display a group""" user = get_user_from_username(request.user, username) - groups = user.bookwyrmgroup_set.all() # follow the relationship backwards, nice - paginated = Paginator(groups, 12) + memberships = models.BookwyrmGroupMember.objects.filter(user=user).all() + paginated = Paginator(memberships, 12) data = { - "groups": paginated.get_page(request.GET.get("page")), + "memberships": paginated.get_page(request.GET.get("page")), "is_self": request.user.id == user.id, "user": user, "group_form": forms.GroupForm(), @@ -89,8 +89,10 @@ class FindUsers(View): def get(self, request, group_id): """basic profile info""" query = request.GET.get("query") + group = models.BookwyrmGroup.objects.get(id=group_id) user_results = ( models.User.viewer_aware_objects(request.user) + .exclude(memberships__in=group.memberships.all()) # don't suggest users who are already members .annotate( similarity=Greatest( TrigramSimilarity("username", query), @@ -149,7 +151,7 @@ def invite_member(request): @require_POST @login_required -def uninvite_member(request): +def remove_member(request): """invite a member to the group""" group = get_object_or_404(models.BookwyrmGroup, id=request.POST.get("group")) @@ -160,51 +162,31 @@ def uninvite_member(request): if not user: return HttpResponseBadRequest() - if not group.user == request.user: - return HttpResponseBadRequest() + is_member = models.BookwyrmGroupMember.objects.filter(group=group,user=user).exists() + is_invited = models.GroupMemberInvitation.objects.filter(group=group,user=user).exists() - try: - invitation = models.GroupMemberInvitation.objects.get( - user=user, - group=group - ) + if is_invited: + try: + invitation = models.GroupMemberInvitation.objects.get( + user=user, + group=group + ) - invitation.reject() + invitation.reject() - except IntegrityError: - pass + except IntegrityError: + pass - return redirect(user.local_path) + if is_member: -@require_POST -@login_required -def remove_member(request): - """remove a member from the group""" + try: + membership = models.BookwyrmGroupMember.objects.get(group=group,user=user) + membership.delete() - # TODO: send notification to user telling them they have been removed - # TODO: remove yourself from a group!!!! (except owner) - # FUTURE TODO: transfer ownership of group - # THIS LOGIC SHOULD BE IN MODEL + except IntegrityError: + pass - # TODO: if groups become AP values we need something like get_group_from_group_fullname - # group = get_object_or_404(models.Group, id=request.POST.get("group")) # NOTE: does this not work? - group = models.BookwyrmGroup.objects.get(id=request.POST["group"]) - if not group: - return HttpResponseBadRequest() - - user = get_user_from_username(request.user, request.POST["user"]) - if not user: - return HttpResponseBadRequest() - - if not group.user == request.user: - return HttpResponseBadRequest() - - try: - membership = models.BookwyrmGroupMember.objects.get(group=group,user=user) # BUG: wrong - membership.delete() - - except IntegrityError: - pass + # TODO: should send notification to all members including the now ex-member that they have been removed. return redirect(user.local_path) @@ -227,7 +209,7 @@ def accept_membership(request): except IntegrityError: pass - return redirect(request.user.local_path) + return redirect(group.local_path) @require_POST @login_required