forked from mirrors/bookwyrm
group membership invitations
- fix display of group information on user and group pages - send, receive, accept and reject invitations
This commit is contained in:
parent
89dea44614
commit
0984972b05
10 changed files with 72 additions and 59 deletions
|
@ -20,6 +20,7 @@
|
|||
<span class="is-sr-only">Manager</span>
|
||||
</span>
|
||||
{% endif %}
|
||||
<!-- TODO: change this to a remove_from_group button -->
|
||||
{% include 'snippets/add_to_group_button.html' with user=member group=group minimal=True %}
|
||||
{% if member.mutuals %}
|
||||
<p class="help">
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
No users found for {{ query }}
|
||||
No potential members found for "{{ query }}"
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
{% load interaction %}
|
||||
|
||||
<div class="columns is-multiline">
|
||||
{% for group in groups %}
|
||||
{% for membership in memberships %}
|
||||
{% with group=membership.group %}
|
||||
<div class="column is-one-quarter">
|
||||
<div class="card is-stretchable">
|
||||
<header class="card-header">
|
||||
|
@ -31,5 +32,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<span class="icon icon-comment"></span>
|
||||
{% elif notification.notification_type == 'REPLY' %}
|
||||
<span class="icon icon-comments"></span>
|
||||
{% 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' %}
|
||||
<span class="icon icon-local"></span>
|
||||
{% elif notification.notification_type == 'BOOST' %}
|
||||
<span class="icon icon-boost"></span>
|
||||
|
@ -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 <em><a href="{{ book_path }}">{{ book_title }}</a></em> to your list "<a href="{{ list_path }}/curate">{{ list_name }}</a>"{% 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 <a href="{{ group_path }}">{{ group_name }}</a> {% endblocktrans %}
|
||||
<div class="row shrink">
|
||||
{% include 'snippets/join_invitation_buttons.html' with group=notification.related_group %}
|
||||
</div>
|
||||
{% 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 "<a href="{{ group_path }}">{{ group_name }}</a>"{% endblocktrans %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% elif notification.related_import %}
|
||||
{% url 'import-status' notification.related_import.id as url %}
|
||||
|
|
|
@ -24,22 +24,22 @@
|
|||
<span><em>Remote User</em></span>
|
||||
{% endif %}
|
||||
</form>
|
||||
<form action="{% url 'uninvite-group-member' %}" method="POST" class="interaction add_{{ user.id }} {% if not group|is_member:user or not group|is_invited:user %}is-hidden{% endif %}" data-id="add_{{ user.id }}">
|
||||
<form action="{% url 'remove-group-member' %}" method="POST" class="interaction add_{{ user.id }} {% if not group|is_member:user and not group|is_invited:user %}is-hidden{% endif %}" data-id="add_{{ user.id }}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="group" value="{{ group.id }}">
|
||||
<input type="hidden" name="user" value="{{ user.username }}">
|
||||
{% if group|is_invited:user %}
|
||||
{% if not group|is_member:user %}
|
||||
<button class="button is-small is-danger is-light" type="submit">
|
||||
{% trans "Undo Invitation" %}
|
||||
</button>
|
||||
{% else %}
|
||||
<button class="button is-small is-danger is-light" type="submit">
|
||||
{% if show_username %}
|
||||
{% blocktrans with username=user.localname %}Remove @{{ username }}{% endblocktrans %}
|
||||
{% else %}
|
||||
{% trans "Remove" %}
|
||||
{% endif %}
|
||||
</button>
|
||||
{% if show_username %}
|
||||
{% blocktrans with username=user.localname %}Remove @{{ username }}{% endblocktrans %}
|
||||
{% else %}
|
||||
{% trans "Remove" %}
|
||||
{% endif %}
|
||||
</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
|
|
16
bookwyrm/templates/snippets/join_invitation_buttons.html
Normal file
16
bookwyrm/templates/snippets/join_invitation_buttons.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% load i18n %}
|
||||
{% load bookwyrm_group_tags %}
|
||||
{% if group|is_invited:request.user %}
|
||||
<div class="field is-grouped">
|
||||
<form action="/accept-group-invitation/" method="POST">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="group" value="{{ group.id }}">
|
||||
<button class="button is-link is-small" type="submit">{% trans "Accept" %}</button>
|
||||
</form>
|
||||
<form action="/reject-group-invitation/" method="POST">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="group" value="{{ group.id }}">
|
||||
<button class="button is-danger is-light is-small" type="submit" class="warning">{% trans "Delete" %}</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
{% block panel %}
|
||||
<section class="block">
|
||||
<form name="create-group" method="post" action="{% url 'user-groups' request.user.name %}" class="box is-hidden" id="create_group">
|
||||
<form name="create-group" method="post" action="{% url 'user-groups' request.user.username %}" class="box is-hidden" id="create_group">
|
||||
<header class="columns">
|
||||
<h3 class="title column">{% trans "Create group" %}</h3>
|
||||
<div class="column is-narrow">
|
||||
|
@ -34,9 +34,9 @@
|
|||
{% include 'groups/form.html' %}
|
||||
</form>
|
||||
|
||||
{% include 'groups/user_groups.html' %}
|
||||
{% include 'groups/user_groups.html' with memberships=memberships %}
|
||||
</section>
|
||||
<div>
|
||||
{% include 'snippets/pagination.html' with page=user_groups path=path %}
|
||||
{% include 'snippets/pagination.html' with page=user.memberships path=path %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
{% load utilities %}
|
||||
{% load markdown %}
|
||||
{% load layout %}
|
||||
{% load bookwyrm_group_tags %}
|
||||
|
||||
{% block title %}{{ user.display_name }}{% endblock %}
|
||||
|
||||
|
@ -75,7 +76,7 @@
|
|||
<a href="{{ url }}">{% trans "Lists" %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if is_self or user.bookwyrm_groups %}
|
||||
{% if is_self or user|has_groups %}
|
||||
{% url 'user-groups' user|username as url %}
|
||||
<li{% if url in request.path %} class="is-active"{% endif %}>
|
||||
<a href="{{ url }}">{% trans "Groups" %}</a>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue