diff --git a/zubhub_backend/compose/web/dev/start b/zubhub_backend/compose/web/dev/start index 6057ab88e..cde5bcd3d 100644 --- a/zubhub_backend/compose/web/dev/start +++ b/zubhub_backend/compose/web/dev/start @@ -18,7 +18,6 @@ python /zubhub_backend/zubhub/manage.py createcachetable python /zubhub_backend/zubhub/manage.py populate_countries python /zubhub_backend/zubhub/manage.py populate_categories -python /zubhub_backend/zubhub/manage.py populate_violation_reasons python /zubhub_backend/zubhub/manage.py populate_initial_creator_tags exec /usr/local/bin/gunicorn zubhub.wsgi --reload --threads=3 --timeout 155 --bind 0.0.0.0:8000 \ diff --git a/zubhub_backend/zubhub/creators/migrations/0009_alter_setting_contact.py b/zubhub_backend/zubhub/creators/migrations/0009_alter_setting_contact.py deleted file mode 100644 index 0b69d79fb..000000000 --- a/zubhub_backend/zubhub/creators/migrations/0009_alter_setting_contact.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2 on 2022-04-30 01:48 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('creators', '0008_auto_20220222_0254'), - ] - - operations = [ - migrations.AlterField( - model_name='setting', - name='contact', - field=models.PositiveSmallIntegerField(blank=True, choices=[(1, 'WHATSAPP'), (2, 'EMAIL'), (3, 'SMS'), (4, 'WEB')], default=3, null=True), - ), - ] diff --git a/zubhub_backend/zubhub/creators/utils.py b/zubhub_backend/zubhub/creators/utils.py index e85bb38f4..b551cf612 100644 --- a/zubhub_backend/zubhub/creators/utils.py +++ b/zubhub_backend/zubhub/creators/utils.py @@ -241,7 +241,6 @@ def activity_notification(activities, **kwargs): if len(phone_contexts) > 0 and ctx_values: send_mass_text.delay(template_name=template_name, ctxs=phone_contexts) - def perform_creator_search(user, query_string): from creators.models import CreatorTag """ @@ -255,28 +254,28 @@ def perform_creator_search(user, query_string): rank = SearchRank(F('search_vector'), query) result_creators = None + # fetch all creators whose creatortag(s) matches the search query result_tags = CreatorTag.objects.filter( search_vector=query).prefetch_related("creators") for tag in result_tags: - result_creators = tag.creators.filter(is_active=True).annotate( - rank=rank).order_by('-rank') + result_creators = tag.creators.filter(is_active=True).annotate(rank=rank).order_by('-rank') ############################################################ # fetch all creators that matches the search term if result_creators: - result_creators.union(get_user_model().objects.annotate( - rank=rank).filter(search_vector=query, - is_active=True).order_by('-rank')) + result_creators.union(get_user_model().objects.annotate(rank=rank).filter( + search_vector=query, is_active=True ).order_by('-rank')) else: result_creators = get_user_model().objects.annotate(rank=rank).filter( - search_vector=query, is_active=True).order_by('-rank') + search_vector=query,is_active=True ).order_by('-rank') ############################################################## return result_creators + def custom_set_creatortags_queryset(creator, creatortags): """ Handle the process of assigning a queryset of creatortags to creator.tags @@ -299,26 +298,22 @@ def custom_set_creatortags_queryset(creator, creatortags): tag = CreatorTag.objects.filter(name="staff").first() if creatortags.filter(name=tag.name).exists(): - creator.tags.set( - enforce_creator__creator_tags_constraints(creator, tag)) + creator.tags.set(enforce_creator__creator_tags_constraints(creator, tag)) creatortags = creatortags.exclude(name=tag.name) tag = CreatorTag.objects.filter(name="moderator").first() if creatortags.filter(name=tag.name).exists(): - creator.tags.set( - enforce_creator__creator_tags_constraints(creator, tag)) + creator.tags.set(enforce_creator__creator_tags_constraints(creator, tag)) creatortags = creatortags.exclude(name=tag.name) tag = CreatorTag.objects.filter(name="group").first() if creatortags.filter(name=tag.name).exists(): - creator.tags.set( - enforce_creator__creator_tags_constraints(creator, tag)) + creator.tags.set(enforce_creator__creator_tags_constraints(creator, tag)) creatortags = creatortags.exclude(name=tag.name) tag = CreatorTag.objects.filter(name="creator").first() if creatortags.filter(name=tag.name).exists(): - creator.tags.set( - enforce_creator__creator_tags_constraints(creator, tag)) + creator.tags.set(enforce_creator__creator_tags_constraints(creator, tag)) creatortags = creatortags.exclude(name=tag.name) @@ -341,29 +336,25 @@ def enforce_creator__creator_tags_constraints(creator, tag): if tag.name == "creator": """ If tag is 'creator', ensure that 'staff', 'moderator' and 'group' tags are not in the user's tags list """ - diff = CreatorTag.objects.filter( - name__in=["creator", "staff", "group", "moderator"]) + diff = CreatorTag.objects.filter(name__in=["creator", "staff", "group", "moderator"]) tags_to_set = creator.tags.difference(diff) return tags_to_set.union(diff.filter(name=tag.name)) - + elif tag.name == "staff": """ If tag is 'staff', ensure that 'creator' and 'group' tags are not in the user's tags list """ - diff = CreatorTag.objects.filter( - name__in=["creator", "staff", "group"]) + diff = CreatorTag.objects.filter(name__in=["creator", "staff", "group"]) tags_to_set = creator.tags.difference(diff) return tags_to_set.union(diff.filter(name=tag.name)) elif tag.name == "moderator": """ If tag is 'moderator', ensure that 'creator' and 'group' tags are not in the user's tags list """ - diff = CreatorTag.objects.filter( - name__in=["creator", "group", "moderator"]) + diff = CreatorTag.objects.filter(name__in=["creator", "group", "moderator"]) tags_to_set = creator.tags.difference(diff) return tags_to_set.union(diff.filter(name=tag.name)) elif tag.name == "group": """ If tag is 'group', ensure that 'staff', 'creator' and 'moderator' tags are not in the user's tags list """ - diff = CreatorTag.objects.filter( - name__in=["creator", "staff", "group", "moderator"]) + diff = CreatorTag.objects.filter(name__in=["creator", "staff", "group", "moderator"]) tags_to_set = creator.tags.difference(diff) return tags_to_set.union(diff.filter(name=tag.name)) @@ -377,14 +368,16 @@ def enforce_creator__creator_tags_constraints(creator, tag): return creator.tags.all() -ALL_SETTINGS = {Setting.WHATSAPP, Setting.EMAIL, Setting.SMS, Setting.WEB} + enabled_notification_settings: Dict[Notification.Type, Set[int]] = { Notification.Type.BOOKMARK: {Setting.WEB}, Notification.Type.CLAP: {Setting.WEB}, - Notification.Type.COMMENT: ALL_SETTINGS, - Notification.Type.FOLLOW: ALL_SETTINGS, - Notification.Type.FOLLOWING_PROJECT: ALL_SETTINGS, - Notification.Type.PROJECT_VIOLATION: ALL_SETTINGS + Notification.Type.COMMENT: + {Setting.WHATSAPP, Setting.EMAIL, Setting.SMS, Setting.WEB}, + Notification.Type.FOLLOW: + {Setting.WHATSAPP, Setting.EMAIL, Setting.SMS, Setting.WEB}, + Notification.Type.FOLLOWING_PROJECT: + {Setting.WHATSAPP, Setting.EMAIL, Setting.SMS, Setting.WEB}, } diff --git a/zubhub_backend/zubhub/notifications/migrations/0010_alter_notification_type.py b/zubhub_backend/zubhub/notifications/migrations/0010_alter_notification_type.py deleted file mode 100644 index fa207b9d4..000000000 --- a/zubhub_backend/zubhub/notifications/migrations/0010_alter_notification_type.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2 on 2022-04-30 01:48 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('notifications', '0009_alter_notification_sources'), - ] - - operations = [ - migrations.AlterField( - model_name='notification', - name='type', - field=models.PositiveSmallIntegerField(choices=[(1, 'Bookmark'), (2, 'Clap'), (3, 'Comment'), (4, 'Follow'), (5, 'Following Project'), (6, 'Project Violation')]), - ), - ] diff --git a/zubhub_backend/zubhub/notifications/models.py b/zubhub_backend/zubhub/notifications/models.py index abf8b5444..adc11e4fb 100644 --- a/zubhub_backend/zubhub/notifications/models.py +++ b/zubhub_backend/zubhub/notifications/models.py @@ -6,28 +6,21 @@ class Notification(models.Model): - class Type(models.IntegerChoices): BOOKMARK = 1 CLAP = 2 COMMENT = 3 FOLLOW = 4 FOLLOWING_PROJECT = 5 - PROJECT_VIOLATION = 6 - id = models.UUIDField(primary_key=True, - default=uuid.uuid4, - editable=False, - unique=True) - type = models.PositiveSmallIntegerField(choices=Type.choices, ) - recipient = models.ForeignKey(Creator, - on_delete=models.CASCADE, - null=True, - related_name="notification_recipient", - blank=True) - sources = models.ManyToManyField(Creator, - related_name='notification_source', - blank=True) + id = models.UUIDField( + primary_key=True, default=uuid.uuid4, editable=False, unique=True) + type = models.PositiveSmallIntegerField( + choices=Type.choices, + ) + recipient = models.ForeignKey( + Creator, on_delete=models.CASCADE, null=True, related_name="notification_recipient", blank=True) + sources = models.ManyToManyField(Creator, related_name='notification_source', blank=True) message = models.CharField(max_length=255, blank=True, null=True) link = models.CharField(max_length=1000, blank=True, null=True) viewed = models.BooleanField(default=False) diff --git a/zubhub_backend/zubhub/projects/admin.py b/zubhub_backend/zubhub/projects/admin.py index ac6e096cc..476db876a 100644 --- a/zubhub_backend/zubhub/projects/admin.py +++ b/zubhub_backend/zubhub/projects/admin.py @@ -2,8 +2,8 @@ from treebeard.admin import TreeAdmin from treebeard.forms import movenodeform_factory from django.conf import settings -from .models import (Project, Comment, Image, StaffPick, Category, Tag, - PublishingRule, Violation, ViolationReason) +from .models import (Project, Comment, Image, StaffPick, + Category, Tag, PublishingRule) from .utils import project_changed, send_staff_pick_notification from projects.tasks import delete_file_task from creators.utils import activity_notification @@ -24,22 +24,20 @@ class InlineProjectComments(admin.StackedInline): class InlineProject(admin.StackedInline): model = Project.staff_picks.through - class ImageAdmin(admin.ModelAdmin): search_fields = ["project__title", "image_url"] list_display = ["image_url"] exclude = ["id"] - list_per_page = 50 ## paginate when more than 50 items - + list_per_page = 50 ## paginate when more than 50 items + class CommentAdmin(TreeAdmin): list_display = ["creator", "text", "created_on", "publish"] - - search_fields = [ - "project__tite", "creator__username", "text", "created_on" - ] + + search_fields = ["project__tite", + "creator__username", "text", "created_on"] list_filter = ["created_on"] - list_per_page = 50 ## paginate when more than 50 items + list_per_page = 50 ## paginate when more than 50 items form = movenodeform_factory(Comment) @@ -53,24 +51,18 @@ def get_readonly_fields(self, request, obj=None): class ProjectAdmin(admin.ModelAdmin): - list_display = [ - "title", "creator", "views_count", "likes_count", "comments_count", - "created_on", "publish" - ] - - search_fields = [ - "title", 'creator__username', 'creator__email', "created_on" - ] + list_display = ["title", "creator", "views_count", "likes_count", + "comments_count", "created_on", "publish"] + + search_fields = ["title", 'creator__username', 'creator__email', + "created_on"] list_filter = ['created_on'] inlines = [InlineProjectImages, InlineProjectComments] exclude = ["search_vector"] - list_per_page = 50 ## paginate when more than 50 items + list_per_page = 50 ## paginate when more than 50 items def get_readonly_fields(self, request, obj=None): - return [ - "id", "slug", "views_count", "likes_count", "comments_count", - "created_on" - ] + return ["id", "slug", "views_count", "likes_count", "comments_count", "created_on"] def save_model(self, request, obj, form, change): if change: @@ -80,12 +72,10 @@ def save_model(self, request, obj, form, change): if change: new = Project.objects.get(pk=obj.pk) - if old.video.find( - "cloudinary.com") > -1 and old.video != new.video: + if old.video.find("cloudinary.com") > -1 and old.video != new.video: delete_file_task.delay(old.video) - elif old.video.startswith("{0}://{1}".format( - settings.DEFAULT_MEDIA_SERVER_PROTOCOL, settings. - DEFAULT_MEDIA_SERVER_DOMAIN)) and old.video != new.video: + elif old.video.startswith("{0}://{1}".format(settings.DEFAULT_MEDIA_SERVER_PROTOCOL, + settings.DEFAULT_MEDIA_SERVER_DOMAIN)) and old.video != new.video: delete_file_task.delay(old.video) if project_changed(old, new): info = { @@ -95,6 +85,8 @@ def save_model(self, request, obj, form, change): activity_notification(["edited_project"], **info) + + def projects_count(obj): if obj: return obj.projects.count() @@ -144,19 +136,7 @@ class tagAdmin(admin.ModelAdmin): search_fields = ["name"] readonly_fields = ["slug"] exclude = ["id", "search_vector"] - list_per_page = 50 ## paginate when more than 50 items - - -class ViolationReasonsAdmin(admin.ModelAdmin): - search_fields = ['description'] - exclude = ["id"] - list_per_page = 50 - - -class ViolationAdmin(admin.ModelAdmin): - search_fields = ["name"] - exclude = ["id"] - list_per_page = 50 + list_per_page = 50 ## paginate when more than 50 items admin.site.register(Project, ProjectAdmin) @@ -165,5 +145,3 @@ class ViolationAdmin(admin.ModelAdmin): admin.site.register(Category, categoryAdmin) admin.site.register(Tag, tagAdmin) admin.site.register(StaffPick, StaffPickAdmin) -admin.site.register(ViolationReason, ViolationReasonsAdmin) -admin.site.register(Violation, ViolationAdmin) diff --git a/zubhub_backend/zubhub/projects/management/commands/populate_violation_reasons.py b/zubhub_backend/zubhub/projects/management/commands/populate_violation_reasons.py deleted file mode 100644 index 735d6df38..000000000 --- a/zubhub_backend/zubhub/projects/management/commands/populate_violation_reasons.py +++ /dev/null @@ -1,25 +0,0 @@ -from projects.models import ViolationReason -from django.core.management.base import BaseCommand - - -class Command(BaseCommand): - help = 'Populate ViolationReason table with violation reasons' - - def handle(self, *args, **kwargs): - if ViolationReason.objects.all().count() < 1: - with open( - "./zubhub/projects/management/commands/violation_reasons.txt", - "r") as violation_reasons: - violation_reasons = violation_reasons.readlines() - for violation_reason in violation_reasons: - self.stdout.write(violation_reason) - ViolationReason.objects.create( - description=violation_reason.split("\n")[0]) - self.stdout.write( - self.style.SUCCESS( - 'The ViolationReason table has been successfully populated!' - )) - else: - self.stdout.write( - self.style.NOTICE( - 'The ViolationReason table is already populated')) diff --git a/zubhub_backend/zubhub/projects/management/commands/violation_reasons.txt b/zubhub_backend/zubhub/projects/management/commands/violation_reasons.txt deleted file mode 100644 index 9c5ab8d47..000000000 --- a/zubhub_backend/zubhub/projects/management/commands/violation_reasons.txt +++ /dev/null @@ -1,7 +0,0 @@ -Promotes bigotry, discrimination, hatred, or violence against any individual or group; -Threatens, harasses, or intimidates any other person, whether that person is a ZubHub user or not; -Contains foul language or personal attacks; -Contains sexually explicit or graphically violent material; -Provides instructions on how to commit illegal activities or obtain illegal products; -Asks any other user for personally identifying information, contact information, or passwords; or -Exposes any others person's personally identifying information, contact information, or passwords without that person's permission. diff --git a/zubhub_backend/zubhub/projects/migrations/0007_auto_20220423_0217.py b/zubhub_backend/zubhub/projects/migrations/0007_auto_20220423_0217.py deleted file mode 100644 index d3abb3f59..000000000 --- a/zubhub_backend/zubhub/projects/migrations/0007_auto_20220423_0217.py +++ /dev/null @@ -1,52 +0,0 @@ -# Generated by Django 3.2 on 2022-04-23 02:17 - -from django.conf import settings -import django.contrib.postgres.indexes -from django.db import migrations, models -import django.db.models.deletion -import django.utils.timezone -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('projects', '0006_auto_20220409_1917'), - ] - - operations = [ - migrations.CreateModel( - name='Violation', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), - ('date', models.DateTimeField(default=django.utils.timezone.now)), - ], - ), - migrations.CreateModel( - name='ViolationReason', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), - ('description', models.CharField(max_length=250)), - ], - ), - migrations.AddIndex( - model_name='tag', - index=django.contrib.postgres.indexes.GinIndex(fields=['name'], name='tag_name_gin_idx', opclasses=['gin_trgm_ops']), - ), - migrations.AddField( - model_name='violation', - name='creator', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), - ), - migrations.AddField( - model_name='violation', - name='project', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='violations', to='projects.project'), - ), - migrations.AddField( - model_name='violation', - name='reasons', - field=models.ManyToManyField(blank=True, null=True, related_name='violations', to='projects.ViolationReason'), - ), - ] diff --git a/zubhub_backend/zubhub/projects/migrations/0008_alter_violation_reasons.py b/zubhub_backend/zubhub/projects/migrations/0008_alter_violation_reasons.py deleted file mode 100644 index 13b70da00..000000000 --- a/zubhub_backend/zubhub/projects/migrations/0008_alter_violation_reasons.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2 on 2022-04-23 02:18 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('projects', '0007_auto_20220423_0217'), - ] - - operations = [ - migrations.AlterField( - model_name='violation', - name='reasons', - field=models.ManyToManyField(blank=True, related_name='violations', to='projects.ViolationReason'), - ), - ] diff --git a/zubhub_backend/zubhub/projects/models.py b/zubhub_backend/zubhub/projects/models.py index 598f32ade..588ed561f 100644 --- a/zubhub_backend/zubhub/projects/models.py +++ b/zubhub_backend/zubhub/projects/models.py @@ -249,31 +249,3 @@ def save(self, *args, **kwargs): uid = uid[0:floor(len(uid) / 6)] self.slug = slugify(self.title) + "-" + uid super().save(*args, **kwargs) - - -class ViolationReason(models.Model): - id = models.UUIDField(primary_key=True, - default=uuid.uuid4, - editable=False, - unique=True) - description = models.CharField(max_length=250) - - -class Violation(models.Model): - id = models.UUIDField(primary_key=True, - default=uuid.uuid4, - editable=False, - unique=True) - reasons = models.ManyToManyField(ViolationReason, - blank=True, - related_name='violations') - project = models.ForeignKey(Project, - null=True, - blank=True, - on_delete=models.CASCADE, - related_name='violations') - creator = models.ForeignKey(Creator, - null=True, - blank=True, - on_delete=models.SET_NULL) - date = models.DateTimeField(default=timezone.now) diff --git a/zubhub_backend/zubhub/projects/serializers.py b/zubhub_backend/zubhub/projects/serializers.py index 1c23d820c..996dd7fe0 100644 --- a/zubhub_backend/zubhub/projects/serializers.py +++ b/zubhub_backend/zubhub/projects/serializers.py @@ -5,56 +5,25 @@ from django.conf import settings from django.db import transaction from creators.serializers import CreatorMinimalSerializer -from .models import Project, Comment, Image, StaffPick, Category, Tag, PublishingRule, Violation, ViolationReason +from .models import Project, Comment, Image, StaffPick, Category, Tag, PublishingRule from projects.tasks import filter_spam_task from .pagination import ProjectNumberPagination from .utils import update_images, update_tags, parse_comment_trees, get_published_projects_for_user from .tasks import update_video_url_if_transform_ready, delete_file_task from math import ceil -Creator = get_user_model() - - -class ViolationReasonSerializer(serializers.ModelSerializer): - id = serializers.UUIDField() - description = serializers.CharField(read_only=True) - - class Meta: - model = ViolationReason - fields = ['id', 'description'] - - -class ViolationSerializer(serializers.ModelSerializer): - id = serializers.UUIDField(read_only=True) - reasons = ViolationReasonSerializer(many=True) - date = serializers.DateTimeField(read_only=True) - - class Meta: - model = Violation - fields = ['id', 'reasons', 'creator', 'date', 'project'] - def create(self, validated_data): - with transaction.atomic(): - violation = Violation(creator=validated_data['creator'], - project=validated_data['project']) - reasons_data = validated_data.pop('reasons') - reasons = [ - ViolationReason.objects.get(**reason_data) - for reason_data in reasons_data - ] - violation.reasons.set(reasons) - violation.save() - - return violation +Creator = get_user_model() class PublishingRuleSerializer(serializers.ModelSerializer): visible_to = CreatorMinimalSerializer(read_only=True, many=True) - class Meta: model = PublishingRule - fields = ["type", "visible_to"] - + fields = [ + "type", + "visible_to" + ] class CommentSerializer(serializers.ModelSerializer): id = serializers.UUIDField(read_only=True) @@ -81,55 +50,59 @@ def save(self, **kwargs): class Meta: model = Comment - fields = ["id", "creator", "text", "created_on", "publish"] + fields = [ + "id", + "creator", + "text", + "created_on", + "publish" + ] def get_creator(self, obj): - return { - "id": str(obj.creator.id), - "username": obj.creator.username, - "avatar": obj.creator.avatar - } + return {"id": str(obj.creator.id), "username": obj.creator.username, "avatar": obj.creator.avatar} class ImageSerializer(serializers.ModelSerializer): class Meta: model = Image - fields = ["image_url", "public_id"] + fields = [ + "image_url", + "public_id" + ] class TagSerializer(serializers.ModelSerializer): class Meta: model = Tag - fields = ["name"] - + fields = [ + "name" + ] class CategorySerializer(serializers.ModelSerializer): - class Meta: model = Category - fields = ["id", "name"] + fields = [ + "id", + "name" + ] class ProjectSerializer(serializers.ModelSerializer): creator = CreatorMinimalSerializer(read_only=True) - likes = serializers.SlugRelatedField(many=True, - slug_field='id', - read_only=True) - saved_by = serializers.SlugRelatedField(many=True, - slug_field='id', - read_only=True) + likes = serializers.SlugRelatedField( + many=True, slug_field='id', read_only=True) + saved_by = serializers.SlugRelatedField( + many=True, slug_field='id', read_only=True) comments = serializers.SerializerMethodField('get_comments') images = ImageSerializer(many=True, required=False) tags = TagSerializer(many=True, required=False, read_only=True) - category = serializers.SlugRelatedField(slug_field="name", - queryset=Category.objects.all(), - required=False) + category = serializers.SlugRelatedField( + slug_field="name", queryset=Category.objects.all(), required=False) created_on = serializers.DateTimeField(read_only=True) views_count = serializers.IntegerField(read_only=True) - publish = PublishingRuleSerializer(read_only=True) - violations = ViolationSerializer(many=True, required=False, read_only=True) + publish = PublishingRuleSerializer(read_only=True) class Meta: model = Project @@ -148,8 +121,7 @@ class Meta: "views_count", "comments", "created_on", - "publish", - 'violations', + "publish" ] read_only_fields = ["created_on", "views_count"] @@ -175,40 +147,42 @@ def get_comments(self, obj): return parse_comment_trees(user, root_comments, creators_dict) def validate_video(self, video): - if (video == "" and len(self.initial_data.get("images")) == 0): + if(video == "" and len(self.initial_data.get("images")) == 0): raise serializers.ValidationError( - _("You must provide either image(s), video file, or video URL to create your project!" - )) + _("You must provide either image(s), video file, or video URL to create your project!")) return video def validate_images(self, images): - if (len(images) == 0 and len(self.initial_data["video"]) == 0): + if(len(images) == 0 and len(self.initial_data["video"]) == 0): raise serializers.ValidationError( - _("You must provide either image(s), video file, or video URL to create your project!" - )) + _("You must provide either image(s), video file, or video URL to create your project!")) return images def validate_tags(self, tags): if not isinstance(tags, list): - raise serializers.ValidationError(_("tags format not supported")) + raise serializers.ValidationError( + _("tags format not supported") + ) try: if len(tags) > 0: # attempt parsing tags list(map(lambda x: x["name"], tags)) except: - raise serializers.ValidationError(_("tags format not supported")) + raise serializers.ValidationError( + _("tags format not supported") + ) for tag in tags: - if (not re.fullmatch("[0-9A-Za-z\s\-]+", - tag["name"])) or (tag["name"] == " "): + if (not re.fullmatch("[0-9A-Za-z\s\-]+", tag["name"])) or (tag["name"] == " "): raise serializers.ValidationError( _("tags support only letters, numbers, spaces, and dashes") ) if len(tags) > 5: raise serializers.ValidationError( - _("tags must not be more than 5")) + _("tags must not be more than 5") + ) return tags def validate_publish(self, publish): @@ -216,50 +190,47 @@ def validate_publish(self, publish): try: if publish["type"] not in [ - PublishingRule.DRAFT, PublishingRule.PUBLIC, - PublishingRule.AUTHENTICATED_VIEWERS, - PublishingRule.PREVIEW - ]: + PublishingRule.DRAFT, PublishingRule.PUBLIC, + PublishingRule.AUTHENTICATED_VIEWERS, PublishingRule.PREVIEW]: raise serializers.ValidationError( - _("publish type is not supported. must be one of 1,2,3 or 4" - )) + _("publish type is not supported. must be one of 1,2,3 or 4") + ) if not isinstance(publish["visible_to"], list): raise serializers.ValidationError( - _("publish visible_to must be a list")) + _("publish visible_to must be a list") + ) - if (publish["type"] == PublishingRule.PREVIEW - and len(publish["visible_to"]) == 0): + if (publish["type"] == PublishingRule.PREVIEW and + len(publish["visible_to"]) == 0): raise serializers.ValidationError( - _("publish visible_to must not be empty when publish type is Preview" - )) + _("publish visible_to must not be empty when publish type is Preview") + ) except: - raise serializers.ValidationError( - _("publish format is not supported")) + raise serializers.ValidationError( + _("publish format is not supported") + ) return publish + def create(self, validated_data): images_data = validated_data.pop('images') - tags_data = self.validate_tags(self.context['request'].data.get( - "tags", [])) + tags_data = self.validate_tags(self.context['request'].data.get("tags", [])) category = None if validated_data.get('category', None): category = validated_data.pop('category') - publish = self.validate_publish(self.context['request'].data.get( - "publish", {})) + publish = self.validate_publish(self.context['request'].data.get("publish", {})) with transaction.atomic(): - rule = PublishingRule.objects.create( - type=publish["type"], - publisher_id=str(self.context["request"].user.id)) - + rule = PublishingRule.objects.create(type=publish["type"], + publisher_id=str(self.context["request"].user.id)) + if rule.type == PublishingRule.PREVIEW: - rule.visible_to.set( - Creator.objects.filter(username__in=publish["visible_to"])) + rule.visible_to.set(Creator.objects.filter(username__in=publish["visible_to"])) project = Project.objects.create(**validated_data, publish=rule) @@ -273,15 +244,9 @@ def create(self, validated_data): if category: category.projects.add(project) - if project.video.find( - "cloudinary.com") > -1 and project.video.split( - ".")[-1] != "mpd": - update_video_url_if_transform_ready.delay({ - "url": - project.video, - "project_id": - project.id - }) + if project.video.find("cloudinary.com") > -1 and project.video.split(".")[-1] != "mpd": + update_video_url_if_transform_ready.delay( + {"url": project.video, "project_id": project.id}) return project @@ -296,29 +261,27 @@ def update(self, project, validated_data): video_data = validated_data.pop("video") - if (project.video.find("cloudinary.com") > -1 - or project.video.startswith("{0}://{1}".format( - settings.DEFAULT_MEDIA_SERVER_PROTOCOL, - settings.DEFAULT_MEDIA_SERVER_DOMAIN)) - and project.video != video_data): + if (project.video.find("cloudinary.com") > -1 or + project.video.startswith("{0}://{1}".format( + settings.DEFAULT_MEDIA_SERVER_PROTOCOL, + settings.DEFAULT_MEDIA_SERVER_DOMAIN)) and + project.video != video_data): delete_file_task.delay(project.video) with transaction.atomic(): - rule = PublishingRule.objects.create( - type=publish["type"], - publisher_id=str(self.context["request"].user.id)) + rule = PublishingRule.objects.create(type=publish["type"], + publisher_id=str(self.context["request"].user.id)) if rule.type == PublishingRule.PREVIEW: - rule.visible_to.set( - Creator.objects.filter(username__in=publish["visible_to"])) + rule.visible_to.set(Creator.objects.filter(username__in=publish["visible_to"])) project.title = validated_data.pop("title") project.description = validated_data.pop("description") project.video = video_data project.materials_used = validated_data.pop("materials_used") project.publish = rule - + project.save() update_images(project, images_data) @@ -330,15 +293,9 @@ def update(self, project, validated_data): if category: category.projects.add(project) - if project.video.find( - "cloudinary.com") > -1 and project.video.split( - ".")[-1] != "mpd": - update_video_url_if_transform_ready.delay({ - "url": - project.video, - "project_id": - project.id - }) + if project.video.find("cloudinary.com") > -1 and project.video.split(".")[-1] != "mpd": + update_video_url_if_transform_ready.delay( + {"url": project.video, "project_id": project.id}) return project @@ -346,20 +303,27 @@ def update(self, project, validated_data): class ProjectListSerializer(serializers.ModelSerializer): creator = CreatorMinimalSerializer(read_only=True) images = ImageSerializer(many=True) - likes = serializers.SlugRelatedField(many=True, - slug_field='id', - read_only=True) - saved_by = serializers.SlugRelatedField(many=True, - slug_field='id', - read_only=True) + likes = serializers.SlugRelatedField( + many=True, slug_field='id', read_only=True) + saved_by = serializers.SlugRelatedField( + many=True, slug_field='id', read_only=True) created_on = serializers.DateTimeField(read_only=True) - publish = PublishingRuleSerializer(read_only=True) + publish = PublishingRuleSerializer(read_only=True) class Meta: model = Project fields = [ - "id", "creator", "title", "description", "video", "images", - "views_count", "likes", "saved_by", "comments_count", "created_on", + "id", + "creator", + "title", + "description", + "video", + "images", + "views_count", + "likes", + "saved_by", + "comments_count", + "created_on", "publish" ] @@ -381,19 +345,18 @@ def paginated_projects(self, obj): projects = obj.projects.all() projects = get_published_projects_for_user( - self.context['request'].user, projects) + self.context['request'].user, + projects) paginator = ProjectNumberPagination() - page = paginator.paginate_queryset(projects, self.context['request']) - serializer = ProjectSerializer( - page, - read_only=True, - many=True, - context={'request': self.context['request']}) + page = paginator.paginate_queryset( + projects, self.context['request']) + serializer = ProjectSerializer(page, read_only=True, many=True, context={ + 'request': self.context['request']}) count = projects.count() - num_pages = ceil(count / paginator.page_size) - current_page = int(self.context["request"].query_params.get( - "page", "1")) + num_pages = ceil(count/paginator.page_size) + current_page = int( + self.context["request"].query_params.get("page", "1")) if current_page != 1: prev_page = current_page - 1 else: @@ -404,9 +367,4 @@ def paginated_projects(self, obj): else: next_page = None - return { - "results": serializer.data, - "prev": prev_page, - "next": next_page, - "count": count - } + return {"results": serializer.data, "prev": prev_page, "next": next_page, "count": count} diff --git a/zubhub_backend/zubhub/projects/urls.py b/zubhub_backend/zubhub/projects/urls.py index 8a760f0df..a735d72c8 100644 --- a/zubhub_backend/zubhub/projects/urls.py +++ b/zubhub_backend/zubhub/projects/urls.py @@ -42,14 +42,5 @@ path('staff-picks/', StaffPickListAPIView.as_view(), name="staff_picks"), path('staff-picks//', StaffPickDetailsAPIView.as_view(), - name="staff_pick_details"), - path('violation-reasons/', - ViolationReasonsListAPIView.as_view(), - name='violation_reasons'), - path('/add-violation', - ProjectViolationAddApiView.as_view(), - name="add_violation"), - path('/clear-violations', - ProjectViolationsClearApiView.as_view(), - name='clear_violations') + name="staff_pick_details") ] diff --git a/zubhub_backend/zubhub/projects/views.py b/zubhub_backend/zubhub/projects/views.py index 6b1dd18b4..2bdd50899 100644 --- a/zubhub_backend/zubhub/projects/views.py +++ b/zubhub_backend/zubhub/projects/views.py @@ -9,29 +9,20 @@ from django.db.models import F from django.db import transaction from rest_framework import status -from rest_framework.views import APIView from rest_framework.generics import (UpdateAPIView, CreateAPIView, ListAPIView, RetrieveAPIView, DestroyAPIView) from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly, AllowAny -from rest_framework.exceptions import APIException from projects.permissions import (IsOwner, IsStaffOrModerator, SustainedRateThrottle, PostUserRateThrottle, GetUserRateThrottle, CustomUserRateThrottle) -from .models import Project, Comment, StaffPick, Category, Tag, PublishingRule, Violation, ViolationReason +from .models import Project, Comment, StaffPick, Category, Tag, PublishingRule from .utils import (ProjectSearchCriteria, project_changed, detect_mentions, perform_project_search, can_view, get_published_projects_for_user) from creators.utils import activity_notification, send_notification -from .serializers import ( - ProjectSerializer, - ProjectListSerializer, - CommentSerializer, - CategorySerializer, - TagSerializer, - StaffPickSerializer, - ViolationReasonSerializer, - ViolationSerializer, -) +from .serializers import (ProjectSerializer, ProjectListSerializer, + CommentSerializer, CategorySerializer, TagSerializer, + StaffPickSerializer) from .pagination import ProjectNumberPagination @@ -67,13 +58,12 @@ def perform_create(self, serializer): if self.request.user.followers is not None: print(self.__dict__) send_notification( - list(self.request.user.followers.all()), self.request.user, - [{ - "project": obj.title - } for _ in list(self.request.user.followers.all())], + list(self.request.user.followers.all()), + self.request.user, + [{"project": obj.title} for _ in list(self.request.user.followers.all())], Notification.Type.FOLLOWING_PROJECT, - f'/creators/{self.request.user.username}') - + f'/creators/{self.request.user.username}' + ) class ProjectUpdateAPIView(UpdateAPIView): """ @@ -332,18 +322,19 @@ def get_object(self): obj.likes.add(self.request.user) obj.save() - send_notification([obj.creator], self.request.user, - [{ - 'project': obj.title - }], Notification.Type.CLAP, - f'/projects/{obj.pk}') + send_notification( + [obj.creator], + self.request.user, + [{'project': obj.title}], + Notification.Type.CLAP, + f'/projects/{obj.pk}' + ) return obj else: raise PermissionDenied( _('you are not permitted to view this project')) - class ToggleSaveAPIView(RetrieveAPIView): """ Add/Remove a project from authenticated user's bookmark. @@ -373,18 +364,19 @@ def get_object(self): obj.saved_by.add(self.request.user) obj.save() - send_notification([obj.creator], self.request.user, - [{ - 'project': obj.title - }], Notification.Type.BOOKMARK, - f'/projects/{obj.pk}') + send_notification( + [obj.creator], + self.request.user, + [{'project': obj.title}], + Notification.Type.BOOKMARK, + f'/projects/{obj.pk}' + ) return obj else: raise PermissionDenied( _('you are not permitted to view this project')) - class AddCommentAPIView(CreateAPIView): """ Comment on project. @@ -455,16 +447,19 @@ def create(self, request, *args, **kwargs): "project_id": result.pk, "creator": request.user.username }) - send_notification([result.creator], self.request.user, - [{ - 'project': result.title - }], Notification.Type.COMMENT, - f'/projects/{result.pk}') + send_notification( + [result.creator], + self.request.user, + [{'project': result.title}], + Notification.Type.COMMENT, + f'/projects/{result.pk}' + ) return Response(ProjectSerializer(result, context={ 'request': request }).data, status=status.HTTP_201_CREATED) + class CategoryListAPIView(ListAPIView): @@ -591,76 +586,3 @@ def delete(self, request, *args, **kwargs): profile.save() return result - - - -class ViolationReasonsListAPIView(ListAPIView): - """ - List all violation reasons. - - Requires authentication and staff or moderator. - Returns violations reasons. - """ - - queryset = ViolationReason.objects.all() - serializer_class = ViolationReasonSerializer - permission_classes = [IsAuthenticated, IsStaffOrModerator] - throttle_classes = [CustomUserRateThrottle, SustainedRateThrottle] - - -class ProjectViolationsClearApiView(APIView): - """ - Clear all violations for a project - - Requires authentication and owner. - Returns project details. - """ - - permission_classes = [IsAuthenticated, IsOwner] - throttle_classes = [CustomUserRateThrottle, SustainedRateThrottle] - - def post(self, request, *, pk): - try: - old = Project.objects.get(pk=pk) - except Project.DoesNotExist: - return Response('Not found', status=404) - - if not request.user or old.creator.id != request.user.id: - return Response('Error', status=403) - - old.violations.set([]) - old.save() - return Response('Success') - - -class ProjectViolationAddApiView(CreateAPIView): - """ - Creates a new violation and adds it to a project. - - Requires authentication and staff or moderator. - Returns the violation details. - """ - queryset = Violation.objects.all() - serializer_class = ViolationSerializer - permission_classes = [IsAuthenticated, IsStaffOrModerator] - throttle_classes = [PostUserRateThrottle, SustainedRateThrottle] - - def perform_create(self, serializer): - pk = self.kwargs.get("pk") - try: - project = Project.objects.get(id=pk) - except Project.DoesNotExist: - return Response('Not found', status=404) - - violation = serializer.save(creator=self.request.user, project=project) - project.violations.add(violation) - project.save() - - send_notification([project.creator], self.request.user, - [{ - "project": project.title - }], Notification.Type.PROJECT_VIOLATION, - f'/projects/{project.id}') - - return violation - diff --git a/zubhub_backend/zubhub/templates/notifications/project_violation/email_message.html b/zubhub_backend/zubhub/templates/notifications/project_violation/email_message.html deleted file mode 100644 index b94efc75c..000000000 --- a/zubhub_backend/zubhub/templates/notifications/project_violation/email_message.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - {% load account %} {% load i18n %} {% load default_template_tags %} {% - autoescape off %} - -

