diff --git a/bookwyrm/migrations/0112_auto_20211022_0844.py b/bookwyrm/migrations/0112_auto_20211022_0844.py new file mode 100644 index 000000000..246480b3a --- /dev/null +++ b/bookwyrm/migrations/0112_auto_20211022_0844.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.5 on 2021-10-22 08:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0111_merge_0107_auto_20211016_0639_0110_auto_20211015_1734"), + ] + + operations = [ + migrations.RemoveConstraint( + model_name="notification", + name="notification_type_valid", + ), + migrations.AlterField( + model_name="notification", + name="notification_type", + field=models.CharField( + choices=[ + ("FAVORITE", "Favorite"), + ("REPLY", "Reply"), + ("MENTION", "Mention"), + ("TAG", "Tag"), + ("FOLLOW", "Follow"), + ("FOLLOW_REQUEST", "Follow Request"), + ("BOOST", "Boost"), + ("IMPORT", "Import"), + ("ADD", "Add"), + ("REPORT", "Report"), + ("INVITE", "Invite"), + ("ACCEPT", "Accept"), + ("JOIN", "Join"), + ("LEAVE", "Leave"), + ("REMOVE", "Remove"), + ("GROUP_PRIVACY", "Group Privacy"), + ("GROUP_NAME", "Group Name"), + ("GROUP_DESCRIPTION", "Group Description"), + ], + max_length=255, + ), + ), + migrations.AlterField( + model_name="user", + name="preferred_language", + field=models.CharField( + blank=True, + choices=[ + ("en-us", "English"), + ("de-de", "Deutsch (German)"), + ("es-es", "Español (Spanish)"), + ("fr-fr", "Français (French)"), + ("pt-br", "Português - Brasil (Brazilian Portuguese)"), + ("zh-hans", "简体中文 (Simplified Chinese)"), + ("zh-hant", "繁體中文 (Traditional Chinese)"), + ], + max_length=255, + null=True, + ), + ), + migrations.AddConstraint( + model_name="notification", + constraint=models.CheckConstraint( + check=models.Q( + ( + "notification_type__in", + [ + "FAVORITE", + "REPLY", + "MENTION", + "TAG", + "FOLLOW", + "FOLLOW_REQUEST", + "BOOST", + "IMPORT", + "ADD", + "REPORT", + "INVITE", + "ACCEPT", + "JOIN", + "LEAVE", + "REMOVE", + "GROUP_PRIVACY", + "GROUP_NAME", + "GROUP_DESCRIPTION", + ], + ) + ), + name="notification_type_valid", + ), + ), + ] diff --git a/bookwyrm/models/group.py b/bookwyrm/models/group.py index 552e2c287..bd5b8d410 100644 --- a/bookwyrm/models/group.py +++ b/bookwyrm/models/group.py @@ -23,7 +23,7 @@ class Group(BookWyrmModel): @classmethod def followers_filter(cls, queryset, viewer): """Override filter for "followers" privacy level to allow non-following - group members to see the existence of groups and group lists""" + group members to see the existence of group-curated lists""" return queryset.exclude( ~Q( # user is not a group member diff --git a/bookwyrm/models/notification.py b/bookwyrm/models/notification.py index b15b95c2c..2f1aae4f3 100644 --- a/bookwyrm/models/notification.py +++ b/bookwyrm/models/notification.py @@ -7,7 +7,7 @@ from . import Boost, Favorite, ImportJob, Report, Status, User # pylint: disable=line-too-long NotificationType = models.TextChoices( "NotificationType", - "FAVORITE REPLY MENTION TAG FOLLOW FOLLOW_REQUEST BOOST IMPORT ADD REPORT INVITE ACCEPT JOIN LEAVE REMOVE", + "FAVORITE REPLY MENTION TAG FOLLOW FOLLOW_REQUEST BOOST IMPORT ADD REPORT INVITE ACCEPT JOIN LEAVE REMOVE GROUP_PRIVACY GROUP_NAME GROUP_DESCRIPTION", ) diff --git a/bookwyrm/templates/groups/form.html b/bookwyrm/templates/groups/form.html index c1281172b..21c525ee0 100644 --- a/bookwyrm/templates/groups/form.html +++ b/bookwyrm/templates/groups/form.html @@ -4,7 +4,6 @@
-
{{ group_form.name }} @@ -19,7 +18,7 @@
- {% include 'snippets/privacy_select.html' with current=group.privacy %} + {% include 'snippets/privacy_select_no_followers.html' with current=group.privacy %}
diff --git a/bookwyrm/templates/notifications/item.html b/bookwyrm/templates/notifications/item.html index 3ed43a96a..e8e2dcb26 100644 --- a/bookwyrm/templates/notifications/item.html +++ b/bookwyrm/templates/notifications/item.html @@ -27,4 +27,10 @@ {% include 'notifications/items/leave.html' %} {% elif notification.notification_type == 'REMOVE' %} {% include 'notifications/items/remove.html' %} +{% elif notification.notification_type == 'GROUP_PRIVACY' %} + {% include 'notifications/items/update.html' %} +{% elif notification.notification_type == 'GROUP_NAME' %} + {% include 'notifications/items/update.html' %} +{% elif notification.notification_type == 'GROUP_DESCRIPTION' %} + {% include 'notifications/items/update.html' %} {% endif %} diff --git a/bookwyrm/templates/notifications/items/join.html b/bookwyrm/templates/notifications/items/join.html index 9c766806f..93b356424 100644 --- a/bookwyrm/templates/notifications/items/join.html +++ b/bookwyrm/templates/notifications/items/join.html @@ -18,6 +18,3 @@ has joined your group "{{ group_name }}" {% endblocktrans %} {% endblock %} - - - diff --git a/bookwyrm/templates/notifications/items/update.html b/bookwyrm/templates/notifications/items/update.html new file mode 100644 index 000000000..f963fd3a9 --- /dev/null +++ b/bookwyrm/templates/notifications/items/update.html @@ -0,0 +1,28 @@ +{% extends 'notifications/items/item_layout.html' %} + +{% load i18n %} +{% load utilities %} + +{% block primary_link %}{% spaceless %} + {{ notification.related_group.local_path }} +{% endspaceless %}{% endblock %} + +{% block icon %} + +{% endblock %} + +{% block description %} + {% if notification.notification_type == 'GROUP_PRIVACY' %} + {% blocktrans with group_name=notification.related_group.name group_path=notification.related_group.local_path %} + has changed the privacy level for {{ group_name }} + {% endblocktrans %} + {% elif notification.notification_type == 'GROUP_NAME' %} + {% blocktrans with group_name=notification.related_group.name group_path=notification.related_group.local_path %} + has changed the name of {{ group_name }} + {% endblocktrans %} + {% else %} + {% blocktrans with group_name=notification.related_group.name group_path=notification.related_group.local_path %} + has changed the description of {{ group_name }} + {% endblocktrans %} + {% endif %} +{% endblock %} diff --git a/bookwyrm/templates/snippets/privacy_select_no_followers.html b/bookwyrm/templates/snippets/privacy_select_no_followers.html new file mode 100644 index 000000000..2c601e7ff --- /dev/null +++ b/bookwyrm/templates/snippets/privacy_select_no_followers.html @@ -0,0 +1,21 @@ +{% load i18n %} +{% load utilities %} +
+ {% firstof privacy_uuid 0|uuid as uuid %} + {% if not no_label %} + + {% endif %} + {% firstof current user.default_post_privacy "public" as privacy %} + +
+ diff --git a/bookwyrm/tests/models/test_group.py b/bookwyrm/tests/models/test_group.py index 275fce196..33341d192 100644 --- a/bookwyrm/tests/models/test_group.py +++ b/bookwyrm/tests/models/test_group.py @@ -75,15 +75,6 @@ class Group(TestCase): ) models.GroupMember.objects.create(group=self.public_group, user=self.capybara) - def test_group_members_can_see_followers_only_groups(self, _): - """follower-only group should not be excluded from group listings for group members viewing""" - - rat_groups = models.Group.privacy_filter(self.rat).all() - badger_groups = models.Group.privacy_filter(self.badger).all() - - self.assertFalse(self.followers_only_group in rat_groups) - self.assertTrue(self.followers_only_group in badger_groups) - def test_group_members_can_see_private_groups(self, _): """direct privacy group should not be excluded from group listings for group members viewing""" diff --git a/bookwyrm/views/group.py b/bookwyrm/views/group.py index 1c0a28486..9ee99bffa 100644 --- a/bookwyrm/views/group.py +++ b/bookwyrm/views/group.py @@ -47,6 +47,31 @@ class Group(View): if not form.is_valid(): return redirect("group", user_group.id) user_group = form.save() + + # let the other members know something about the group changed + memberships = models.GroupMember.objects.filter(group=user_group) + model = apps.get_model("bookwyrm.Notification", require_ready=True) + for field in form.changed_data: + notification_type = ( + "GROUP_PRIVACY" + if field == "privacy" + else "GROUP_NAME" + if field == "name" + else "GROUP_DESCRIPTION" + if field == "description" + else None + ) + if notification_type: + for membership in memberships: + member = membership.user + if member != request.user: + model.objects.create( + user=member, + related_user=request.user, + related_group=user_group, + notification_type=notification_type, + ) + return redirect("group", user_group.id)