feat: module favourites for user (#370)

This commit is contained in:
pablohashescobar 2023-03-06 19:00:00 +05:30 committed by GitHub
parent cb8b6b43dc
commit d28fe930a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 150 additions and 4 deletions

View File

@ -45,6 +45,7 @@ from .module import (
ModuleSerializer,
ModuleIssueSerializer,
ModuleLinkSerializer,
ModuleFavoriteSerializer,
)
from .api_token import APITokenSerializer

View File

@ -7,7 +7,7 @@ from .user import UserLiteSerializer
from .project import ProjectSerializer
from .issue import IssueStateSerializer
from plane.db.models import User, Module, ModuleMember, ModuleIssue, ModuleLink
from plane.db.models import User, Module, ModuleMember, ModuleIssue, ModuleLink, ModuleFavorite
class ModuleWriteSerializer(BaseSerializer):
@ -135,6 +135,7 @@ class ModuleSerializer(BaseSerializer):
members_detail = UserLiteSerializer(read_only=True, many=True, source="members")
issue_module = ModuleIssueSerializer(read_only=True, many=True)
link_module = ModuleLinkSerializer(read_only=True, many=True)
is_favorite = serializers.BooleanField(read_only=True)
class Meta:
model = Module
@ -147,3 +148,15 @@ class ModuleSerializer(BaseSerializer):
"created_at",
"updated_at",
]
class ModuleFavoriteSerializer(BaseSerializer):
module_detail = ModuleFlatSerializer(source="module", read_only=True)
class Meta:
model = ModuleFavorite
fields = "__all__"
read_only_fields = [
"workspace",
"project",
"user",
]

View File

@ -90,6 +90,7 @@ from plane.api.views import (
# Modules
ModuleViewSet,
ModuleIssueViewSet,
ModuleFavoriteViewSet,
## End Modules
# Api Tokens
ApiTokenEndpoint,
@ -802,6 +803,25 @@ urlpatterns = [
),
name="project-issue-module-links",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-modules/",
ModuleFavoriteViewSet.as_view(
{
"get": "list",
"post": "create",
}
),
name="user-favorite-module",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-modules/<uuid:module_id>/",
ModuleFavoriteViewSet.as_view(
{
"delete": "destroy",
}
),
name="user-favorite-module",
),
## End Modules
# API Tokens
path("api-tokens/", ApiTokenEndpoint.as_view(), name="api-tokens"),

View File

@ -80,7 +80,12 @@ from .authentication import (
MagicSignInGenerateEndpoint,
)
from .module import ModuleViewSet, ModuleIssueViewSet, ModuleLinkViewSet
from .module import (
ModuleViewSet,
ModuleIssueViewSet,
ModuleLinkViewSet,
ModuleFavoriteViewSet,
)
from .api_token import ApiTokenEndpoint

View File

@ -3,7 +3,7 @@ import json
# Django Imports
from django.db import IntegrityError
from django.db.models import Prefetch, F, OuterRef, Func
from django.db.models import Prefetch, F, OuterRef, Func, Exists
from django.core import serializers
# Third party imports
@ -18,6 +18,7 @@ from plane.api.serializers import (
ModuleSerializer,
ModuleIssueSerializer,
ModuleLinkSerializer,
ModuleFavoriteSerializer,
)
from plane.api.permissions import ProjectEntityPermission
from plane.db.models import (
@ -26,6 +27,7 @@ from plane.db.models import (
Project,
Issue,
ModuleLink,
ModuleFavorite,
)
from plane.bgtasks.issue_activites_task import issue_activity
from plane.utils.grouper import group_results
@ -99,6 +101,23 @@ class ModuleViewSet(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST,
)
def list(self, request, slug, project_id):
try:
subquery = ModuleFavorite.objects.filter(
user=self.request.user,
module_id=OuterRef("pk"),
project_id=project_id,
workspace__slug=slug,
)
modules = self.get_queryset().annotate(is_favorite=Exists(subquery))
return Response(ModuleSerializer(modules, many=True).data)
except Exception as e:
capture_exception(e)
return Response(
{"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST,
)
class ModuleIssueViewSet(BaseViewSet):
serializer_class = ModuleIssueSerializer
@ -285,3 +304,65 @@ class ModuleLinkViewSet(BaseViewSet):
.filter(project__project_projectmember__member=self.request.user)
.distinct()
)
class ModuleFavoriteViewSet(BaseViewSet):
serializer_class = ModuleFavoriteSerializer
model = ModuleFavorite
def get_queryset(self):
return self.filter_queryset(
super()
.get_queryset()
.filter(workspace__slug=self.kwargs.get("slug"))
.filter(user=self.request.user)
.select_related("module")
)
def create(self, request, slug, project_id):
try:
serializer = ModuleFavoriteSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=request.user, project_id=project_id)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except IntegrityError as e:
if "already exists" in str(e):
return Response(
{"error": "The module is already added to favorites"},
status=status.HTTP_410_GONE,
)
else:
capture_exception(e)
return Response(
{"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST,
)
except Exception as e:
capture_exception(e)
return Response(
{"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST,
)
def destroy(self, request, slug, project_id, module_id):
try:
module_favorite = ModuleFavorite.objects.get(
project=project_id,
user=request.user,
workspace__slug=slug,
module_id=module_id,
)
module_favorite.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
except ModuleFavorite.DoesNotExist:
return Response(
{"error": "Module is not in favorites"},
status=status.HTTP_400_BAD_REQUEST,
)
except Exception as e:
capture_exception(e)
return Response(
{"error": "Something went wrong please try again later"},
status=status.HTTP_400_BAD_REQUEST,
)

View File

@ -45,7 +45,7 @@ from .shortcut import Shortcut
from .view import View
from .module import Module, ModuleMember, ModuleIssue, ModuleLink
from .module import Module, ModuleMember, ModuleIssue, ModuleLink, ModuleFavorite
from .api_token import APIToken

View File

@ -100,3 +100,29 @@ class ModuleLink(ProjectBaseModel):
def __str__(self):
return f"{self.module.name} {self.url}"
class ModuleFavorite(ProjectBaseModel):
"""_summary_
ModuleFavorite (model): To store all the module favorite of the user
"""
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="module_favorites",
)
module = models.ForeignKey(
"db.Module", on_delete=models.CASCADE, related_name="module_favorites"
)
class Meta:
unique_together = ["module", "user"]
verbose_name = "Module Favorite"
verbose_name_plural = "Module Favorites"
db_table = "module_favorites"
ordering = ("-created_at",)
def __str__(self):
"""Return user and the module"""
return f"{self.user.email} <{self.module.name}>"