{% default_display_name %} Your Project Received a Violation

-

Project: {{ project }}

- - diff --git a/zubhub_backend/zubhub/templates/notifications/project_violation/email_subject.txt b/zubhub_backend/zubhub/templates/notifications/project_violation/email_subject.txt deleted file mode 100644 index 15a0c856b..000000000 --- a/zubhub_backend/zubhub/templates/notifications/project_violation/email_subject.txt +++ /dev/null @@ -1,4 +0,0 @@ -{% load i18n %} -{% autoescape off %} -{% blocktrans %}Violation Received on One of Your Projects.{% endblocktrans %} -{% endautoescape %} diff --git a/zubhub_backend/zubhub/templates/notifications/project_violation/sms.txt b/zubhub_backend/zubhub/templates/notifications/project_violation/sms.txt deleted file mode 100644 index baa8a5c55..000000000 --- a/zubhub_backend/zubhub/templates/notifications/project_violation/sms.txt +++ /dev/null @@ -1 +0,0 @@ -Violation received on project {{ project }}. diff --git a/zubhub_backend/zubhub/templates/notifications/project_violation/web.html b/zubhub_backend/zubhub/templates/notifications/project_violation/web.html deleted file mode 100644 index 9dec8d038..000000000 --- a/zubhub_backend/zubhub/templates/notifications/project_violation/web.html +++ /dev/null @@ -1 +0,0 @@ -Violation received on project "{{ project }}" diff --git a/zubhub_backend/zubhub/templates/notifications/project_violation/whatsapp.txt b/zubhub_backend/zubhub/templates/notifications/project_violation/whatsapp.txt deleted file mode 100644 index baa8a5c55..000000000 --- a/zubhub_backend/zubhub/templates/notifications/project_violation/whatsapp.txt +++ /dev/null @@ -1 +0,0 @@ -Violation received on project {{ project }}. diff --git a/zubhub_frontend/zubhub/src/api/api.js b/zubhub_frontend/zubhub/src/api/api.js index 1a9fb3715..8002aa577 100644 --- a/zubhub_frontend/zubhub/src/api/api.js +++ b/zubhub_frontend/zubhub/src/api/api.js @@ -254,24 +254,6 @@ class API { } }; - getReasons = ({ token }) => { - const url = `projects/violation-reasons/`; - return this.request({ token, url }).then(res => res.json()); - }; - - addViolation = ({ id, token, body }) => { - const url = `projects/${id}/add-violation`; - body = JSON.stringify(body); - return this.request({ token, url, body, method: 'POST' }).then(res => - res.json(), - ); - }; - - clearViolations = ({ id, token }) => { - const url = `projects/${id}/clear-violations`; - return this.request({ token, url, method: 'POST' }).then(res => res.json()); - }; - /** * @method getUserProjects - get a paginated list of projects * created by the user with the provided username diff --git a/zubhub_frontend/zubhub/src/assets/js/styles/components/notification/NotificationStyles.js b/zubhub_frontend/zubhub/src/assets/js/styles/components/notification/NotificationStyles.js index 396956c32..ab2b2429e 100644 --- a/zubhub_frontend/zubhub/src/assets/js/styles/components/notification/NotificationStyles.js +++ b/zubhub_frontend/zubhub/src/assets/js/styles/components/notification/NotificationStyles.js @@ -47,11 +47,6 @@ const styles = theme => ({ backgroundColor: 'white', alignSelf: 'center', }, - warningIconWrapper: { justifyContent: 'center', minWidth: '65px' }, - warningIcon: { - border: 'none', - alignSelf: 'center', - }, group: { height: '78px', width: '68px', diff --git a/zubhub_frontend/zubhub/src/assets/js/styles/components/unpublish_form/unpublishFormStyles.js b/zubhub_frontend/zubhub/src/assets/js/styles/components/unpublish_form/unpublishFormStyles.js deleted file mode 100644 index e5aa7afdd..000000000 --- a/zubhub_frontend/zubhub/src/assets/js/styles/components/unpublish_form/unpublishFormStyles.js +++ /dev/null @@ -1,122 +0,0 @@ -const styles = theme => ({ - unpublishModalStyle: { - backgroundColor: "#ffffff", - position: 'absolute', - top: '50%', - left: '50%', - transform: 'translate(-50%, -50%)', - borderRadius: 20, - width: '45%', - padding: 35, - paddingTop: 20, - paddingRight: 0, - }, - overflowWrapper: { - maxHeight: '60vh', - overflow: 'scroll', - overflowX: 'hidden', - }, - unpublishModalMobileStyle: { - backgroundColor: "#ffffff", - position: 'absolute', - top: '50%', - left: '50%', - transform: 'translate(-50%, -50%)', - borderRadius: 20, - width: '90%', - height: '65%', - padding: 25, - paddingRight: 0, - }, - closeIconStyle: { - color: '#C4C4C4', - fontSize: 30, - strokeWidth: 0.5, - stroke: '#ffffff', - position: 'absolute', - right: 25, - top: 10, - }, - closeIconMobileStyle: { - color: '#C4C4C4', - fontSize: 30, - strokeWidth: 0.5, - stroke: '#ffffff', - position: 'absolute', - right: 10, - top: 10, - }, - descriptionHeadingStyle: { - marginTop: '1rem', - fontWeight: 900, - fontSize: '2rem', - }, - descriptionHeadingMobileStyle: { - marginTop: '1rem', - fontWeight: 900, - fontSize: '1.6rem', - marginRight: 20, - }, - descriptionSubtitleMobileStyle: { - marginBottom: '1rem', - marginRight: '1.5em', - fontSize: '0.9rem', - color: 'rgba(0, 0, 0, 0.54)', - '& .ql-editor': { - fontSize: '1rem', - fontFamily: 'Raleway,Roboto,sans-serif', - }, - }, - descriptionBodyStyle: { - marginBottom: '1rem', - marginRight: '1.5em', - color: 'rgba(0, 0, 0, 0.54)', - '& .ql-editor': { - fontSize: '1.5rem', - fontFamily: 'Raleway,Roboto,sans-serif', - }, - }, - descriptionBodyMobileStyle: { - marginRight: '1.5em', - marginBottom: '1.5em', - color: 'rgba(0, 0, 0, 0.54)', - '& .ql-editor': { - fontSize: '1rem', - fontFamily: 'Raleway,Roboto,sans-serif', - }, - '& .MuiTypography-root': { - fontSize: '0.9rem', - } - }, - hideProjectButtonStyle: { - float: 'right', - backgroundColor: '#DC3545', - paddingLeft: 25, - paddingRight: 25, - marginRight: 25, - }, - hideProjectButtonMobileStyle: { - float: 'right', - backgroundColor: '#DC3545', - paddingLeft: 25, - paddingRight: 25, - marginRight: 25, - marginBottom: 10, - }, - checkboxStyle: { - '& .MuiCheckbox-colorSecondary.Mui-checked': { - color: '#DC3545', - }, - '& .MuiCheckbox-root': { - color: '#C4C4C4', - }, - '& .MuiSvgIcon-root': { - fontSize: '3.0rem', - fontWeight: 900, - strokeWidth: 0.8, - stroke: '#ffffff', - }, - } -}); - -export default styles; \ No newline at end of file diff --git a/zubhub_frontend/zubhub/src/assets/js/styles/components/unpublish_menu/unpublishMenuStyles.js b/zubhub_frontend/zubhub/src/assets/js/styles/components/unpublish_menu/unpublishMenuStyles.js deleted file mode 100644 index 4ceff5a22..000000000 --- a/zubhub_frontend/zubhub/src/assets/js/styles/components/unpublish_menu/unpublishMenuStyles.js +++ /dev/null @@ -1,13 +0,0 @@ -const styles = theme => ({ - unpublishMenuButtonStyle: { - marginLeft: '15px', - padding: 0, - minWidth: 0, - color: '#757575', - '& .MuiSvgIcon-root': { - fontSize: '2rem', - } - }, -}); - -export default styles; \ No newline at end of file diff --git a/zubhub_frontend/zubhub/src/assets/js/styles/components/unpublished/unpublishedModalStyles.js b/zubhub_frontend/zubhub/src/assets/js/styles/components/unpublished/unpublishedModalStyles.js deleted file mode 100644 index df27731c0..000000000 --- a/zubhub_frontend/zubhub/src/assets/js/styles/components/unpublished/unpublishedModalStyles.js +++ /dev/null @@ -1,96 +0,0 @@ -const styles = theme => ({ - descriptionHeadingStyle: { - marginTop: '0em', - marginBottom: '0.5em', - fontWeight: 900, - fontSize: '2.2em', - lineHeight: '1.3em', - }, - unpublishedLabelStyle: { - borderRadius: '5px', - marginRight: '20px', - marginTop: '15px', - padding: '5px 20px', - backgroundColor: 'rgb(221,52,68)', - color: 'white', - fontSize: '0.7rem', - fontFamily: 'Raleway,Roboto,sans-serif', - fontWeight: '400', - width: 'fit-content', - height: 'fit-content', - cursor: 'pointer', - }, - overflowWrapper: { - maxHeight: '60vh', - overflowY: 'scroll', - paddingRight: '20px', - paddingBottom: '20px', - marginLeft: '10px', - }, - modalStyle: { - position: 'absolute', - top: '50%', - left: '50%', - transform: 'translate(-50%, -50%)', - width: '650px', - backgroundColor: '#ffffff', - border: 'none', - borderRadius: '20px', - padding: '20px', - boxShadow: 24, - p: 4, - maxHeight: '70%', - '&:focus': { - outline: 0, - }, - marginRight: '20', - }, - modalMobileStyle: { - position: 'absolute', - top: '50%', - left: '50%', - transform: 'translate(-50%, -50%)', - width: '90%', - backgroundColor: '#ffffff', - borderRadius: '20px', - padding: '20px', - boxShadow: 24, - p: 4, - maxHeight: '70%', - marginRight: '20', - }, - modalBodyStyle: { - marginBottom: '1.0em', - color: 'rgba(0, 0, 0, 0.54)', - '& .ql-editor': { - fontSize: '1.5rem', - fontFamily: 'Raleway,Roboto,sans-serif', - }, - }, - violationReasonStyle: { - marginBottom: '0.7em', - color: 'rgba(220, 53, 69, 1)', - '& .ql-editor': { - fontSize: '1.5rem', - fontFamily: 'Raleway,Roboto,sans-serif', - }, - }, - understandButtonStyle: { - float: 'right', - marginTop: '30px', - }, - closeIconWrapper: { - width: '100%', - }, - descriptionWrapper: { - marginRight: '-20px', - paddingBottom: '20px', - }, - closeIconStyle: { - float: 'right', - color: 'rgba(196, 196, 196, 1)', - fontSize: 40, - }, -}); - -export default styles; diff --git a/zubhub_frontend/zubhub/src/assets/js/styles/views/project_details/projectDetailsStyles.js b/zubhub_frontend/zubhub/src/assets/js/styles/views/project_details/projectDetailsStyles.js index 991482be2..bb7362354 100644 --- a/zubhub_frontend/zubhub/src/assets/js/styles/views/project_details/projectDetailsStyles.js +++ b/zubhub_frontend/zubhub/src/assets/js/styles/views/project_details/projectDetailsStyles.js @@ -29,11 +29,6 @@ const styles = theme => ({ fontWeight: 900, textAlign: 'center', }, - headerWrapperStyle: { - maxWidth: '100vw', - display: 'flex', - justifyContent: 'center', - }, metaInfoStyle: { display: 'flex', justifyContent: 'space-between', diff --git a/zubhub_frontend/zubhub/src/components/notification/Notification.jsx b/zubhub_frontend/zubhub/src/components/notification/Notification.jsx index 6491ac87a..0c3311d80 100644 --- a/zubhub_frontend/zubhub/src/components/notification/Notification.jsx +++ b/zubhub_frontend/zubhub/src/components/notification/Notification.jsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React from 'react'; import styles from '../../assets/js/styles/components/notification/NotificationStyles'; import { makeStyles } from '@material-ui/core/styles'; import { useSelector } from 'react-redux'; @@ -13,7 +13,6 @@ import { AvatarGroup } from '@material-ui/lab'; import { dFormatter } from '../../assets/js/utils/scripts'; import { useTranslation } from 'react-i18next'; import { Link, useHistory } from 'react-router-dom'; -import WarningIcon from '@material-ui/icons/Warning'; const useStyles = makeStyles(styles); const Notification = ({ notification, onNotificationClick }) => { @@ -21,42 +20,6 @@ const Notification = ({ notification, onNotificationClick }) => { const token = useSelector(store => store.auth.token); const { t } = useTranslation(); const st = dFormatter(JSON.parse('"' + notification.date + '"')); - const notificationImage = useMemo(() => { - if (notification.type === NotificationType.PROJECT_VIOLATION) { - return ( - - - - - - ); - } - - return ( - - {notification.sources.length === 1 && ( - - - - )} - {notification.sources.length > 1 && ( - - - - - )} - - ); - }, [notification]); return ( @@ -77,7 +40,28 @@ const Notification = ({ notification, onNotificationClick }) => { onNotificationClick(); }} > - {notificationImage} + + {notification.sources.length === 1 && ( + + + + )} + {notification.sources.length > 1 && ( + + + + + )} + { ); }; -export const NotificationType = { - BOOKMARK: 1, - CLAP: 2, - COMMENT: 3, - FOLLOW: 4, - FOLLOWING_PROJECT: 5, - PROJECT_VIOLATION: 6, -}; - export default Notification; diff --git a/zubhub_frontend/zubhub/src/components/unpublish_form/UnpublishForm.jsx b/zubhub_frontend/zubhub/src/components/unpublish_form/UnpublishForm.jsx deleted file mode 100644 index 7b1a17d75..000000000 --- a/zubhub_frontend/zubhub/src/components/unpublish_form/UnpublishForm.jsx +++ /dev/null @@ -1,149 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { useSelector } from 'react-redux'; -import { makeStyles } from '@material-ui/core/styles'; -import { useMediaQuery } from '@material-ui/core'; -import { - Modal, - Box, - Button, - MenuItem, - Typography, - FormGroup, - FormControlLabel, - Checkbox, -} from '@material-ui/core'; - -import CloseIcon from '@material-ui/icons/Close'; -import CustomButton from '../../components/button/Button'; -import styles from '../../assets/js/styles/components/unpublish_form/unpublishFormStyles'; -import commonStyles from '../../assets/js/styles'; -import API from '../../api'; - -const useStyles = makeStyles(styles); -const useCommonStyles = makeStyles(commonStyles); - -function UnpublishForm({ id }) { - const classes = useStyles(); - const [open, setOpen] = useState(false); - const [reasons, setReasons] = useState([]); - const [selectedReasons, setSelectedReasons] = useState(new Set()); - const mediaQuery = useMediaQuery('(max-width: 600px)'); - const token = useSelector(state => state.auth.token); - - useEffect(() => { - const fetchReasons = async () => { - const api = new API(); - const res = await api.getReasons({ token }); - setReasons(res); - }; - - fetchReasons(); - }, []); - - const handleHideProject = async () => { - const body = {}; - body['reasons'] = [...selectedReasons].map(reason => ({ id: reason })); - const api = new API(); - try { - await api.addViolation({ token, body, id }); - setOpen(false); - } catch (err) { - console.log(err); - } - }; - - const handleCheckboxClick = e => { - const id = e.target.value; - if (selectedReasons.has(id)) { - selectedReasons.delete(id); - } else { - selectedReasons.add(id); - } - setSelectedReasons(new Set(selectedReasons)); - }; - - console.log(selectedReasons); - return ( - <> - setOpen(true)}>Unpublish - setOpen(false)} - aria-labelledby="modal-modal-title" - aria-describedby="modal-modal-description" - > - - setOpen(false)} - className={ - mediaQuery ? classes.closeIconMobileStyle : classes.closeIconStyle - } - /> -
- - Why are you unpublishing this? - - - Please select the terms of use that have been breached. - - - - {reasons.map(reason => ( - - } - label={reason.description} - key={reason.id} - /> - ))} - - - - Hide Project - -
-
-
- - ); -} - -export default UnpublishForm; diff --git a/zubhub_frontend/zubhub/src/components/unpublish_menu/UnpublishMenu.jsx b/zubhub_frontend/zubhub/src/components/unpublish_menu/UnpublishMenu.jsx deleted file mode 100644 index 8ae58ae28..000000000 --- a/zubhub_frontend/zubhub/src/components/unpublish_menu/UnpublishMenu.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import React, { useState } from 'react'; -import clsx from 'clsx'; -import { makeStyles } from '@material-ui/core/styles'; -import { Modal, Typography, Button, Menu, MenuItem } from '@material-ui/core'; - -import styles from '../../assets/js/styles/components/unpublish_menu/unpublishMenuStyles'; -import commonStyles from '../../assets/js/styles'; - -import CustomButton from '../../components/button/Button'; -import MoreVertIcon from '@material-ui/icons/MoreVert'; - -import UnpublishForm from '../../components/unpublish_form/UnpublishForm.jsx'; - -const useStyles = makeStyles(styles); -const useCommonStyles = makeStyles(commonStyles); - -function UnpublishMenu({ id }) { - const classes = useStyles(); - const common_classes = useCommonStyles(); - - const [menuAnchor, setMenuAnchor] = useState(null); - - return ( - <> - setMenuAnchor(e.currentTarget)} - className={clsx(classes.unpublishMenuButtonStyle)} - > - - - setMenuAnchor(null)} - anchorOrigin={{ - vertical: 'top', - horizontal: 'left', - }} - > - - - - ); -} - -export default UnpublishMenu; diff --git a/zubhub_frontend/zubhub/src/components/unpublished_project_modal/UnpublishedModal.jsx b/zubhub_frontend/zubhub/src/components/unpublished_project_modal/UnpublishedModal.jsx deleted file mode 100644 index 665f8a9f6..000000000 --- a/zubhub_frontend/zubhub/src/components/unpublished_project_modal/UnpublishedModal.jsx +++ /dev/null @@ -1,84 +0,0 @@ -import React, { useState } from 'react'; -import { useMediaQuery } from '@material-ui/core'; -import { makeStyles } from '@material-ui/core/styles'; -import { Box, Typography, Modal, Grid } from '@material-ui/core'; -import CloseIcon from '@material-ui/icons/Close'; - -import styles from '../../assets/js/styles/components/unpublished/unpublishedModalStyles'; -import commonStyles from '../../assets/js/styles'; -import CustomButton from '../button/Button'; - -const useStyles = makeStyles(styles); - -function UnpublishedModal({ violations }) { - const classes = useStyles(); - const [open, setOpen] = useState(true); - const mediaQuery = useMediaQuery('(max-width: 600px)'); - - const handleOpen = () => setOpen(true); - const handleClose = () => setOpen(false); - - return ( - <> -
-
- UNPUBLISHED -
-
- - - - - - - -
- - Your project has been unpublished. - - - This is because your project contains information that: - - {violations.map(violation => ( - - {violation.description} - - ))} - - You must make changes to your project before it can be - republished. - - - I UNDERSTAND - -
-
-
-
-
- - ); -} - -export default UnpublishedModal; diff --git a/zubhub_frontend/zubhub/src/store/actions/projectActions.js b/zubhub_frontend/zubhub/src/store/actions/projectActions.js index 607cebf22..81a5310c9 100644 --- a/zubhub_frontend/zubhub/src/store/actions/projectActions.js +++ b/zubhub_frontend/zubhub/src/store/actions/projectActions.js @@ -17,7 +17,6 @@ export const setProjects = projects => { }; }; - /** * @function createProject * @author Raymond Ndibe diff --git a/zubhub_frontend/zubhub/src/views/create_project/createProjectScripts.js b/zubhub_frontend/zubhub/src/views/create_project/createProjectScripts.js index 7ee8475c4..edeaa977e 100644 --- a/zubhub_frontend/zubhub/src/views/create_project/createProjectScripts.js +++ b/zubhub_frontend/zubhub/src/views/create_project/createProjectScripts.js @@ -9,7 +9,6 @@ import { } from '../../assets/js/utils/scripts'; import worker from 'workerize-loader!../../assets/js/removeMetaDataWorker'; // eslint-disable-line import/no-webpack-loader-syntax import { site_mode, publish_type } from '../../assets/js/utils/constants'; -import API from '../../api'; /** * @constant vars @@ -729,15 +728,6 @@ export const uploadProject = async (state, props, handleSetState) => { category: props.values.category, t: props.t, }) - .then(_ => { - if (props.match.params.id) { - const api = new API(); - api.clearViolations({ - id: props.match.params.id, - token: props.auth.token, - }); - } - }) .catch(error => { handleSetState({ media_upload: { diff --git a/zubhub_frontend/zubhub/src/views/project_details/ProjectDetails.jsx b/zubhub_frontend/zubhub/src/views/project_details/ProjectDetails.jsx index 4bcf2f7fe..0359c00a2 100644 --- a/zubhub_frontend/zubhub/src/views/project_details/ProjectDetails.jsx +++ b/zubhub_frontend/zubhub/src/views/project_details/ProjectDetails.jsx @@ -1,7 +1,7 @@ import React from 'react'; import { useMediaQuery } from '@material-ui/core'; import { Link, useParams } from 'react-router-dom'; -import { connect, useSelector } from 'react-redux'; +import { connect } from 'react-redux'; import clsx from 'clsx'; import PropTypes from 'prop-types'; @@ -12,7 +12,6 @@ import 'slick-carousel/slick/slick.css'; import 'slick-carousel/slick/slick-theme.css'; import { makeStyles } from '@material-ui/core/styles'; -import MoreVertIcon from '@material-ui/icons/MoreVert'; import BookmarkIcon from '@material-ui/icons/Bookmark'; import BookmarkBorderIcon from '@material-ui/icons/BookmarkBorder'; import VisibilityIcon from '@material-ui/icons/Visibility'; @@ -36,7 +35,6 @@ import CustomButton from '../../components/button/Button'; import Comments from '../../components/comments/Comments'; import ErrorPage from '../error/ErrorPage'; import LoadingPage from '../loading/LoadingPage'; -import UnpublishMenu from '../../components/unpublish_menu/UnpublishMenu'; import ClapIcon, { ClapBorderIcon } from '../../assets/js/icons/ClapIcon'; import { handleOpenEnlargedImageDialog, @@ -62,8 +60,6 @@ import styles, { } from '../../assets/js/styles/views/project_details/projectDetailsStyles'; import commonStyles from '../../assets/js/styles'; -import UnpublishedModal from '../../components/unpublished_project_modal/UnpublishedModal.jsx'; - const useStyles = makeStyles(styles); const useCommonStyles = makeStyles(commonStyles); @@ -115,7 +111,6 @@ function ProjectDetails(props) { const classes = useStyles(); const common_classes = useCommonStyles(); const mediaQuery = useMediaQuery('(max-width: 600px)'); - const auth = useSelector(state => state.auth); const { id } = useParams(); const [state, setState] = React.useState({ @@ -178,26 +173,18 @@ function ProjectDetails(props) { if (loading) { return ; } else if (Object.keys(project).length > 0) { - const violations = state.project.violations[0]; return ( <> -
- {state.project.creator.id === props.auth.id && violations ? ( - - ) : ( - <> - )} - - {project.title} - -
+ + {project.title} + -
- {auth.tags.includes('staff') || - auth.tags.includes('moderator') ? ( - - ) : null} -
{project.images && project.images.length > 0 ? ( @@ -445,7 +419,6 @@ function ProjectDetails(props) { ) : null} -