mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: lock and favorite
This commit is contained in:
parent
a77839a942
commit
f1ded8540e
@ -87,6 +87,7 @@ urlpatterns = [
|
|||||||
UserIssueCompletedGraphEndpoint.as_view(),
|
UserIssueCompletedGraphEndpoint.as_view(),
|
||||||
name="completed-graph",
|
name="completed-graph",
|
||||||
),
|
),
|
||||||
|
## End User Graph
|
||||||
path(
|
path(
|
||||||
"users/me/workspaces/<str:slug>/dashboard/",
|
"users/me/workspaces/<str:slug>/dashboard/",
|
||||||
UserWorkspaceDashboardEndpoint.as_view(),
|
UserWorkspaceDashboardEndpoint.as_view(),
|
||||||
@ -118,6 +119,15 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
name="user-workspace-views",
|
name="user-workspace-views",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"users/me/workspaces/<str:slug>/views/<uuid:pk>/lock/",
|
||||||
|
UserWorkspaceViewViewSet.as_view(
|
||||||
|
{
|
||||||
|
"post": "toggle_lock",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
name="user-workspace-views-lock",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"users/me/workspaces/<str:slug>/projects/<uuid:project_id>/views/",
|
"users/me/workspaces/<str:slug>/projects/<uuid:project_id>/views/",
|
||||||
UserProjectViewViewSet.as_view(
|
UserProjectViewViewSet.as_view(
|
||||||
@ -139,5 +149,5 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
name="user-project-views",
|
name="user-project-views",
|
||||||
),
|
),
|
||||||
## End User Graph
|
|
||||||
]
|
]
|
||||||
|
@ -4,7 +4,8 @@ from django.urls import path
|
|||||||
from plane.app.views import (
|
from plane.app.views import (
|
||||||
ProjectViewViewSet,
|
ProjectViewViewSet,
|
||||||
WorkspaceViewViewSet,
|
WorkspaceViewViewSet,
|
||||||
ViewFavoriteViewSet,
|
WorkspaceViewFavoriteViewSet,
|
||||||
|
ProjectViewFavoriteViewSet,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -62,22 +63,25 @@ urlpatterns = [
|
|||||||
name="global-view-issues",
|
name="global-view-issues",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-views/",
|
"workspaces/<str:slug>/views/<uuid:view_id>/favorite/",
|
||||||
ViewFavoriteViewSet.as_view(
|
WorkspaceViewFavoriteViewSet.as_view(
|
||||||
{
|
{
|
||||||
"get": "list",
|
"get": "list",
|
||||||
"post": "create",
|
"post": "create",
|
||||||
}
|
|
||||||
),
|
|
||||||
name="user-favorite-view",
|
|
||||||
),
|
|
||||||
path(
|
|
||||||
"workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-views/<uuid:view_id>/",
|
|
||||||
ViewFavoriteViewSet.as_view(
|
|
||||||
{
|
|
||||||
"delete": "destroy",
|
"delete": "destroy",
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
name="user-favorite-view",
|
name="user-workspace-favorite-view",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"workspaces/<str:slug>/projects/<uuid:project_id>/views/<uuid:view_id>/favorite/",
|
||||||
|
ProjectViewFavoriteViewSet.as_view(
|
||||||
|
{
|
||||||
|
"get": "list",
|
||||||
|
"post": "create",
|
||||||
|
"delete": "destroy",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
name="user-project-favorite-view",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -54,7 +54,8 @@ from .state import StateViewSet
|
|||||||
from .view import (
|
from .view import (
|
||||||
WorkspaceViewViewSet,
|
WorkspaceViewViewSet,
|
||||||
ProjectViewViewSet,
|
ProjectViewViewSet,
|
||||||
ViewFavoriteViewSet,
|
WorkspaceViewFavoriteViewSet,
|
||||||
|
ProjectViewFavoriteViewSet,
|
||||||
UserWorkspaceViewViewSet,
|
UserWorkspaceViewViewSet,
|
||||||
UserProjectViewViewSet,
|
UserProjectViewViewSet,
|
||||||
ProjectViewViewSet,
|
ProjectViewViewSet,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
# Django imports
|
# Django imports
|
||||||
from django.db.models import (
|
from django.db.models import (
|
||||||
Prefetch,
|
|
||||||
OuterRef,
|
OuterRef,
|
||||||
Func,
|
Func,
|
||||||
F,
|
F,
|
||||||
@ -68,46 +67,38 @@ class UserWorkspaceViewViewSet(BaseViewSet):
|
|||||||
.filter(Q(owned_by=self.request.user) & Q(access=0))
|
.filter(Q(owned_by=self.request.user) & Q(access=0))
|
||||||
.select_related("workspace")
|
.select_related("workspace")
|
||||||
.annotate(is_favorite=Exists(subquery))
|
.annotate(is_favorite=Exists(subquery))
|
||||||
.order_by(self.request.GET.get("order_by", "-created_at"))
|
.order_by(self.request.GET.get("order_by", "-is_pinned"))
|
||||||
|
.order_by("-is_pinned", "-created_at")
|
||||||
.distinct()
|
.distinct()
|
||||||
)
|
)
|
||||||
|
|
||||||
def perform_update(self, serializer):
|
def partial_update(self, request, slug, pk):
|
||||||
view = View.objects.get(pk=self.kwargs.get("pk"))
|
view = View.objects.get(pk=pk, workspace__slug=slug)
|
||||||
if view.is_locked:
|
if view.owned_by == self.request.user and not view.is_locked:
|
||||||
|
serializer = ViewSerializer(view, data=request.data, partial=True)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||||
return Response(
|
return Response(
|
||||||
{"error": "You cannot update the view"},
|
serializer.errors, status=status.HTTP_400_BAD_REQUEST
|
||||||
status=status.HTTP_403_FORBIDDEN,
|
|
||||||
)
|
)
|
||||||
if view.owned_by == self.request.user:
|
|
||||||
serializer.save()
|
|
||||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
|
||||||
return Response(
|
return Response(
|
||||||
{"error": "You cannot update the view"},
|
{"error": "You cannot update the view"},
|
||||||
status=status.HTTP_403_FORBIDDEN,
|
status=status.HTTP_403_FORBIDDEN,
|
||||||
)
|
)
|
||||||
|
|
||||||
def lock(self, request, slug, pk):
|
def toggle_lock(self, request, slug, pk):
|
||||||
view = View.objects.get(pk=pk, workspace__slug=slug)
|
view = View.objects.get(pk=pk, workspace__slug=slug)
|
||||||
|
lock = request.data.get("lock", view.is_locked)
|
||||||
if view.owned_by != self.request.user:
|
if view.owned_by != self.request.user:
|
||||||
return Response(
|
return Response(
|
||||||
{"error": "You cannot lock the view"},
|
{"error": "You cannot lock the view"},
|
||||||
status=status.HTTP_403_FORBIDDEN,
|
status=status.HTTP_403_FORBIDDEN,
|
||||||
)
|
)
|
||||||
view.is_locked = True
|
view.is_locked = lock
|
||||||
view.save()
|
view.save(update_fields=["is_locked"])
|
||||||
return Response(status=status.HTTP_200_OK)
|
return Response(ViewSerializer(view).data, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
def unlock(self, request, slug, pk):
|
|
||||||
view = View.objects.get(pk=pk, workspace__slug=slug)
|
|
||||||
if view.owned_by != self.request.user:
|
|
||||||
return Response(
|
|
||||||
{"error": "You cannot un lock the view"},
|
|
||||||
status=status.HTTP_403_FORBIDDEN,
|
|
||||||
)
|
|
||||||
view.is_locked = False
|
|
||||||
view.save()
|
|
||||||
return Response(status=status.HTTP_200_OK)
|
|
||||||
|
|
||||||
def destroy(self, request, slug, pk):
|
def destroy(self, request, slug, pk):
|
||||||
view = View.objects.get(workspace__slug=slug, pk=pk)
|
view = View.objects.get(workspace__slug=slug, pk=pk)
|
||||||
@ -149,27 +140,12 @@ class WorkspaceViewViewSet(BaseViewSet):
|
|||||||
.distinct()
|
.distinct()
|
||||||
)
|
)
|
||||||
|
|
||||||
def lock(self, request, slug, pk):
|
def toggle_lock(self, request, slug, pk):
|
||||||
view = View.objects.get(pk=pk, workspace__slug=slug)
|
view = View.objects.get(pk=pk, workspace__slug=slug)
|
||||||
if view.owned_by != self.request.user:
|
lock = request.data.get("lock", view.is_locked)
|
||||||
return Response(
|
view.is_locked = lock
|
||||||
{"error": "You cannot lock the view"},
|
view.save(update_fields=["is_locked"])
|
||||||
status=status.HTTP_403_FORBIDDEN,
|
return Response(ViewSerializer(view).data, status=status.HTTP_200_OK)
|
||||||
)
|
|
||||||
view.is_locked = True
|
|
||||||
view.save()
|
|
||||||
return Response(status=status.HTTP_200_OK)
|
|
||||||
|
|
||||||
def unlock(self, request, slug, pk):
|
|
||||||
view = View.objects.get(pk=pk, workspace__slug=slug)
|
|
||||||
if view.owned_by != self.request.user:
|
|
||||||
return Response(
|
|
||||||
{"error": "You cannot un lock the view"},
|
|
||||||
status=status.HTTP_403_FORBIDDEN,
|
|
||||||
)
|
|
||||||
view.is_locked = False
|
|
||||||
view.save()
|
|
||||||
return Response(status=status.HTTP_200_OK)
|
|
||||||
|
|
||||||
|
|
||||||
class UserProjectViewViewSet(BaseViewSet):
|
class UserProjectViewViewSet(BaseViewSet):
|
||||||
@ -208,16 +184,37 @@ class UserProjectViewViewSet(BaseViewSet):
|
|||||||
.distinct()
|
.distinct()
|
||||||
)
|
)
|
||||||
|
|
||||||
def perform_update(self, serializer):
|
def partial_update(self, request, slug, project_id, pk):
|
||||||
view = View.objects.get(pk=self.kwargs.get("pk"))
|
view = View.objects.get(
|
||||||
if view.owned_by == self.request.user:
|
pk=pk, project_id=project_id, workspace__slug=slug
|
||||||
serializer.save()
|
)
|
||||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
if view.owned_by == self.request.user and not view.is_locked:
|
||||||
|
serializer = ViewSerializer(view, data=request.data, partial=True)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||||
|
return Response(
|
||||||
|
serializer.errors, status=status.HTTP_400_BAD_REQUEST
|
||||||
|
)
|
||||||
return Response(
|
return Response(
|
||||||
{"error": "You cannot update the view"},
|
{"error": "You cannot update the view"},
|
||||||
status=status.HTTP_403_FORBIDDEN,
|
status=status.HTTP_403_FORBIDDEN,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def toggle_lock(self, request, slug, project_id, pk):
|
||||||
|
view = View.objects.get(
|
||||||
|
pk=pk, project_id=project_id, workspace__slug=slug
|
||||||
|
)
|
||||||
|
lock = request.data.get("lock", view.is_locked)
|
||||||
|
if view.owned_by != self.request.user:
|
||||||
|
return Response(
|
||||||
|
{"error": "You cannot lock the view"},
|
||||||
|
status=status.HTTP_403_FORBIDDEN,
|
||||||
|
)
|
||||||
|
view.is_locked = lock
|
||||||
|
view.save(update_fields=["is_locked"])
|
||||||
|
return Response(ViewSerializer(view).data, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
def destroy(self, request, slug, project_id, pk):
|
def destroy(self, request, slug, project_id, pk):
|
||||||
view = View.objects.get(
|
view = View.objects.get(
|
||||||
workspace__slug=slug, project_id=project_id, pk=pk
|
workspace__slug=slug, project_id=project_id, pk=pk
|
||||||
@ -230,28 +227,6 @@ class UserProjectViewViewSet(BaseViewSet):
|
|||||||
view.delete()
|
view.delete()
|
||||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
def lock(self, request, slug, pk):
|
|
||||||
view = View.objects.get(pk=pk, workspace__slug=slug)
|
|
||||||
if view.owned_by != self.request.user:
|
|
||||||
return Response(
|
|
||||||
{"error": "You cannot lock the view"},
|
|
||||||
status=status.HTTP_403_FORBIDDEN,
|
|
||||||
)
|
|
||||||
view.is_locked = True
|
|
||||||
view.save()
|
|
||||||
return Response(status=status.HTTP_200_OK)
|
|
||||||
|
|
||||||
def unlock(self, request, slug, pk):
|
|
||||||
view = View.objects.get(pk=pk, workspace__slug=slug)
|
|
||||||
if view.owned_by != self.request.user:
|
|
||||||
return Response(
|
|
||||||
{"error": "You cannot un lock the view"},
|
|
||||||
status=status.HTTP_403_FORBIDDEN,
|
|
||||||
)
|
|
||||||
view.is_locked = False
|
|
||||||
view.save()
|
|
||||||
return Response(status=status.HTTP_200_OK)
|
|
||||||
|
|
||||||
|
|
||||||
class ProjectViewViewSet(BaseViewSet):
|
class ProjectViewViewSet(BaseViewSet):
|
||||||
serializer_class = ViewSerializer
|
serializer_class = ViewSerializer
|
||||||
@ -288,27 +263,16 @@ class ProjectViewViewSet(BaseViewSet):
|
|||||||
.distinct()
|
.distinct()
|
||||||
)
|
)
|
||||||
|
|
||||||
def lock(self, request, slug, pk):
|
def toggle_lock(self, request, slug, project_id, pk):
|
||||||
view = View.objects.get(pk=pk, workspace__slug=slug)
|
view = (
|
||||||
if view.owned_by != self.request.user:
|
self.get_queryset()
|
||||||
return Response(
|
.filter(pk=pk, project_id=project_id, workspace__slug=slug)
|
||||||
{"error": "You cannot lock the view"},
|
.first()
|
||||||
status=status.HTTP_403_FORBIDDEN,
|
)
|
||||||
)
|
lock = request.data.get("lock", view.is_locked)
|
||||||
view.is_locked = True
|
view.is_locked = lock
|
||||||
view.save()
|
view.save(update_fields=["is_locked"])
|
||||||
return Response(status=status.HTTP_200_OK)
|
return Response(ViewSerializer(view).data, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
def unlock(self, request, slug, pk):
|
|
||||||
view = View.objects.get(pk=pk, workspace__slug=slug)
|
|
||||||
if view.owned_by != self.request.user:
|
|
||||||
return Response(
|
|
||||||
{"error": "You cannot un lock the view"},
|
|
||||||
status=status.HTTP_403_FORBIDDEN,
|
|
||||||
)
|
|
||||||
view.is_locked = False
|
|
||||||
view.save()
|
|
||||||
return Response(status=status.HTTP_200_OK)
|
|
||||||
|
|
||||||
|
|
||||||
class WorkspaceViewIssuesViewSet(BaseViewSet):
|
class WorkspaceViewIssuesViewSet(BaseViewSet):
|
||||||
@ -376,7 +340,7 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
|
|||||||
|
|
||||||
order_by_param = request.GET.get("order_by", "-created_at")
|
order_by_param = request.GET.get("order_by", "-created_at")
|
||||||
|
|
||||||
issue_queryset = (self.get_queryset().filter(**filters))
|
issue_queryset = self.get_queryset().filter(**filters)
|
||||||
|
|
||||||
# Priority Ordering
|
# Priority Ordering
|
||||||
if order_by_param == "priority" or order_by_param == "-priority":
|
if order_by_param == "priority" or order_by_param == "-priority":
|
||||||
@ -444,7 +408,7 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
|
|||||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
class ViewFavoriteViewSet(BaseViewSet):
|
class WorkspaceViewFavoriteViewSet(BaseViewSet):
|
||||||
serializer_class = ViewFavoriteSerializer
|
serializer_class = ViewFavoriteSerializer
|
||||||
model = ViewFavorite
|
model = ViewFavorite
|
||||||
|
|
||||||
@ -457,12 +421,45 @@ class ViewFavoriteViewSet(BaseViewSet):
|
|||||||
.select_related("view")
|
.select_related("view")
|
||||||
)
|
)
|
||||||
|
|
||||||
def create(self, request, slug, project_id):
|
def create(self, request, slug, view_id):
|
||||||
serializer = ViewFavoriteSerializer(data=request.data)
|
workspace = Workspace.objects.get(slug=slug)
|
||||||
if serializer.is_valid():
|
view = ViewFavorite.objects.create(
|
||||||
serializer.save(user=request.user, project_id=project_id)
|
view_id=view_id, user=request.user, workspace_id=workspace.id
|
||||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
)
|
||||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
return Response(
|
||||||
|
ViewFavoriteSerializer(view).data, status=status.HTTP_201_CREATED
|
||||||
|
)
|
||||||
|
|
||||||
|
def destroy(self, request, slug, view_id):
|
||||||
|
view_favorite = ViewFavorite.objects.get(
|
||||||
|
user=request.user,
|
||||||
|
workspace__slug=slug,
|
||||||
|
view_id=view_id,
|
||||||
|
)
|
||||||
|
view_favorite.delete()
|
||||||
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectViewFavoriteViewSet(BaseViewSet):
|
||||||
|
serializer_class = ViewFavoriteSerializer
|
||||||
|
model = ViewFavorite
|
||||||
|
|
||||||
|
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("view")
|
||||||
|
)
|
||||||
|
|
||||||
|
def create(self, request, slug, project_id, view_id):
|
||||||
|
view = ViewFavorite.objects.create(
|
||||||
|
view_id=view_id, user=request.user, project_id=project_id
|
||||||
|
)
|
||||||
|
return Response(
|
||||||
|
ViewFavoriteSerializer(view).data, status=status.HTTP_201_CREATED
|
||||||
|
)
|
||||||
|
|
||||||
def destroy(self, request, slug, project_id, view_id):
|
def destroy(self, request, slug, project_id, view_id):
|
||||||
view_favorite = ViewFavorite.objects.get(
|
view_favorite = ViewFavorite.objects.get(
|
||||||
|
Loading…
Reference in New Issue
Block a user