diff --git a/apiserver/back_migration.py b/apiserver/back_migration.py
index 328b9db2b..69eb2f1df 100644
--- a/apiserver/back_migration.py
+++ b/apiserver/back_migration.py
@@ -26,9 +26,7 @@ def update_description():
updated_issues.append(issue)
Issue.objects.bulk_update(
- updated_issues,
- ["description_html", "description_stripped"],
- batch_size=100,
+ updated_issues, ["description_html", "description_stripped"], batch_size=100
)
print("Success")
except Exception as e:
@@ -42,9 +40,7 @@ def update_comments():
updated_issue_comments = []
for issue_comment in issue_comments:
- issue_comment.comment_html = (
- f"
{issue_comment.comment_stripped}
"
- )
+ issue_comment.comment_html = f"{issue_comment.comment_stripped}
"
updated_issue_comments.append(issue_comment)
IssueComment.objects.bulk_update(
@@ -103,9 +99,7 @@ def updated_issue_sort_order():
issue.sort_order = issue.sequence_id * random.randint(100, 500)
updated_issues.append(issue)
- Issue.objects.bulk_update(
- updated_issues, ["sort_order"], batch_size=100
- )
+ Issue.objects.bulk_update(updated_issues, ["sort_order"], batch_size=100)
print("Success")
except Exception as e:
print(e)
@@ -143,9 +137,7 @@ def update_project_cover_images():
project.cover_image = project_cover_images[random.randint(0, 19)]
updated_projects.append(project)
- Project.objects.bulk_update(
- updated_projects, ["cover_image"], batch_size=100
- )
+ Project.objects.bulk_update(updated_projects, ["cover_image"], batch_size=100)
print("Success")
except Exception as e:
print(e)
@@ -194,9 +186,7 @@ def update_label_color():
def create_slack_integration():
try:
- _ = Integration.objects.create(
- provider="slack", network=2, title="Slack"
- )
+ _ = Integration.objects.create(provider="slack", network=2, title="Slack")
print("Success")
except Exception as e:
print(e)
@@ -222,16 +212,12 @@ def update_integration_verified():
def update_start_date():
try:
- issues = Issue.objects.filter(
- state__group__in=["started", "completed"]
- )
+ issues = Issue.objects.filter(state__group__in=["started", "completed"])
updated_issues = []
for issue in issues:
issue.start_date = issue.created_at.date()
updated_issues.append(issue)
- Issue.objects.bulk_update(
- updated_issues, ["start_date"], batch_size=500
- )
+ Issue.objects.bulk_update(updated_issues, ["start_date"], batch_size=500)
print("Success")
except Exception as e:
print(e)
diff --git a/apiserver/manage.py b/apiserver/manage.py
index 744086783..972869462 100644
--- a/apiserver/manage.py
+++ b/apiserver/manage.py
@@ -3,9 +3,7 @@ import os
import sys
if __name__ == "__main__":
- os.environ.setdefault(
- "DJANGO_SETTINGS_MODULE", "plane.settings.production"
- )
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "plane.settings.production")
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
diff --git a/apiserver/plane/api/middleware/api_authentication.py b/apiserver/plane/api/middleware/api_authentication.py
index 893df7f84..ddabb4132 100644
--- a/apiserver/plane/api/middleware/api_authentication.py
+++ b/apiserver/plane/api/middleware/api_authentication.py
@@ -25,10 +25,7 @@ class APIKeyAuthentication(authentication.BaseAuthentication):
def validate_api_token(self, token):
try:
api_token = APIToken.objects.get(
- Q(
- Q(expired_at__gt=timezone.now())
- | Q(expired_at__isnull=True)
- ),
+ Q(Q(expired_at__gt=timezone.now()) | Q(expired_at__isnull=True)),
token=token,
is_active=True,
)
diff --git a/apiserver/plane/api/rate_limit.py b/apiserver/plane/api/rate_limit.py
index 65cfd6b0c..a70ae4186 100644
--- a/apiserver/plane/api/rate_limit.py
+++ b/apiserver/plane/api/rate_limit.py
@@ -80,4 +80,4 @@ class ServiceTokenRateThrottle(SimpleRateThrottle):
request.META["X-RateLimit-Remaining"] = max(0, available)
request.META["X-RateLimit-Reset"] = reset_time
- return allowed
\ No newline at end of file
+ return allowed
diff --git a/apiserver/plane/api/serializers/__init__.py b/apiserver/plane/api/serializers/__init__.py
index 1f17e053e..b7780a90c 100644
--- a/apiserver/plane/api/serializers/__init__.py
+++ b/apiserver/plane/api/serializers/__init__.py
@@ -13,9 +13,5 @@ from .issue import (
)
from .state import StateLiteSerializer, StateSerializer
from .cycle import CycleSerializer, CycleIssueSerializer, CycleLiteSerializer
-from .module import (
- ModuleSerializer,
- ModuleIssueSerializer,
- ModuleLiteSerializer,
-)
+from .module import ModuleSerializer, ModuleIssueSerializer, ModuleLiteSerializer
from .intake import IntakeIssueSerializer
diff --git a/apiserver/plane/api/serializers/base.py b/apiserver/plane/api/serializers/base.py
index 5653ba318..d51434554 100644
--- a/apiserver/plane/api/serializers/base.py
+++ b/apiserver/plane/api/serializers/base.py
@@ -102,8 +102,6 @@ class BaseSerializer(serializers.ModelSerializer):
response[expand] = exp_serializer.data
else:
# You might need to handle this case differently
- response[expand] = getattr(
- instance, f"{expand}_id", None
- )
+ response[expand] = getattr(instance, f"{expand}_id", None)
return response
diff --git a/apiserver/plane/api/serializers/cycle.py b/apiserver/plane/api/serializers/cycle.py
index 90e3e1b42..f4f06c324 100644
--- a/apiserver/plane/api/serializers/cycle.py
+++ b/apiserver/plane/api/serializers/cycle.py
@@ -23,9 +23,7 @@ class CycleSerializer(BaseSerializer):
and data.get("end_date", None) is not None
and data.get("start_date", None) > data.get("end_date", None)
):
- raise serializers.ValidationError(
- "Start date cannot exceed end date"
- )
+ raise serializers.ValidationError("Start date cannot exceed end date")
return data
class Meta:
@@ -50,11 +48,7 @@ class CycleIssueSerializer(BaseSerializer):
class Meta:
model = CycleIssue
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- "cycle",
- ]
+ read_only_fields = ["workspace", "project", "cycle"]
class CycleLiteSerializer(BaseSerializer):
diff --git a/apiserver/plane/api/serializers/intake.py b/apiserver/plane/api/serializers/intake.py
index 0b207c704..69c85ed61 100644
--- a/apiserver/plane/api/serializers/intake.py
+++ b/apiserver/plane/api/serializers/intake.py
@@ -6,7 +6,6 @@ from rest_framework import serializers
class IntakeIssueSerializer(BaseSerializer):
-
issue_detail = IssueExpandSerializer(read_only=True, source="issue")
inbox = serializers.UUIDField(source="intake.id", read_only=True)
diff --git a/apiserver/plane/api/serializers/issue.py b/apiserver/plane/api/serializers/issue.py
index 905157339..72918b268 100644
--- a/apiserver/plane/api/serializers/issue.py
+++ b/apiserver/plane/api/serializers/issue.py
@@ -49,25 +49,13 @@ class IssueSerializer(BaseSerializer):
required=False,
)
type_id = serializers.PrimaryKeyRelatedField(
- source="type",
- queryset=IssueType.objects.all(),
- required=False,
- allow_null=True,
+ source="type", queryset=IssueType.objects.all(), required=False, allow_null=True
)
class Meta:
model = Issue
- read_only_fields = [
- "id",
- "workspace",
- "project",
- "updated_by",
- "updated_at",
- ]
- exclude = [
- "description",
- "description_stripped",
- ]
+ read_only_fields = ["id", "workspace", "project", "updated_by", "updated_at"]
+ exclude = ["description", "description_stripped"]
def validate(self, data):
if (
@@ -75,9 +63,7 @@ class IssueSerializer(BaseSerializer):
and data.get("target_date", None) is not None
and data.get("start_date", None) > data.get("target_date", None)
):
- raise serializers.ValidationError(
- "Start date cannot exceed target date"
- )
+ raise serializers.ValidationError("Start date cannot exceed target date")
try:
if data.get("description_html", None) is not None:
@@ -99,16 +85,14 @@ class IssueSerializer(BaseSerializer):
# Validate labels are from project
if data.get("labels", []):
data["labels"] = Label.objects.filter(
- project_id=self.context.get("project_id"),
- id__in=data["labels"],
+ project_id=self.context.get("project_id"), id__in=data["labels"]
).values_list("id", flat=True)
# Check state is from the project only else raise validation error
if (
data.get("state")
and not State.objects.filter(
- project_id=self.context.get("project_id"),
- pk=data.get("state").id,
+ project_id=self.context.get("project_id"), pk=data.get("state").id
).exists()
):
raise serializers.ValidationError(
@@ -119,8 +103,7 @@ class IssueSerializer(BaseSerializer):
if (
data.get("parent")
and not Issue.objects.filter(
- workspace_id=self.context.get("workspace_id"),
- pk=data.get("parent").id,
+ workspace_id=self.context.get("workspace_id"), pk=data.get("parent").id
).exists()
):
raise serializers.ValidationError(
@@ -147,9 +130,7 @@ class IssueSerializer(BaseSerializer):
issue_type = issue_type
issue = Issue.objects.create(
- **validated_data,
- project_id=project_id,
- type=issue_type,
+ **validated_data, project_id=project_id, type=issue_type
)
# Issue Audit Users
@@ -264,13 +245,9 @@ class IssueSerializer(BaseSerializer):
]
if "labels" in self.fields:
if "labels" in self.expand:
- data["labels"] = LabelSerializer(
- instance.labels.all(), many=True
- ).data
+ data["labels"] = LabelSerializer(instance.labels.all(), many=True).data
else:
- data["labels"] = [
- str(label.id) for label in instance.labels.all()
- ]
+ data["labels"] = [str(label.id) for label in instance.labels.all()]
return data
@@ -278,11 +255,7 @@ class IssueSerializer(BaseSerializer):
class IssueLiteSerializer(BaseSerializer):
class Meta:
model = Issue
- fields = [
- "id",
- "sequence_id",
- "project_id",
- ]
+ fields = ["id", "sequence_id", "project_id"]
read_only_fields = fields
@@ -334,8 +307,7 @@ class IssueLinkSerializer(BaseSerializer):
# Validation if url already exists
def create(self, validated_data):
if IssueLink.objects.filter(
- url=validated_data.get("url"),
- issue_id=validated_data.get("issue_id"),
+ url=validated_data.get("url"), issue_id=validated_data.get("issue_id")
).exists():
raise serializers.ValidationError(
{"error": "URL already exists for this Issue"}
@@ -345,8 +317,7 @@ class IssueLinkSerializer(BaseSerializer):
def update(self, instance, validated_data):
if (
IssueLink.objects.filter(
- url=validated_data.get("url"),
- issue_id=instance.issue_id,
+ url=validated_data.get("url"), issue_id=instance.issue_id
)
.exclude(pk=instance.id)
.exists()
@@ -387,10 +358,7 @@ class IssueCommentSerializer(BaseSerializer):
"created_at",
"updated_at",
]
- exclude = [
- "comment_stripped",
- "comment_json",
- ]
+ exclude = ["comment_stripped", "comment_json"]
def validate(self, data):
try:
@@ -407,38 +375,27 @@ class IssueCommentSerializer(BaseSerializer):
class IssueActivitySerializer(BaseSerializer):
class Meta:
model = IssueActivity
- exclude = [
- "created_by",
- "updated_by",
- ]
+ exclude = ["created_by", "updated_by"]
class CycleIssueSerializer(BaseSerializer):
cycle = CycleSerializer(read_only=True)
class Meta:
- fields = [
- "cycle",
- ]
+ fields = ["cycle"]
class ModuleIssueSerializer(BaseSerializer):
module = ModuleSerializer(read_only=True)
class Meta:
- fields = [
- "module",
- ]
+ fields = ["module"]
class LabelLiteSerializer(BaseSerializer):
class Meta:
model = Label
- fields = [
- "id",
- "name",
- "color",
- ]
+ fields = ["id", "name", "color"]
class IssueExpandSerializer(BaseSerializer):
diff --git a/apiserver/plane/api/serializers/module.py b/apiserver/plane/api/serializers/module.py
index c1a0c577d..ace4e15c8 100644
--- a/apiserver/plane/api/serializers/module.py
+++ b/apiserver/plane/api/serializers/module.py
@@ -53,14 +53,11 @@ class ModuleSerializer(BaseSerializer):
and data.get("target_date", None) is not None
and data.get("start_date", None) > data.get("target_date", None)
):
- raise serializers.ValidationError(
- "Start date cannot exceed target date"
- )
+ raise serializers.ValidationError("Start date cannot exceed target date")
if data.get("members", []):
data["members"] = ProjectMember.objects.filter(
- project_id=self.context.get("project_id"),
- member_id__in=data["members"],
+ project_id=self.context.get("project_id"), member_id__in=data["members"]
).values_list("member_id", flat=True)
return data
@@ -74,9 +71,7 @@ class ModuleSerializer(BaseSerializer):
module_name = validated_data.get("name")
if module_name:
# Lookup for the module name in the module table for that project
- if Module.objects.filter(
- name=module_name, project_id=project_id
- ).exists():
+ if Module.objects.filter(name=module_name, project_id=project_id).exists():
raise serializers.ValidationError(
{"error": "Module with this name already exists"}
)
@@ -107,9 +102,7 @@ class ModuleSerializer(BaseSerializer):
if module_name:
# Lookup for the module name in the module table for that project
if (
- Module.objects.filter(
- name=module_name, project=instance.project
- )
+ Module.objects.filter(name=module_name, project=instance.project)
.exclude(id=instance.id)
.exists()
):
@@ -172,8 +165,7 @@ class ModuleLinkSerializer(BaseSerializer):
# Validation if url already exists
def create(self, validated_data):
if ModuleLink.objects.filter(
- url=validated_data.get("url"),
- module_id=validated_data.get("module_id"),
+ url=validated_data.get("url"), module_id=validated_data.get("module_id")
).exists():
raise serializers.ValidationError(
{"error": "URL already exists for this Issue"}
diff --git a/apiserver/plane/api/serializers/project.py b/apiserver/plane/api/serializers/project.py
index d9c3e2c2a..744084ab1 100644
--- a/apiserver/plane/api/serializers/project.py
+++ b/apiserver/plane/api/serializers/project.py
@@ -2,11 +2,7 @@
from rest_framework import serializers
# Module imports
-from plane.db.models import (
- Project,
- ProjectIdentifier,
- WorkspaceMember,
-)
+from plane.db.models import Project, ProjectIdentifier, WorkspaceMember
from .base import BaseSerializer
@@ -67,16 +63,12 @@ class ProjectSerializer(BaseSerializer):
def create(self, validated_data):
identifier = validated_data.get("identifier", "").strip().upper()
if identifier == "":
- raise serializers.ValidationError(
- detail="Project Identifier is required"
- )
+ raise serializers.ValidationError(detail="Project Identifier is required")
if ProjectIdentifier.objects.filter(
name=identifier, workspace_id=self.context["workspace_id"]
).exists():
- raise serializers.ValidationError(
- detail="Project Identifier is taken"
- )
+ raise serializers.ValidationError(detail="Project Identifier is taken")
project = Project.objects.create(
**validated_data, workspace_id=self.context["workspace_id"]
diff --git a/apiserver/plane/api/serializers/state.py b/apiserver/plane/api/serializers/state.py
index f4ffcba85..85b4c41ed 100644
--- a/apiserver/plane/api/serializers/state.py
+++ b/apiserver/plane/api/serializers/state.py
@@ -7,9 +7,9 @@ class StateSerializer(BaseSerializer):
def validate(self, data):
# If the default is being provided then make all other states default False
if data.get("default", False):
- State.objects.filter(
- project_id=self.context.get("project_id")
- ).update(default=False)
+ State.objects.filter(project_id=self.context.get("project_id")).update(
+ default=False
+ )
return data
class Meta:
@@ -30,10 +30,5 @@ class StateSerializer(BaseSerializer):
class StateLiteSerializer(BaseSerializer):
class Meta:
model = State
- fields = [
- "id",
- "name",
- "color",
- "group",
- ]
+ fields = ["id", "name", "color", "group"]
read_only_fields = fields
diff --git a/apiserver/plane/api/serializers/workspace.py b/apiserver/plane/api/serializers/workspace.py
index a47de3d31..84453b8e0 100644
--- a/apiserver/plane/api/serializers/workspace.py
+++ b/apiserver/plane/api/serializers/workspace.py
@@ -8,9 +8,5 @@ class WorkspaceLiteSerializer(BaseSerializer):
class Meta:
model = Workspace
- fields = [
- "name",
- "slug",
- "id",
- ]
+ fields = ["name", "slug", "id"]
read_only_fields = fields
diff --git a/apiserver/plane/api/urls/member.py b/apiserver/plane/api/urls/member.py
index 5fe1785a7..1ec9cddb3 100644
--- a/apiserver/plane/api/urls/member.py
+++ b/apiserver/plane/api/urls/member.py
@@ -1,13 +1,11 @@
from django.urls import path
-from plane.api.views import (
- ProjectMemberAPIEndpoint,
-)
+from plane.api.views import ProjectMemberAPIEndpoint
urlpatterns = [
path(
"workspaces//projects//members/",
ProjectMemberAPIEndpoint.as_view(),
name="users",
- ),
+ )
]
diff --git a/apiserver/plane/api/urls/project.py b/apiserver/plane/api/urls/project.py
index 5efb85bb0..d35c2cdd5 100644
--- a/apiserver/plane/api/urls/project.py
+++ b/apiserver/plane/api/urls/project.py
@@ -1,15 +1,10 @@
from django.urls import path
-from plane.api.views import (
- ProjectAPIEndpoint,
- ProjectArchiveUnarchiveAPIEndpoint,
-)
+from plane.api.views import ProjectAPIEndpoint, ProjectArchiveUnarchiveAPIEndpoint
urlpatterns = [
path(
- "workspaces//projects/",
- ProjectAPIEndpoint.as_view(),
- name="project",
+ "workspaces//projects/", ProjectAPIEndpoint.as_view(), name="project"
),
path(
"workspaces//projects//",
diff --git a/apiserver/plane/api/views/base.py b/apiserver/plane/api/views/base.py
index a3241eaf3..c79c2f853 100644
--- a/apiserver/plane/api/views/base.py
+++ b/apiserver/plane/api/views/base.py
@@ -37,13 +37,9 @@ class TimezoneMixin:
class BaseAPIView(TimezoneMixin, APIView, BasePaginator):
- authentication_classes = [
- APIKeyAuthentication,
- ]
+ authentication_classes = [APIKeyAuthentication]
- permission_classes = [
- IsAuthenticated,
- ]
+ permission_classes = [IsAuthenticated]
def filter_queryset(self, queryset):
for backend in list(self.filter_backends):
@@ -56,8 +52,7 @@ class BaseAPIView(TimezoneMixin, APIView, BasePaginator):
if api_key:
service_token = APIToken.objects.filter(
- token=api_key,
- is_service=True,
+ token=api_key, is_service=True
).first()
if service_token:
@@ -123,9 +118,7 @@ class BaseAPIView(TimezoneMixin, APIView, BasePaginator):
def finalize_response(self, request, response, *args, **kwargs):
# Call super to get the default response
- response = super().finalize_response(
- request, response, *args, **kwargs
- )
+ response = super().finalize_response(request, response, *args, **kwargs)
# Add custom headers if they exist in the request META
ratelimit_remaining = request.META.get("X-RateLimit-Remaining")
@@ -154,17 +147,13 @@ class BaseAPIView(TimezoneMixin, APIView, BasePaginator):
@property
def fields(self):
fields = [
- field
- for field in self.request.GET.get("fields", "").split(",")
- if field
+ field for field in self.request.GET.get("fields", "").split(",") if field
]
return fields if fields else None
@property
def expand(self):
expand = [
- expand
- for expand in self.request.GET.get("expand", "").split(",")
- if expand
+ expand for expand in self.request.GET.get("expand", "").split(",") if expand
]
- return expand if expand else None
\ No newline at end of file
+ return expand if expand else None
diff --git a/apiserver/plane/api/views/cycle.py b/apiserver/plane/api/views/cycle.py
index a4a61a928..3665e3b0f 100644
--- a/apiserver/plane/api/views/cycle.py
+++ b/apiserver/plane/api/views/cycle.py
@@ -25,10 +25,7 @@ from rest_framework import status
from rest_framework.response import Response
# Module imports
-from plane.api.serializers import (
- CycleIssueSerializer,
- CycleSerializer,
-)
+from plane.api.serializers import CycleIssueSerializer, CycleSerializer
from plane.app.permissions import ProjectEntityPermission
from plane.bgtasks.issue_activities_task import issue_activity
from plane.db.models import (
@@ -57,9 +54,7 @@ class CycleAPIEndpoint(BaseAPIView):
serializer_class = CycleSerializer
model = Cycle
webhook_event = "cycle"
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
def get_queryset(self):
return (
@@ -143,26 +138,18 @@ class CycleAPIEndpoint(BaseAPIView):
def get(self, request, slug, project_id, pk=None):
if pk:
- queryset = (
- self.get_queryset().filter(archived_at__isnull=True).get(pk=pk)
- )
+ queryset = self.get_queryset().filter(archived_at__isnull=True).get(pk=pk)
data = CycleSerializer(
- queryset,
- fields=self.fields,
- expand=self.expand,
+ queryset, fields=self.fields, expand=self.expand
).data
- return Response(
- data,
- status=status.HTTP_200_OK,
- )
+ return Response(data, status=status.HTTP_200_OK)
queryset = self.get_queryset().filter(archived_at__isnull=True)
cycle_view = request.GET.get("cycle_view", "all")
# Current Cycle
if cycle_view == "current":
queryset = queryset.filter(
- start_date__lte=timezone.now(),
- end_date__gte=timezone.now(),
+ start_date__lte=timezone.now(), end_date__gte=timezone.now()
)
data = CycleSerializer(
queryset, many=True, fields=self.fields, expand=self.expand
@@ -176,10 +163,7 @@ class CycleAPIEndpoint(BaseAPIView):
request=request,
queryset=(queryset),
on_results=lambda cycles: CycleSerializer(
- cycles,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ cycles, many=True, fields=self.fields, expand=self.expand
).data,
)
@@ -190,53 +174,38 @@ class CycleAPIEndpoint(BaseAPIView):
request=request,
queryset=(queryset),
on_results=lambda cycles: CycleSerializer(
- cycles,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ cycles, many=True, fields=self.fields, expand=self.expand
).data,
)
# Draft Cycles
if cycle_view == "draft":
- queryset = queryset.filter(
- end_date=None,
- start_date=None,
- )
+ queryset = queryset.filter(end_date=None, start_date=None)
return self.paginate(
request=request,
queryset=(queryset),
on_results=lambda cycles: CycleSerializer(
- cycles,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ cycles, many=True, fields=self.fields, expand=self.expand
).data,
)
# Incomplete Cycles
if cycle_view == "incomplete":
queryset = queryset.filter(
- Q(end_date__gte=timezone.now()) | Q(end_date__isnull=True),
+ Q(end_date__gte=timezone.now()) | Q(end_date__isnull=True)
)
return self.paginate(
request=request,
queryset=(queryset),
on_results=lambda cycles: CycleSerializer(
- cycles,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ cycles, many=True, fields=self.fields, expand=self.expand
).data,
)
return self.paginate(
request=request,
queryset=(queryset),
on_results=lambda cycles: CycleSerializer(
- cycles,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ cycles, many=True, fields=self.fields, expand=self.expand
).data,
)
@@ -273,10 +242,7 @@ class CycleAPIEndpoint(BaseAPIView):
},
status=status.HTTP_409_CONFLICT,
)
- serializer.save(
- project_id=project_id,
- owned_by=request.user,
- )
+ serializer.save(project_id=project_id, owned_by=request.user)
# Send the model activity
model_activity.delay(
model_name="cycle",
@@ -287,12 +253,8 @@ class CycleAPIEndpoint(BaseAPIView):
slug=slug,
origin=request.META.get("HTTP_ORIGIN"),
)
- return Response(
- serializer.data, status=status.HTTP_201_CREATED
- )
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.data, status=status.HTTP_201_CREATED)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(
{
@@ -302,9 +264,7 @@ class CycleAPIEndpoint(BaseAPIView):
)
def patch(self, request, slug, project_id, pk):
- cycle = Cycle.objects.get(
- workspace__slug=slug, project_id=project_id, pk=pk
- )
+ cycle = Cycle.objects.get(workspace__slug=slug, project_id=project_id, pk=pk)
current_instance = json.dumps(
CycleSerializer(cycle).data, cls=DjangoJSONEncoder
@@ -322,9 +282,7 @@ class CycleAPIEndpoint(BaseAPIView):
if "sort_order" in request_data:
# Can only change sort order
request_data = {
- "sort_order": request_data.get(
- "sort_order", cycle.sort_order
- )
+ "sort_order": request_data.get("sort_order", cycle.sort_order)
}
else:
return Response(
@@ -371,9 +329,7 @@ class CycleAPIEndpoint(BaseAPIView):
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, slug, project_id, pk):
- cycle = Cycle.objects.get(
- workspace__slug=slug, project_id=project_id, pk=pk
- )
+ cycle = Cycle.objects.get(workspace__slug=slug, project_id=project_id, pk=pk)
if cycle.owned_by_id != request.user.id and (
not ProjectMember.objects.filter(
workspace__slug=slug,
@@ -389,9 +345,9 @@ class CycleAPIEndpoint(BaseAPIView):
)
cycle_issues = list(
- CycleIssue.objects.filter(
- cycle_id=self.kwargs.get("pk")
- ).values_list("issue", flat=True)
+ CycleIssue.objects.filter(cycle_id=self.kwargs.get("pk")).values_list(
+ "issue", flat=True
+ )
)
issue_activity.delay(
@@ -413,17 +369,13 @@ class CycleAPIEndpoint(BaseAPIView):
cycle.delete()
# Delete the user favorite cycle
UserFavorite.objects.filter(
- entity_type="cycle",
- entity_identifier=pk,
- project_id=project_id,
+ entity_type="cycle", entity_identifier=pk, project_id=project_id
).delete()
return Response(status=status.HTTP_204_NO_CONTENT)
class CycleArchiveUnarchiveAPIEndpoint(BaseAPIView):
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
def get_queryset(self):
return (
@@ -502,9 +454,7 @@ class CycleArchiveUnarchiveAPIEndpoint(BaseAPIView):
),
)
)
- .annotate(
- total_estimates=Sum("issue_cycle__issue__estimate_point")
- )
+ .annotate(total_estimates=Sum("issue_cycle__issue__estimate_point"))
.annotate(
completed_estimates=Sum(
"issue_cycle__issue__estimate_point",
@@ -536,10 +486,7 @@ class CycleArchiveUnarchiveAPIEndpoint(BaseAPIView):
request=request,
queryset=(self.get_queryset()),
on_results=lambda cycles: CycleSerializer(
- cycles,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ cycles, many=True, fields=self.fields, expand=self.expand
).data,
)
@@ -582,16 +529,12 @@ class CycleIssueAPIEndpoint(BaseAPIView):
model = CycleIssue
webhook_event = "cycle_issue"
bulk = True
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
def get_queryset(self):
return (
CycleIssue.objects.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("issue_id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("issue_id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -630,13 +573,10 @@ class CycleIssueAPIEndpoint(BaseAPIView):
order_by = request.GET.get("order_by", "created_at")
issues = (
Issue.issue_objects.filter(
- issue_cycle__cycle_id=cycle_id,
- issue_cycle__deleted_at__isnull=True,
+ issue_cycle__cycle_id=cycle_id, issue_cycle__deleted_at__isnull=True
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -672,10 +612,7 @@ class CycleIssueAPIEndpoint(BaseAPIView):
request=request,
queryset=(issues),
on_results=lambda issues: CycleSerializer(
- issues,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ issues, many=True, fields=self.fields, expand=self.expand
).data,
)
@@ -684,8 +621,7 @@ class CycleIssueAPIEndpoint(BaseAPIView):
if not issues:
return Response(
- {"error": "Issues are required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Issues are required"}, status=status.HTTP_400_BAD_REQUEST
)
cycle = Cycle.objects.get(
@@ -694,9 +630,7 @@ class CycleIssueAPIEndpoint(BaseAPIView):
# Get all CycleIssues already created
cycle_issues = list(
- CycleIssue.objects.filter(
- ~Q(cycle_id=cycle_id), issue_id__in=issues
- )
+ CycleIssue.objects.filter(~Q(cycle_id=cycle_id), issue_id__in=issues)
)
existing_issues = [
@@ -741,9 +675,7 @@ class CycleIssueAPIEndpoint(BaseAPIView):
)
# Update the cycle issues
- CycleIssue.objects.bulk_update(
- updated_records, ["cycle_id"], batch_size=100
- )
+ CycleIssue.objects.bulk_update(updated_records, ["cycle_id"], batch_size=100)
# Capture Issue Activity
issue_activity.delay(
@@ -802,9 +734,7 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView):
"""
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
def post(self, request, slug, project_id, cycle_id):
new_cycle_id = request.data.get("new_cycle_id", False)
@@ -930,9 +860,7 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView):
)
.values("display_name", "assignee_id", "avatar", "avatar_url")
.annotate(
- total_estimates=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ total_estimates=Sum(Cast("estimate_point__value", FloatField()))
)
.annotate(
completed_estimates=Sum(
@@ -961,9 +889,7 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView):
{
"display_name": item["display_name"],
"assignee_id": (
- str(item["assignee_id"])
- if item["assignee_id"]
- else None
+ str(item["assignee_id"]) if item["assignee_id"] else None
),
"avatar": item.get("avatar", None),
"avatar_url": item.get("avatar_url", None),
@@ -986,9 +912,7 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView):
.annotate(label_id=F("labels__id"))
.values("label_name", "color", "label_id")
.annotate(
- total_estimates=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ total_estimates=Sum(Cast("estimate_point__value", FloatField()))
)
.annotate(
completed_estimates=Sum(
@@ -1025,9 +949,7 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView):
{
"label_name": item["label_name"],
"color": item["color"],
- "label_id": (
- str(item["label_id"]) if item["label_id"] else None
- ),
+ "label_id": (str(item["label_id"]) if item["label_id"] else None),
"total_estimates": item["total_estimates"],
"completed_estimates": item["completed_estimates"],
"pending_estimates": item["pending_estimates"],
@@ -1059,8 +981,7 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView):
),
# If `avatar_asset` is None, fall back to using `avatar` field directly
When(
- assignees__avatar_asset__isnull=True,
- then="assignees__avatar",
+ assignees__avatar_asset__isnull=True, then="assignees__avatar"
),
default=Value(None),
output_field=models.CharField(),
@@ -1069,12 +990,8 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView):
.values("display_name", "assignee_id", "avatar_url")
.annotate(
total_issues=Count(
- "id",
- filter=Q(
- archived_at__isnull=True,
- is_draft=False,
- ),
- ),
+ "id", filter=Q(archived_at__isnull=True, is_draft=False)
+ )
)
.annotate(
completed_issues=Count(
@@ -1128,12 +1045,8 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView):
.values("label_name", "color", "label_id")
.annotate(
total_issues=Count(
- "id",
- filter=Q(
- archived_at__isnull=True,
- is_draft=False,
- ),
- ),
+ "id", filter=Q(archived_at__isnull=True, is_draft=False)
+ )
)
.annotate(
completed_issues=Count(
@@ -1163,9 +1076,7 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView):
{
"label_name": item["label_name"],
"color": item["color"],
- "label_id": (
- str(item["label_id"]) if item["label_id"] else None
- ),
+ "label_id": (str(item["label_id"]) if item["label_id"] else None),
"total_issues": item["total_issues"],
"completed_issues": item["completed_issues"],
"pending_issues": item["pending_issues"],
@@ -1210,10 +1121,7 @@ class TransferCycleIssueAPIEndpoint(BaseAPIView):
}
current_cycle.save(update_fields=["progress_snapshot"])
- if (
- new_cycle.end_date is not None
- and new_cycle.end_date < timezone.now()
- ):
+ if new_cycle.end_date is not None and new_cycle.end_date < timezone.now():
return Response(
{
"error": "The cycle where the issues are transferred is already completed"
diff --git a/apiserver/plane/api/views/intake.py b/apiserver/plane/api/views/intake.py
index 95354f235..c2d0733ba 100644
--- a/apiserver/plane/api/views/intake.py
+++ b/apiserver/plane/api/views/intake.py
@@ -17,14 +17,7 @@ from rest_framework.response import Response
from plane.api.serializers import IntakeIssueSerializer, IssueSerializer
from plane.app.permissions import ProjectLitePermission
from plane.bgtasks.issue_activities_task import issue_activity
-from plane.db.models import (
- Intake,
- IntakeIssue,
- Issue,
- Project,
- ProjectMember,
- State,
-)
+from plane.db.models import Intake, IntakeIssue, Issue, Project, ProjectMember, State
from .base import BaseAPIView
@@ -36,16 +29,12 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
"""
- permission_classes = [
- ProjectLitePermission,
- ]
+ permission_classes = [ProjectLitePermission]
serializer_class = IntakeIssueSerializer
model = IntakeIssue
- filterset_fields = [
- "status",
- ]
+ filterset_fields = ["status"]
def get_queryset(self):
intake = Intake.objects.filter(
@@ -54,8 +43,7 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
).first()
project = Project.objects.get(
- workspace__slug=self.kwargs.get("slug"),
- pk=self.kwargs.get("project_id"),
+ workspace__slug=self.kwargs.get("slug"), pk=self.kwargs.get("project_id")
)
if intake is None and not project.intake_view:
@@ -63,8 +51,7 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
return (
IntakeIssue.objects.filter(
- Q(snoozed_till__gte=timezone.now())
- | Q(snoozed_till__isnull=True),
+ Q(snoozed_till__gte=timezone.now()) | Q(snoozed_till__isnull=True),
workspace__slug=self.kwargs.get("slug"),
project_id=self.kwargs.get("project_id"),
intake_id=intake.id,
@@ -77,41 +64,29 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
if issue_id:
intake_issue_queryset = self.get_queryset().get(issue_id=issue_id)
intake_issue_data = IntakeIssueSerializer(
- intake_issue_queryset,
- fields=self.fields,
- expand=self.expand,
+ intake_issue_queryset, fields=self.fields, expand=self.expand
).data
- return Response(
- intake_issue_data,
- status=status.HTTP_200_OK,
- )
+ return Response(intake_issue_data, status=status.HTTP_200_OK)
issue_queryset = self.get_queryset()
return self.paginate(
request=request,
queryset=(issue_queryset),
on_results=lambda intake_issues: IntakeIssueSerializer(
- intake_issues,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ intake_issues, many=True, fields=self.fields, expand=self.expand
).data,
)
def post(self, request, slug, project_id):
if not request.data.get("issue", {}).get("name", False):
return Response(
- {"error": "Name is required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Name is required"}, status=status.HTTP_400_BAD_REQUEST
)
intake = Intake.objects.filter(
workspace__slug=slug, project_id=project_id
).first()
- project = Project.objects.get(
- workspace__slug=slug,
- pk=project_id,
- )
+ project = Project.objects.get(workspace__slug=slug, pk=project_id)
# Intake view
if intake is None and not project.intake_view:
@@ -131,8 +106,7 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
"none",
]:
return Response(
- {"error": "Invalid priority"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Invalid priority"}, status=status.HTTP_400_BAD_REQUEST
)
# Create or get state
@@ -184,10 +158,7 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
workspace__slug=slug, project_id=project_id
).first()
- project = Project.objects.get(
- workspace__slug=slug,
- pk=project_id,
- )
+ project = Project.objects.get(workspace__slug=slug, pk=project_id)
# Intake view
if intake is None and not project.intake_view:
@@ -234,7 +205,7 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
distinct=True,
filter=Q(
~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ & Q(label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -251,11 +222,7 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
),
Value([], output_field=ArrayField(UUIDField())),
),
- ).get(
- pk=issue_id,
- workspace__slug=slug,
- project_id=project_id,
- )
+ ).get(pk=issue_id, workspace__slug=slug, project_id=project_id)
# Only allow guests to edit name and description
if project_member.role <= 5:
issue_data = {
@@ -263,14 +230,10 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
"description_html": issue_data.get(
"description_html", issue.description_html
),
- "description": issue_data.get(
- "description", issue.description
- ),
+ "description": issue_data.get("description", issue.description),
}
- issue_serializer = IssueSerializer(
- issue, data=issue_data, partial=True
- )
+ issue_serializer = IssueSerializer(issue, data=issue_data, partial=True)
if issue_serializer.is_valid():
current_instance = issue
@@ -310,14 +273,10 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
# Update the issue state if the issue is rejected or marked as duplicate
if serializer.data["status"] in [-1, 2]:
issue = Issue.objects.get(
- pk=issue_id,
- workspace__slug=slug,
- project_id=project_id,
+ pk=issue_id, workspace__slug=slug, project_id=project_id
)
state = State.objects.filter(
- group="cancelled",
- workspace__slug=slug,
- project_id=project_id,
+ group="cancelled", workspace__slug=slug, project_id=project_id
).first()
if state is not None:
issue.state = state
@@ -326,18 +285,14 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
# Update the issue state if it is accepted
if serializer.data["status"] in [1]:
issue = Issue.objects.get(
- pk=issue_id,
- workspace__slug=slug,
- project_id=project_id,
+ pk=issue_id, workspace__slug=slug, project_id=project_id
)
# Update the issue state only if it is in triage state
if issue.state.is_triage:
# Move to default state
state = State.objects.filter(
- workspace__slug=slug,
- project_id=project_id,
- default=True,
+ workspace__slug=slug, project_id=project_id, default=True
).first()
if state is not None:
issue.state = state
@@ -346,9 +301,7 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
# create a activity for status change
issue_activity.delay(
type="intake.activity.created",
- requested_data=json.dumps(
- request.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(request.data, cls=DjangoJSONEncoder),
actor_id=str(request.user.id),
issue_id=str(issue_id),
project_id=str(project_id),
@@ -360,13 +313,10 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
)
return Response(serializer.data, status=status.HTTP_200_OK)
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(
- IntakeIssueSerializer(intake_issue).data,
- status=status.HTTP_200_OK,
+ IntakeIssueSerializer(intake_issue).data, status=status.HTTP_200_OK
)
def delete(self, request, slug, project_id, issue_id):
@@ -374,10 +324,7 @@ class IntakeIssueAPIEndpoint(BaseAPIView):
workspace__slug=slug, project_id=project_id
).first()
- project = Project.objects.get(
- workspace__slug=slug,
- pk=project_id,
- )
+ project = Project.objects.get(workspace__slug=slug, pk=project_id)
# Intake view
if intake is None and not project.intake_view:
diff --git a/apiserver/plane/api/views/issue.py b/apiserver/plane/api/views/issue.py
index 26945a766..df7b9aec2 100644
--- a/apiserver/plane/api/views/issue.py
+++ b/apiserver/plane/api/views/issue.py
@@ -73,9 +73,7 @@ class WorkspaceIssueAPIEndpoint(BaseAPIView):
def get_queryset(self):
return (
Issue.issue_objects.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -91,14 +89,10 @@ class WorkspaceIssueAPIEndpoint(BaseAPIView):
.order_by(self.kwargs.get("order_by", "-created_at"))
).distinct()
- def get(
- self, request, slug, project__identifier=None, issue__identifier=None
- ):
+ def get(self, request, slug, project__identifier=None, issue__identifier=None):
if issue__identifier and project__identifier:
issue = Issue.issue_objects.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -108,11 +102,7 @@ class WorkspaceIssueAPIEndpoint(BaseAPIView):
sequence_id=issue__identifier,
)
return Response(
- IssueSerializer(
- issue,
- fields=self.fields,
- expand=self.expand,
- ).data,
+ IssueSerializer(issue, fields=self.fields, expand=self.expand).data,
status=status.HTTP_200_OK,
)
@@ -126,17 +116,13 @@ class IssueAPIEndpoint(BaseAPIView):
model = Issue
webhook_event = "issue"
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
serializer_class = IssueSerializer
def get_queryset(self):
return (
Issue.issue_objects.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -164,41 +150,25 @@ class IssueAPIEndpoint(BaseAPIView):
project_id=project_id,
)
return Response(
- IssueSerializer(
- issue,
- fields=self.fields,
- expand=self.expand,
- ).data,
+ IssueSerializer(issue, fields=self.fields, expand=self.expand).data,
status=status.HTTP_200_OK,
)
if pk:
issue = Issue.issue_objects.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
).get(workspace__slug=slug, project_id=project_id, pk=pk)
return Response(
- IssueSerializer(
- issue,
- fields=self.fields,
- expand=self.expand,
- ).data,
+ IssueSerializer(issue, fields=self.fields, expand=self.expand).data,
status=status.HTTP_200_OK,
)
# Custom ordering for priority and state
priority_order = ["urgent", "high", "medium", "low", "none"]
- state_order = [
- "backlog",
- "unstarted",
- "started",
- "completed",
- "cancelled",
- ]
+ state_order = ["backlog", "unstarted", "started", "completed", "cancelled"]
order_by_param = request.GET.get("order_by", "-created_at")
@@ -231,9 +201,7 @@ class IssueAPIEndpoint(BaseAPIView):
# Priority Ordering
if order_by_param == "priority" or order_by_param == "-priority":
priority_order = (
- priority_order
- if order_by_param == "priority"
- else priority_order[::-1]
+ priority_order if order_by_param == "priority" else priority_order[::-1]
)
issue_queryset = issue_queryset.annotate(
priority_order=Case(
@@ -281,9 +249,7 @@ class IssueAPIEndpoint(BaseAPIView):
else order_by_param
)
).order_by(
- "-max_values"
- if order_by_param.startswith("-")
- else "max_values"
+ "-max_values" if order_by_param.startswith("-") else "max_values"
)
else:
issue_queryset = issue_queryset.order_by(order_by_param)
@@ -292,10 +258,7 @@ class IssueAPIEndpoint(BaseAPIView):
request=request,
queryset=(issue_queryset),
on_results=lambda issues: IssueSerializer(
- issues,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ issues, many=True, fields=self.fields, expand=self.expand
).data,
)
@@ -339,22 +302,16 @@ class IssueAPIEndpoint(BaseAPIView):
serializer.save()
# Refetch the issue
issue = Issue.objects.filter(
- workspace__slug=slug,
- project_id=project_id,
- pk=serializer.data["id"],
+ workspace__slug=slug, project_id=project_id, pk=serializer.data["id"]
).first()
issue.created_at = request.data.get("created_at", timezone.now())
- issue.created_by_id = request.data.get(
- "created_by", request.user.id
- )
+ issue.created_by_id = request.data.get("created_by", request.user.id)
issue.save(update_fields=["created_at", "created_by"])
# Track the issue
issue_activity.delay(
type="issue.activity.created",
- requested_data=json.dumps(
- self.request.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(self.request.data, cls=DjangoJSONEncoder),
actor_id=str(request.user.id),
issue_id=str(serializer.data.get("id", None)),
project_id=str(project_id),
@@ -391,9 +348,7 @@ class IssueAPIEndpoint(BaseAPIView):
# Get the requested data, encode it as django object and pass it
# to serializer to validation
- requested_data = json.dumps(
- self.request.data, cls=DjangoJSONEncoder
- )
+ requested_data = json.dumps(self.request.data, cls=DjangoJSONEncoder)
serializer = IssueSerializer(
issue,
data=request.data,
@@ -451,9 +406,7 @@ class IssueAPIEndpoint(BaseAPIView):
# If any of the created_at or created_by is present, update
# the issue with the provided data, else return with the
# default states given.
- issue.created_at = request.data.get(
- "created_at", timezone.now()
- )
+ issue.created_at = request.data.get("created_at", timezone.now())
issue.created_by_id = request.data.get(
"created_by", request.user.id
)
@@ -470,12 +423,8 @@ class IssueAPIEndpoint(BaseAPIView):
current_instance=None,
epoch=int(timezone.now().timestamp()),
)
- return Response(
- serializer.data, status=status.HTTP_201_CREATED
- )
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.data, status=status.HTTP_201_CREATED)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(
{"error": "external_id and external_source are required"},
@@ -483,9 +432,7 @@ class IssueAPIEndpoint(BaseAPIView):
)
def patch(self, request, slug, project_id, pk=None):
- issue = Issue.objects.get(
- workspace__slug=slug, project_id=project_id, pk=pk
- )
+ issue = Issue.objects.get(workspace__slug=slug, project_id=project_id, pk=pk)
project = Project.objects.get(pk=project_id)
current_instance = json.dumps(
IssueSerializer(issue).data, cls=DjangoJSONEncoder
@@ -494,10 +441,7 @@ class IssueAPIEndpoint(BaseAPIView):
serializer = IssueSerializer(
issue,
data=request.data,
- context={
- "project_id": project_id,
- "workspace_id": project.workspace_id,
- },
+ context={"project_id": project_id, "workspace_id": project.workspace_id},
partial=True,
)
if serializer.is_valid():
@@ -535,9 +479,7 @@ class IssueAPIEndpoint(BaseAPIView):
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, slug, project_id, pk=None):
- issue = Issue.objects.get(
- workspace__slug=slug, project_id=project_id, pk=pk
- )
+ issue = Issue.objects.get(workspace__slug=slug, project_id=project_id, pk=pk)
if issue.created_by_id != request.user.id and (
not ProjectMember.objects.filter(
workspace__slug=slug,
@@ -576,9 +518,7 @@ class LabelAPIEndpoint(BaseAPIView):
serializer_class = LabelSerializer
model = Label
- permission_classes = [
- ProjectMemberPermission,
- ]
+ permission_classes = [ProjectMemberPermission]
def get_queryset(self):
return (
@@ -625,12 +565,8 @@ class LabelAPIEndpoint(BaseAPIView):
)
serializer.save(project_id=project_id)
- return Response(
- serializer.data, status=status.HTTP_201_CREATED
- )
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.data, status=status.HTTP_201_CREATED)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except IntegrityError:
label = Label.objects.filter(
workspace__slug=slug,
@@ -651,18 +587,11 @@ class LabelAPIEndpoint(BaseAPIView):
request=request,
queryset=(self.get_queryset()),
on_results=lambda labels: LabelSerializer(
- labels,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ labels, many=True, fields=self.fields, expand=self.expand
).data,
)
label = self.get_queryset().get(pk=pk)
- serializer = LabelSerializer(
- label,
- fields=self.fields,
- expand=self.expand,
- )
+ serializer = LabelSerializer(label, fields=self.fields, expand=self.expand)
return Response(serializer.data, status=status.HTTP_200_OK)
def patch(self, request, slug, project_id, pk=None):
@@ -705,9 +634,7 @@ class IssueLinkAPIEndpoint(BaseAPIView):
"""
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
model = IssueLink
serializer_class = IssueLinkSerializer
@@ -730,46 +657,32 @@ class IssueLinkAPIEndpoint(BaseAPIView):
if pk is None:
issue_links = self.get_queryset()
serializer = IssueLinkSerializer(
- issue_links,
- fields=self.fields,
- expand=self.expand,
+ issue_links, fields=self.fields, expand=self.expand
)
return self.paginate(
request=request,
queryset=(self.get_queryset()),
on_results=lambda issue_links: IssueLinkSerializer(
- issue_links,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ issue_links, many=True, fields=self.fields, expand=self.expand
).data,
)
issue_link = self.get_queryset().get(pk=pk)
serializer = IssueLinkSerializer(
- issue_link,
- fields=self.fields,
- expand=self.expand,
+ issue_link, fields=self.fields, expand=self.expand
)
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request, slug, project_id, issue_id):
serializer = IssueLinkSerializer(data=request.data)
if serializer.is_valid():
- serializer.save(
- project_id=project_id,
- issue_id=issue_id,
- )
+ serializer.save(project_id=project_id, issue_id=issue_id)
link = IssueLink.objects.get(pk=serializer.data["id"])
- link.created_by_id = request.data.get(
- "created_by", request.user.id
- )
+ link.created_by_id = request.data.get("created_by", request.user.id)
link.save(update_fields=["created_by"])
issue_activity.delay(
type="link.activity.created",
- requested_data=json.dumps(
- serializer.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(serializer.data, cls=DjangoJSONEncoder),
issue_id=str(self.kwargs.get("issue_id")),
project_id=str(self.kwargs.get("project_id")),
actor_id=str(link.created_by_id),
@@ -781,19 +694,13 @@ class IssueLinkAPIEndpoint(BaseAPIView):
def patch(self, request, slug, project_id, issue_id, pk):
issue_link = IssueLink.objects.get(
- workspace__slug=slug,
- project_id=project_id,
- issue_id=issue_id,
- pk=pk,
+ workspace__slug=slug, project_id=project_id, issue_id=issue_id, pk=pk
)
requested_data = json.dumps(request.data, cls=DjangoJSONEncoder)
current_instance = json.dumps(
- IssueLinkSerializer(issue_link).data,
- cls=DjangoJSONEncoder,
- )
- serializer = IssueLinkSerializer(
- issue_link, data=request.data, partial=True
+ IssueLinkSerializer(issue_link).data, cls=DjangoJSONEncoder
)
+ serializer = IssueLinkSerializer(issue_link, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
issue_activity.delay(
@@ -810,14 +717,10 @@ class IssueLinkAPIEndpoint(BaseAPIView):
def delete(self, request, slug, project_id, issue_id, pk):
issue_link = IssueLink.objects.get(
- workspace__slug=slug,
- project_id=project_id,
- issue_id=issue_id,
- pk=pk,
+ workspace__slug=slug, project_id=project_id, issue_id=issue_id, pk=pk
)
current_instance = json.dumps(
- IssueLinkSerializer(issue_link).data,
- cls=DjangoJSONEncoder,
+ IssueLinkSerializer(issue_link).data, cls=DjangoJSONEncoder
)
issue_activity.delay(
type="link.activity.deleted",
@@ -842,15 +745,11 @@ class IssueCommentAPIEndpoint(BaseAPIView):
serializer_class = IssueCommentSerializer
model = IssueComment
webhook_event = "issue_comment"
- permission_classes = [
- ProjectLitePermission,
- ]
+ permission_classes = [ProjectLitePermission]
def get_queryset(self):
return (
- IssueComment.objects.filter(
- workspace__slug=self.kwargs.get("slug")
- )
+ IssueComment.objects.filter(workspace__slug=self.kwargs.get("slug"))
.filter(project_id=self.kwargs.get("project_id"))
.filter(issue_id=self.kwargs.get("issue_id"))
.filter(
@@ -877,19 +776,14 @@ class IssueCommentAPIEndpoint(BaseAPIView):
if pk:
issue_comment = self.get_queryset().get(pk=pk)
serializer = IssueCommentSerializer(
- issue_comment,
- fields=self.fields,
- expand=self.expand,
+ issue_comment, fields=self.fields, expand=self.expand
)
return Response(serializer.data, status=status.HTTP_200_OK)
return self.paginate(
request=request,
queryset=(self.get_queryset()),
on_results=lambda issue_comment: IssueCommentSerializer(
- issue_comment,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ issue_comment, many=True, fields=self.fields, expand=self.expand
).data,
)
@@ -922,17 +816,11 @@ class IssueCommentAPIEndpoint(BaseAPIView):
serializer = IssueCommentSerializer(data=request.data)
if serializer.is_valid():
serializer.save(
- project_id=project_id,
- issue_id=issue_id,
- actor=request.user,
- )
- issue_comment = IssueComment.objects.get(
- pk=serializer.data.get("id")
+ project_id=project_id, issue_id=issue_id, actor=request.user
)
+ issue_comment = IssueComment.objects.get(pk=serializer.data.get("id"))
# Update the created_at and the created_by and save the comment
- issue_comment.created_at = request.data.get(
- "created_at", timezone.now()
- )
+ issue_comment.created_at = request.data.get("created_at", timezone.now())
issue_comment.created_by_id = request.data.get(
"created_by", request.user.id
)
@@ -940,9 +828,7 @@ class IssueCommentAPIEndpoint(BaseAPIView):
issue_activity.delay(
type="comment.activity.created",
- requested_data=json.dumps(
- serializer.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(serializer.data, cls=DjangoJSONEncoder),
actor_id=str(issue_comment.created_by_id),
issue_id=str(self.kwargs.get("issue_id")),
project_id=str(self.kwargs.get("project_id")),
@@ -954,24 +840,17 @@ class IssueCommentAPIEndpoint(BaseAPIView):
def patch(self, request, slug, project_id, issue_id, pk):
issue_comment = IssueComment.objects.get(
- workspace__slug=slug,
- project_id=project_id,
- issue_id=issue_id,
- pk=pk,
+ workspace__slug=slug, project_id=project_id, issue_id=issue_id, pk=pk
)
requested_data = json.dumps(self.request.data, cls=DjangoJSONEncoder)
current_instance = json.dumps(
- IssueCommentSerializer(issue_comment).data,
- cls=DjangoJSONEncoder,
+ IssueCommentSerializer(issue_comment).data, cls=DjangoJSONEncoder
)
# Validation check if the issue already exists
if (
request.data.get("external_id")
- and (
- issue_comment.external_id
- != str(request.data.get("external_id"))
- )
+ and (issue_comment.external_id != str(request.data.get("external_id")))
and IssueComment.objects.filter(
project_id=project_id,
workspace__slug=slug,
@@ -1008,14 +887,10 @@ class IssueCommentAPIEndpoint(BaseAPIView):
def delete(self, request, slug, project_id, issue_id, pk):
issue_comment = IssueComment.objects.get(
- workspace__slug=slug,
- project_id=project_id,
- issue_id=issue_id,
- pk=pk,
+ workspace__slug=slug, project_id=project_id, issue_id=issue_id, pk=pk
)
current_instance = json.dumps(
- IssueCommentSerializer(issue_comment).data,
- cls=DjangoJSONEncoder,
+ IssueCommentSerializer(issue_comment).data, cls=DjangoJSONEncoder
)
issue_comment.delete()
issue_activity.delay(
@@ -1031,9 +906,7 @@ class IssueCommentAPIEndpoint(BaseAPIView):
class IssueActivityAPIEndpoint(BaseAPIView):
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
def get(self, request, slug, project_id, issue_id, pk=None):
issue_activities = (
@@ -1058,19 +931,14 @@ class IssueActivityAPIEndpoint(BaseAPIView):
request=request,
queryset=(issue_activities),
on_results=lambda issue_activity: IssueActivitySerializer(
- issue_activity,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ issue_activity, many=True, fields=self.fields, expand=self.expand
).data,
)
class IssueAttachmentEndpoint(BaseAPIView):
serializer_class = IssueAttachmentSerializer
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
model = FileAsset
parser_classes = (MultiPartParser, FormParser)
@@ -1109,10 +977,7 @@ class IssueAttachmentEndpoint(BaseAPIView):
actor_id=str(self.request.user.id),
issue_id=str(self.kwargs.get("issue_id", None)),
project_id=str(self.kwargs.get("project_id", None)),
- current_instance=json.dumps(
- serializer.data,
- cls=DjangoJSONEncoder,
- ),
+ current_instance=json.dumps(serializer.data, cls=DjangoJSONEncoder),
epoch=int(timezone.now().timestamp()),
notification=True,
origin=request.META.get("HTTP_ORIGIN"),
diff --git a/apiserver/plane/api/views/member.py b/apiserver/plane/api/views/member.py
index d6e5fed0c..954ee030b 100644
--- a/apiserver/plane/api/views/member.py
+++ b/apiserver/plane/api/views/member.py
@@ -13,24 +13,14 @@ from rest_framework import status
# Module imports
from .base import BaseAPIView
from plane.api.serializers import UserLiteSerializer
-from plane.db.models import (
- User,
- Workspace,
- Project,
- WorkspaceMember,
- ProjectMember,
-)
+from plane.db.models import User, Workspace, Project, WorkspaceMember, ProjectMember
-from plane.app.permissions import (
- ProjectMemberPermission,
-)
+from plane.app.permissions import ProjectMemberPermission
# API endpoint to get and insert users inside the workspace
class ProjectMemberAPIEndpoint(BaseAPIView):
- permission_classes = [
- ProjectMemberPermission,
- ]
+ permission_classes = [ProjectMemberPermission]
# Get all the users that are present inside the workspace
def get(self, request, slug, project_id):
@@ -48,10 +38,7 @@ class ProjectMemberAPIEndpoint(BaseAPIView):
# Get all the users that are present inside the workspace
users = UserLiteSerializer(
- User.objects.filter(
- id__in=project_members,
- ),
- many=True,
+ User.objects.filter(id__in=project_members), many=True
).data
return Response(users, status=status.HTTP_200_OK)
@@ -78,8 +65,7 @@ class ProjectMemberAPIEndpoint(BaseAPIView):
validate_email(email)
except ValidationError:
return Response(
- {"error": "Invalid email provided"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Invalid email provided"}, status=status.HTTP_400_BAD_REQUEST
)
workspace = Workspace.objects.filter(slug=slug).first()
@@ -108,9 +94,7 @@ class ProjectMemberAPIEndpoint(BaseAPIView):
).first()
if project_member:
return Response(
- {
- "error": "User is already part of the workspace and project"
- },
+ {"error": "User is already part of the workspace and project"},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -131,18 +115,14 @@ class ProjectMemberAPIEndpoint(BaseAPIView):
# Create a workspace member for the user if not already a member
if not workspace_member:
workspace_member = WorkspaceMember.objects.create(
- workspace=workspace,
- member=user,
- role=request.data.get("role", 5),
+ workspace=workspace, member=user, role=request.data.get("role", 5)
)
workspace_member.save()
# Create a project member for the user if not already a member
if not project_member:
project_member = ProjectMember.objects.create(
- project=project,
- member=user,
- role=request.data.get("role", 5),
+ project=project, member=user, role=request.data.get("role", 5)
)
project_member.save()
@@ -150,4 +130,3 @@ class ProjectMemberAPIEndpoint(BaseAPIView):
user_data = UserLiteSerializer(user).data
return Response(user_data, status=status.HTTP_201_CREATED)
-
diff --git a/apiserver/plane/api/views/module.py b/apiserver/plane/api/views/module.py
index c8a8c1716..9e4f4143c 100644
--- a/apiserver/plane/api/views/module.py
+++ b/apiserver/plane/api/views/module.py
@@ -43,9 +43,7 @@ class ModuleAPIEndpoint(BaseAPIView):
"""
model = Module
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
serializer_class = ModuleSerializer
webhook_event = "module"
@@ -60,9 +58,7 @@ class ModuleAPIEndpoint(BaseAPIView):
.prefetch_related(
Prefetch(
"link_module",
- queryset=ModuleLink.objects.select_related(
- "module", "created_by"
- ),
+ queryset=ModuleLink.objects.select_related("module", "created_by"),
)
)
.annotate(
@@ -74,7 +70,7 @@ class ModuleAPIEndpoint(BaseAPIView):
issue_module__deleted_at__isnull=True,
),
distinct=True,
- ),
+ )
)
.annotate(
completed_issues=Count(
@@ -143,10 +139,7 @@ class ModuleAPIEndpoint(BaseAPIView):
project = Project.objects.get(pk=project_id, workspace__slug=slug)
serializer = ModuleSerializer(
data=request.data,
- context={
- "project_id": project_id,
- "workspace_id": project.workspace_id,
- },
+ context={"project_id": project_id, "workspace_id": project.workspace_id},
)
if serializer.is_valid():
if (
@@ -189,9 +182,7 @@ class ModuleAPIEndpoint(BaseAPIView):
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def patch(self, request, slug, project_id, pk):
- module = Module.objects.get(
- pk=pk, project_id=project_id, workspace__slug=slug
- )
+ module = Module.objects.get(pk=pk, project_id=project_id, workspace__slug=slug)
current_instance = json.dumps(
ModuleSerializer(module).data, cls=DjangoJSONEncoder
@@ -203,10 +194,7 @@ class ModuleAPIEndpoint(BaseAPIView):
status=status.HTTP_400_BAD_REQUEST,
)
serializer = ModuleSerializer(
- module,
- data=request.data,
- context={"project_id": project_id},
- partial=True,
+ module, data=request.data, context={"project_id": project_id}, partial=True
)
if serializer.is_valid():
if (
@@ -246,33 +234,21 @@ class ModuleAPIEndpoint(BaseAPIView):
def get(self, request, slug, project_id, pk=None):
if pk:
- queryset = (
- self.get_queryset().filter(archived_at__isnull=True).get(pk=pk)
- )
+ queryset = self.get_queryset().filter(archived_at__isnull=True).get(pk=pk)
data = ModuleSerializer(
- queryset,
- fields=self.fields,
- expand=self.expand,
+ queryset, fields=self.fields, expand=self.expand
).data
- return Response(
- data,
- status=status.HTTP_200_OK,
- )
+ return Response(data, status=status.HTTP_200_OK)
return self.paginate(
request=request,
queryset=(self.get_queryset().filter(archived_at__isnull=True)),
on_results=lambda modules: ModuleSerializer(
- modules,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ modules, many=True, fields=self.fields, expand=self.expand
).data,
)
def delete(self, request, slug, project_id, pk):
- module = Module.objects.get(
- workspace__slug=slug, project_id=project_id, pk=pk
- )
+ module = Module.objects.get(workspace__slug=slug, project_id=project_id, pk=pk)
if module.created_by_id != request.user.id and (
not ProjectMember.objects.filter(
workspace__slug=slug,
@@ -288,9 +264,7 @@ class ModuleAPIEndpoint(BaseAPIView):
)
module_issues = list(
- ModuleIssue.objects.filter(module_id=pk).values_list(
- "issue", flat=True
- )
+ ModuleIssue.objects.filter(module_id=pk).values_list("issue", flat=True)
)
issue_activity.delay(
type="module.activity.deleted",
@@ -304,24 +278,15 @@ class ModuleAPIEndpoint(BaseAPIView):
actor_id=str(request.user.id),
issue_id=None,
project_id=str(project_id),
- current_instance=json.dumps(
- {
- "module_name": str(module.name),
- }
- ),
+ current_instance=json.dumps({"module_name": str(module.name)}),
epoch=int(timezone.now().timestamp()),
)
module.delete()
# Delete the module issues
- ModuleIssue.objects.filter(
- module=pk,
- project_id=project_id,
- ).delete()
+ ModuleIssue.objects.filter(module=pk, project_id=project_id).delete()
# Delete the user favorite module
UserFavorite.objects.filter(
- entity_type="module",
- entity_identifier=pk,
- project_id=project_id,
+ entity_type="module", entity_identifier=pk, project_id=project_id
).delete()
return Response(status=status.HTTP_204_NO_CONTENT)
@@ -338,16 +303,12 @@ class ModuleIssueAPIEndpoint(BaseAPIView):
webhook_event = "module_issue"
bulk = True
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
def get_queryset(self):
return (
ModuleIssue.objects.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("issue")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("issue"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -374,13 +335,10 @@ class ModuleIssueAPIEndpoint(BaseAPIView):
order_by = request.GET.get("order_by", "created_at")
issues = (
Issue.issue_objects.filter(
- issue_module__module_id=module_id,
- issue_module__deleted_at__isnull=True,
+ issue_module__module_id=module_id, issue_module__deleted_at__isnull=True
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -415,10 +373,7 @@ class ModuleIssueAPIEndpoint(BaseAPIView):
request=request,
queryset=(issues),
on_results=lambda issues: IssueSerializer(
- issues,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ issues, many=True, fields=self.fields, expand=self.expand
).data,
)
@@ -426,8 +381,7 @@ class ModuleIssueAPIEndpoint(BaseAPIView):
issues = request.data.get("issues", [])
if not len(issues):
return Response(
- {"error": "Issues are required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Issues are required"}, status=status.HTTP_400_BAD_REQUEST
)
module = Module.objects.get(
workspace__slug=slug, project_id=project_id, pk=module_id
@@ -474,16 +428,10 @@ class ModuleIssueAPIEndpoint(BaseAPIView):
)
ModuleIssue.objects.bulk_create(
- record_to_create,
- batch_size=10,
- ignore_conflicts=True,
+ record_to_create, batch_size=10, ignore_conflicts=True
)
- ModuleIssue.objects.bulk_update(
- records_to_update,
- ["module"],
- batch_size=10,
- )
+ ModuleIssue.objects.bulk_update(records_to_update, ["module"], batch_size=10)
# Capture Issue Activity
issue_activity.delay(
@@ -519,10 +467,7 @@ class ModuleIssueAPIEndpoint(BaseAPIView):
issue_activity.delay(
type="module.activity.deleted",
requested_data=json.dumps(
- {
- "module_id": str(module_id),
- "issues": [str(module_issue.issue_id)],
- }
+ {"module_id": str(module_id), "issues": [str(module_issue.issue_id)]}
),
actor_id=str(request.user.id),
issue_id=str(issue_id),
@@ -534,9 +479,7 @@ class ModuleIssueAPIEndpoint(BaseAPIView):
class ModuleArchiveUnarchiveAPIEndpoint(BaseAPIView):
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
def get_queryset(self):
return (
@@ -550,9 +493,7 @@ class ModuleArchiveUnarchiveAPIEndpoint(BaseAPIView):
.prefetch_related(
Prefetch(
"link_module",
- queryset=ModuleLink.objects.select_related(
- "module", "created_by"
- ),
+ queryset=ModuleLink.objects.select_related("module", "created_by"),
)
)
.annotate(
@@ -564,7 +505,7 @@ class ModuleArchiveUnarchiveAPIEndpoint(BaseAPIView):
issue_module__deleted_at__isnull=True,
),
distinct=True,
- ),
+ )
)
.annotate(
completed_issues=Count(
@@ -634,22 +575,15 @@ class ModuleArchiveUnarchiveAPIEndpoint(BaseAPIView):
request=request,
queryset=(self.get_queryset()),
on_results=lambda modules: ModuleSerializer(
- modules,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ modules, many=True, fields=self.fields, expand=self.expand
).data,
)
def post(self, request, slug, project_id, pk):
- module = Module.objects.get(
- pk=pk, project_id=project_id, workspace__slug=slug
- )
+ module = Module.objects.get(pk=pk, project_id=project_id, workspace__slug=slug)
if module.status not in ["completed", "cancelled"]:
return Response(
- {
- "error": "Only completed or cancelled modules can be archived"
- },
+ {"error": "Only completed or cancelled modules can be archived"},
status=status.HTTP_400_BAD_REQUEST,
)
module.archived_at = timezone.now()
@@ -663,9 +597,7 @@ class ModuleArchiveUnarchiveAPIEndpoint(BaseAPIView):
return Response(status=status.HTTP_204_NO_CONTENT)
def delete(self, request, slug, project_id, pk):
- module = Module.objects.get(
- pk=pk, project_id=project_id, workspace__slug=slug
- )
+ module = Module.objects.get(pk=pk, project_id=project_id, workspace__slug=slug)
module.archived_at = None
module.save()
return Response(status=status.HTTP_204_NO_CONTENT)
diff --git a/apiserver/plane/api/views/project.py b/apiserver/plane/api/views/project.py
index 92a924e11..c52caac0f 100644
--- a/apiserver/plane/api/views/project.py
+++ b/apiserver/plane/api/views/project.py
@@ -39,9 +39,7 @@ class ProjectAPIEndpoint(BaseAPIView):
model = Project
webhook_event = "project"
- permission_classes = [
- ProjectBasePermission,
- ]
+ permission_classes = [ProjectBasePermission]
def get_queryset(self):
return (
@@ -54,10 +52,7 @@ class ProjectAPIEndpoint(BaseAPIView):
| Q(network=2)
)
.select_related(
- "workspace",
- "workspace__owner",
- "default_assignee",
- "project_lead",
+ "workspace", "workspace__owner", "default_assignee", "project_lead"
)
.annotate(
is_member=Exists(
@@ -71,9 +66,7 @@ class ProjectAPIEndpoint(BaseAPIView):
)
.annotate(
total_members=ProjectMember.objects.filter(
- project_id=OuterRef("id"),
- member__is_bot=False,
- is_active=True,
+ project_id=OuterRef("id"), member__is_bot=False, is_active=True
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
@@ -125,8 +118,7 @@ class ProjectAPIEndpoint(BaseAPIView):
Prefetch(
"project_projectmember",
queryset=ProjectMember.objects.filter(
- workspace__slug=slug,
- is_active=True,
+ workspace__slug=slug, is_active=True
).select_related("member"),
)
)
@@ -136,18 +128,11 @@ class ProjectAPIEndpoint(BaseAPIView):
request=request,
queryset=(projects),
on_results=lambda projects: ProjectSerializer(
- projects,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ projects, many=True, fields=self.fields, expand=self.expand
).data,
)
project = self.get_queryset().get(workspace__slug=slug, pk=pk)
- serializer = ProjectSerializer(
- project,
- fields=self.fields,
- expand=self.expand,
- )
+ serializer = ProjectSerializer(project, fields=self.fields, expand=self.expand)
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request, slug):
@@ -161,14 +146,11 @@ class ProjectAPIEndpoint(BaseAPIView):
# Add the user as Administrator to the project
_ = ProjectMember.objects.create(
- project_id=serializer.data["id"],
- member=request.user,
- role=20,
+ project_id=serializer.data["id"], member=request.user, role=20
)
# Also create the issue property for the user
_ = IssueUserProperty.objects.create(
- project_id=serializer.data["id"],
- user=request.user,
+ project_id=serializer.data["id"], user=request.user
)
if serializer.data["project_lead"] is not None and str(
@@ -236,11 +218,7 @@ class ProjectAPIEndpoint(BaseAPIView):
]
)
- project = (
- self.get_queryset()
- .filter(pk=serializer.data["id"])
- .first()
- )
+ project = self.get_queryset().filter(pk=serializer.data["id"]).first()
# Model activity
model_activity.delay(
@@ -254,13 +232,8 @@ class ProjectAPIEndpoint(BaseAPIView):
)
serializer = ProjectSerializer(project)
- return Response(
- serializer.data, status=status.HTTP_201_CREATED
- )
- return Response(
- serializer.errors,
- status=status.HTTP_400_BAD_REQUEST,
- )
+ 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(
@@ -269,8 +242,7 @@ class ProjectAPIEndpoint(BaseAPIView):
)
except Workspace.DoesNotExist:
return Response(
- {"error": "Workspace does not exist"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Workspace does not exist"}, status=status.HTTP_404_NOT_FOUND
)
except ValidationError:
return Response(
@@ -298,10 +270,7 @@ class ProjectAPIEndpoint(BaseAPIView):
serializer = ProjectSerializer(
project,
- data={
- **request.data,
- "intake_view": intake_view,
- },
+ data={**request.data, "intake_view": intake_view},
context={"workspace_id": workspace.id},
partial=True,
)
@@ -310,8 +279,7 @@ class ProjectAPIEndpoint(BaseAPIView):
serializer.save()
if serializer.data["intake_view"]:
intake = Intake.objects.filter(
- project=project,
- is_default=True,
+ project=project, is_default=True
).first()
if not intake:
Intake.objects.create(
@@ -330,11 +298,7 @@ class ProjectAPIEndpoint(BaseAPIView):
is_triage=True,
)
- project = (
- self.get_queryset()
- .filter(pk=serializer.data["id"])
- .first()
- )
+ project = self.get_queryset().filter(pk=serializer.data["id"]).first()
model_activity.delay(
model_name="project",
@@ -348,9 +312,7 @@ class ProjectAPIEndpoint(BaseAPIView):
serializer = ProjectSerializer(project)
return Response(serializer.data, status=status.HTTP_200_OK)
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except IntegrityError as e:
if "already exists" in str(e):
return Response(
@@ -359,8 +321,7 @@ class ProjectAPIEndpoint(BaseAPIView):
)
except (Project.DoesNotExist, Workspace.DoesNotExist):
return Response(
- {"error": "Project does not exist"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Project does not exist"}, status=status.HTTP_404_NOT_FOUND
)
except ValidationError:
return Response(
@@ -372,28 +333,20 @@ class ProjectAPIEndpoint(BaseAPIView):
project = Project.objects.get(pk=pk, workspace__slug=slug)
# Delete the user favorite cycle
UserFavorite.objects.filter(
- entity_type="project",
- entity_identifier=pk,
- project_id=pk,
+ entity_type="project", entity_identifier=pk, project_id=pk
).delete()
project.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
class ProjectArchiveUnarchiveAPIEndpoint(BaseAPIView):
-
- permission_classes = [
- ProjectBasePermission,
- ]
+ permission_classes = [ProjectBasePermission]
def post(self, request, slug, project_id):
project = Project.objects.get(pk=project_id, workspace__slug=slug)
project.archived_at = timezone.now()
project.save()
- UserFavorite.objects.filter(
- workspace__slug=slug,
- project=project_id,
- ).delete()
+ UserFavorite.objects.filter(workspace__slug=slug, project=project_id).delete()
return Response(status=status.HTTP_204_NO_CONTENT)
def delete(self, request, slug, project_id):
diff --git a/apiserver/plane/api/views/state.py b/apiserver/plane/api/views/state.py
index dd239754c..0fbbd222a 100644
--- a/apiserver/plane/api/views/state.py
+++ b/apiserver/plane/api/views/state.py
@@ -16,9 +16,7 @@ from .base import BaseAPIView
class StateAPIEndpoint(BaseAPIView):
serializer_class = StateSerializer
model = State
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
def get_queryset(self):
return (
@@ -67,9 +65,7 @@ class StateAPIEndpoint(BaseAPIView):
serializer.save(project_id=project_id)
return Response(serializer.data, status=status.HTTP_200_OK)
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except IntegrityError:
state = State.objects.filter(
workspace__slug=slug,
@@ -96,19 +92,13 @@ class StateAPIEndpoint(BaseAPIView):
request=request,
queryset=(self.get_queryset()),
on_results=lambda states: StateSerializer(
- states,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ states, many=True, fields=self.fields, expand=self.expand
).data,
)
def delete(self, request, slug, project_id, state_id):
state = State.objects.get(
- is_triage=False,
- pk=state_id,
- project_id=project_id,
- workspace__slug=slug,
+ is_triage=False, pk=state_id, project_id=project_id, workspace__slug=slug
)
if state.default:
@@ -122,9 +112,7 @@ class StateAPIEndpoint(BaseAPIView):
if issue_exist:
return Response(
- {
- "error": "The state is not empty, only empty states can be deleted"
- },
+ {"error": "The state is not empty, only empty states can be deleted"},
status=status.HTTP_400_BAD_REQUEST,
)
diff --git a/apiserver/plane/app/middleware/api_authentication.py b/apiserver/plane/app/middleware/api_authentication.py
index 893df7f84..ddabb4132 100644
--- a/apiserver/plane/app/middleware/api_authentication.py
+++ b/apiserver/plane/app/middleware/api_authentication.py
@@ -25,10 +25,7 @@ class APIKeyAuthentication(authentication.BaseAuthentication):
def validate_api_token(self, token):
try:
api_token = APIToken.objects.get(
- Q(
- Q(expired_at__gt=timezone.now())
- | Q(expired_at__isnull=True)
- ),
+ Q(Q(expired_at__gt=timezone.now()) | Q(expired_at__isnull=True)),
token=token,
is_active=True,
)
diff --git a/apiserver/plane/app/permissions/__init__.py b/apiserver/plane/app/permissions/__init__.py
index e45388144..b7a095e74 100644
--- a/apiserver/plane/app/permissions/__init__.py
+++ b/apiserver/plane/app/permissions/__init__.py
@@ -12,4 +12,4 @@ from .project import (
ProjectMemberPermission,
ProjectLitePermission,
)
-from .base import allow_permission, ROLE
\ No newline at end of file
+from .base import allow_permission, ROLE
diff --git a/apiserver/plane/app/permissions/base.py b/apiserver/plane/app/permissions/base.py
index 06faeceb6..7ba12a2e2 100644
--- a/apiserver/plane/app/permissions/base.py
+++ b/apiserver/plane/app/permissions/base.py
@@ -5,6 +5,7 @@ from rest_framework import status
from enum import Enum
+
class ROLE(Enum):
ADMIN = 20
MEMBER = 15
@@ -15,7 +16,6 @@ def allow_permission(allowed_roles, level="PROJECT", creator=False, model=None):
def decorator(view_func):
@wraps(view_func)
def _wrapped_view(instance, request, *args, **kwargs):
-
# Check for creator if required
if creator and model:
obj = model.objects.filter(
@@ -26,8 +26,7 @@ def allow_permission(allowed_roles, level="PROJECT", creator=False, model=None):
# Convert allowed_roles to their values if they are enum members
allowed_role_values = [
- role.value if isinstance(role, ROLE) else role
- for role in allowed_roles
+ role.value if isinstance(role, ROLE) else role for role in allowed_roles
]
# Check role permissions
diff --git a/apiserver/plane/app/permissions/project.py b/apiserver/plane/app/permissions/project.py
index 11eab008b..470960fcc 100644
--- a/apiserver/plane/app/permissions/project.py
+++ b/apiserver/plane/app/permissions/project.py
@@ -18,9 +18,7 @@ class ProjectBasePermission(BasePermission):
## Safe Methods -> Handle the filtering logic in queryset
if request.method in SAFE_METHODS:
return WorkspaceMember.objects.filter(
- workspace__slug=view.workspace_slug,
- member=request.user,
- is_active=True,
+ workspace__slug=view.workspace_slug, member=request.user, is_active=True
).exists()
## Only workspace owners or admins can create the projects
@@ -50,9 +48,7 @@ class ProjectMemberPermission(BasePermission):
## Safe Methods -> Handle the filtering logic in queryset
if request.method in SAFE_METHODS:
return ProjectMember.objects.filter(
- workspace__slug=view.workspace_slug,
- member=request.user,
- is_active=True,
+ workspace__slug=view.workspace_slug, member=request.user, is_active=True
).exists()
## Only workspace owners or admins can create the projects
if request.method == "POST":
diff --git a/apiserver/plane/app/permissions/workspace.py b/apiserver/plane/app/permissions/workspace.py
index c2dcc9f95..8dc791c0c 100644
--- a/apiserver/plane/app/permissions/workspace.py
+++ b/apiserver/plane/app/permissions/workspace.py
@@ -50,9 +50,7 @@ class WorkspaceOwnerPermission(BasePermission):
return False
return WorkspaceMember.objects.filter(
- workspace__slug=view.workspace_slug,
- member=request.user,
- role=Admin,
+ workspace__slug=view.workspace_slug, member=request.user, role=Admin
).exists()
@@ -77,9 +75,7 @@ class WorkspaceEntityPermission(BasePermission):
## Safe Methods -> Handle the filtering logic in queryset
if request.method in SAFE_METHODS:
return WorkspaceMember.objects.filter(
- workspace__slug=view.workspace_slug,
- member=request.user,
- is_active=True,
+ workspace__slug=view.workspace_slug, member=request.user, is_active=True
).exists()
return WorkspaceMember.objects.filter(
@@ -96,9 +92,7 @@ class WorkspaceViewerPermission(BasePermission):
return False
return WorkspaceMember.objects.filter(
- member=request.user,
- workspace__slug=view.workspace_slug,
- is_active=True,
+ member=request.user, workspace__slug=view.workspace_slug, is_active=True
).exists()
@@ -108,7 +102,5 @@ class WorkspaceUserPermission(BasePermission):
return False
return WorkspaceMember.objects.filter(
- member=request.user,
- workspace__slug=view.workspace_slug,
- is_active=True,
+ member=request.user, workspace__slug=view.workspace_slug, is_active=True
).exists()
diff --git a/apiserver/plane/app/serializers/__init__.py b/apiserver/plane/app/serializers/__init__.py
index 2e2c91baa..2e7022688 100644
--- a/apiserver/plane/app/serializers/__init__.py
+++ b/apiserver/plane/app/serializers/__init__.py
@@ -36,9 +36,7 @@ from .project import (
ProjectMemberRoleSerializer,
)
from .state import StateSerializer, StateLiteSerializer
-from .view import (
- IssueViewSerializer,
-)
+from .view import IssueViewSerializer
from .cycle import (
CycleSerializer,
CycleIssueSerializer,
@@ -112,10 +110,7 @@ from .intake import (
from .analytic import AnalyticViewSerializer
-from .notification import (
- NotificationSerializer,
- UserNotificationPreferenceSerializer,
-)
+from .notification import NotificationSerializer, UserNotificationPreferenceSerializer
from .exporter import ExporterHistorySerializer
diff --git a/apiserver/plane/app/serializers/analytic.py b/apiserver/plane/app/serializers/analytic.py
index 9f3ee6d0a..13b24d14d 100644
--- a/apiserver/plane/app/serializers/analytic.py
+++ b/apiserver/plane/app/serializers/analytic.py
@@ -7,10 +7,7 @@ class AnalyticViewSerializer(BaseSerializer):
class Meta:
model = AnalyticView
fields = "__all__"
- read_only_fields = [
- "workspace",
- "query",
- ]
+ read_only_fields = ["workspace", "query"]
def create(self, validated_data):
query_params = validated_data.get("query_dict", {})
diff --git a/apiserver/plane/app/serializers/asset.py b/apiserver/plane/app/serializers/asset.py
index 136e2264b..560cd3538 100644
--- a/apiserver/plane/app/serializers/asset.py
+++ b/apiserver/plane/app/serializers/asset.py
@@ -6,9 +6,4 @@ class FileAssetSerializer(BaseSerializer):
class Meta:
model = FileAsset
fields = "__all__"
- read_only_fields = [
- "created_by",
- "updated_by",
- "created_at",
- "updated_at",
- ]
+ read_only_fields = ["created_by", "updated_by", "created_at", "updated_at"]
diff --git a/apiserver/plane/app/serializers/base.py b/apiserver/plane/app/serializers/base.py
index ed3201043..715ad6eae 100644
--- a/apiserver/plane/app/serializers/base.py
+++ b/apiserver/plane/app/serializers/base.py
@@ -178,15 +178,10 @@ class DynamicBaseSerializer(BaseSerializer):
response[expand] = exp_serializer.data
else:
# You might need to handle this case differently
- response[expand] = getattr(
- instance, f"{expand}_id", None
- )
+ response[expand] = getattr(instance, f"{expand}_id", None)
# Check if issue_attachments is in fields or expand
- if (
- "issue_attachments" in self.fields
- or "issue_attachments" in self.expand
- ):
+ if "issue_attachments" in self.fields or "issue_attachments" in self.expand:
# Import the model here to avoid circular imports
from plane.db.models import FileAsset
@@ -199,11 +194,9 @@ class DynamicBaseSerializer(BaseSerializer):
entity_type=FileAsset.EntityTypeContext.ISSUE_ATTACHMENT,
)
# Serialize issue_attachments and add them to the response
- response["issue_attachments"] = (
- IssueAttachmentLiteSerializer(
- issue_attachments, many=True
- ).data
- )
+ response["issue_attachments"] = IssueAttachmentLiteSerializer(
+ issue_attachments, many=True
+ ).data
else:
response["issue_attachments"] = []
diff --git a/apiserver/plane/app/serializers/cycle.py b/apiserver/plane/app/serializers/cycle.py
index 97fd47960..bf08de4fe 100644
--- a/apiserver/plane/app/serializers/cycle.py
+++ b/apiserver/plane/app/serializers/cycle.py
@@ -4,11 +4,7 @@ from rest_framework import serializers
# Module imports
from .base import BaseSerializer
from .issue import IssueStateSerializer
-from plane.db.models import (
- Cycle,
- CycleIssue,
- CycleUserProperties,
-)
+from plane.db.models import Cycle, CycleIssue, CycleUserProperties
class CycleWriteSerializer(BaseSerializer):
@@ -18,20 +14,13 @@ class CycleWriteSerializer(BaseSerializer):
and data.get("end_date", None) is not None
and data.get("start_date", None) > data.get("end_date", None)
):
- raise serializers.ValidationError(
- "Start date cannot exceed end date"
- )
+ raise serializers.ValidationError("Start date cannot exceed end date")
return data
class Meta:
model = Cycle
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- "owned_by",
- "archived_at",
- ]
+ read_only_fields = ["workspace", "project", "owned_by", "archived_at"]
class CycleSerializer(BaseSerializer):
@@ -87,18 +76,11 @@ class CycleIssueSerializer(BaseSerializer):
class Meta:
model = CycleIssue
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- "cycle",
- ]
+ read_only_fields = ["workspace", "project", "cycle"]
+
class CycleUserPropertiesSerializer(BaseSerializer):
class Meta:
model = CycleUserProperties
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- "cycle" "user",
- ]
+ read_only_fields = ["workspace", "project", "cycle" "user"]
diff --git a/apiserver/plane/app/serializers/draft.py b/apiserver/plane/app/serializers/draft.py
index e07e416a7..f30835263 100644
--- a/apiserver/plane/app/serializers/draft.py
+++ b/apiserver/plane/app/serializers/draft.py
@@ -22,16 +22,10 @@ from plane.db.models import (
class DraftIssueCreateSerializer(BaseSerializer):
# ids
state_id = serializers.PrimaryKeyRelatedField(
- source="state",
- queryset=State.objects.all(),
- required=False,
- allow_null=True,
+ source="state", queryset=State.objects.all(), required=False, allow_null=True
)
parent_id = serializers.PrimaryKeyRelatedField(
- source="parent",
- queryset=Issue.objects.all(),
- required=False,
- allow_null=True,
+ source="parent", queryset=Issue.objects.all(), required=False, allow_null=True
)
label_ids = serializers.ListField(
child=serializers.PrimaryKeyRelatedField(queryset=Label.objects.all()),
@@ -69,9 +63,7 @@ class DraftIssueCreateSerializer(BaseSerializer):
and data.get("target_date", None) is not None
and data.get("start_date", None) > data.get("target_date", None)
):
- raise serializers.ValidationError(
- "Start date cannot exceed target date"
- )
+ raise serializers.ValidationError("Start date cannot exceed target date")
return data
def create(self, validated_data):
@@ -86,9 +78,7 @@ class DraftIssueCreateSerializer(BaseSerializer):
# Create Issue
issue = DraftIssue.objects.create(
- **validated_data,
- workspace_id=workspace_id,
- project_id=project_id,
+ **validated_data, workspace_id=workspace_id, project_id=project_id
)
# Issue Audit Users
@@ -239,20 +229,11 @@ class DraftIssueCreateSerializer(BaseSerializer):
class DraftIssueSerializer(BaseSerializer):
# ids
cycle_id = serializers.PrimaryKeyRelatedField(read_only=True)
- module_ids = serializers.ListField(
- child=serializers.UUIDField(),
- required=False,
- )
+ module_ids = serializers.ListField(child=serializers.UUIDField(), required=False)
# Many to many
- label_ids = serializers.ListField(
- child=serializers.UUIDField(),
- required=False,
- )
- assignee_ids = serializers.ListField(
- child=serializers.UUIDField(),
- required=False,
- )
+ label_ids = serializers.ListField(child=serializers.UUIDField(), required=False)
+ assignee_ids = serializers.ListField(child=serializers.UUIDField(), required=False)
class Meta:
model = DraftIssue
@@ -286,7 +267,5 @@ class DraftIssueDetailSerializer(DraftIssueSerializer):
description_html = serializers.CharField()
class Meta(DraftIssueSerializer.Meta):
- fields = DraftIssueSerializer.Meta.fields + [
- "description_html",
- ]
+ fields = DraftIssueSerializer.Meta.fields + ["description_html"]
read_only_fields = fields
diff --git a/apiserver/plane/app/serializers/estimate.py b/apiserver/plane/app/serializers/estimate.py
index 8cb083ca5..b2d65ef8c 100644
--- a/apiserver/plane/app/serializers/estimate.py
+++ b/apiserver/plane/app/serializers/estimate.py
@@ -7,14 +7,10 @@ from rest_framework import serializers
class EstimateSerializer(BaseSerializer):
-
class Meta:
model = Estimate
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- ]
+ read_only_fields = ["workspace", "project"]
class EstimatePointSerializer(BaseSerializer):
@@ -23,19 +19,13 @@ class EstimatePointSerializer(BaseSerializer):
raise serializers.ValidationError("Estimate points are required")
value = data.get("value")
if value and len(value) > 20:
- raise serializers.ValidationError(
- "Value can't be more than 20 characters"
- )
+ raise serializers.ValidationError("Value can't be more than 20 characters")
return data
class Meta:
model = EstimatePoint
fields = "__all__"
- read_only_fields = [
- "estimate",
- "workspace",
- "project",
- ]
+ read_only_fields = ["estimate", "workspace", "project"]
class EstimateReadSerializer(BaseSerializer):
@@ -44,11 +34,7 @@ class EstimateReadSerializer(BaseSerializer):
class Meta:
model = Estimate
fields = "__all__"
- read_only_fields = [
- "points",
- "name",
- "description",
- ]
+ read_only_fields = ["points", "name", "description"]
class WorkspaceEstimateSerializer(BaseSerializer):
@@ -57,8 +43,4 @@ class WorkspaceEstimateSerializer(BaseSerializer):
class Meta:
model = Estimate
fields = "__all__"
- read_only_fields = [
- "points",
- "name",
- "description",
- ]
+ read_only_fields = ["points", "name", "description"]
diff --git a/apiserver/plane/app/serializers/exporter.py b/apiserver/plane/app/serializers/exporter.py
index 2dd850fd3..5c78cfa69 100644
--- a/apiserver/plane/app/serializers/exporter.py
+++ b/apiserver/plane/app/serializers/exporter.py
@@ -5,9 +5,7 @@ from .user import UserLiteSerializer
class ExporterHistorySerializer(BaseSerializer):
- initiated_by_detail = UserLiteSerializer(
- source="initiated_by", read_only=True
- )
+ initiated_by_detail = UserLiteSerializer(source="initiated_by", read_only=True)
class Meta:
model = ExporterHistory
diff --git a/apiserver/plane/app/serializers/favorite.py b/apiserver/plane/app/serializers/favorite.py
index 8e0beda10..940b8ee82 100644
--- a/apiserver/plane/app/serializers/favorite.py
+++ b/apiserver/plane/app/serializers/favorite.py
@@ -1,18 +1,9 @@
from rest_framework import serializers
-from plane.db.models import (
- UserFavorite,
- Cycle,
- Module,
- Issue,
- IssueView,
- Page,
- Project,
-)
+from plane.db.models import UserFavorite, Cycle, Module, Issue, IssueView, Page, Project
class ProjectFavoriteLiteSerializer(serializers.ModelSerializer):
-
class Meta:
model = Project
fields = ["id", "name", "logo_props"]
@@ -33,21 +24,18 @@ class PageFavoriteLiteSerializer(serializers.ModelSerializer):
class CycleFavoriteLiteSerializer(serializers.ModelSerializer):
-
class Meta:
model = Cycle
fields = ["id", "name", "logo_props", "project_id"]
class ModuleFavoriteLiteSerializer(serializers.ModelSerializer):
-
class Meta:
model = Module
fields = ["id", "name", "logo_props", "project_id"]
class ViewFavoriteSerializer(serializers.ModelSerializer):
-
class Meta:
model = IssueView
fields = ["id", "name", "logo_props", "project_id"]
@@ -89,9 +77,7 @@ class UserFavoriteSerializer(serializers.ModelSerializer):
entity_type = obj.entity_type
entity_identifier = obj.entity_identifier
- entity_model, entity_serializer = get_entity_model_and_serializer(
- entity_type
- )
+ entity_model, entity_serializer = get_entity_model_and_serializer(entity_type)
if entity_model and entity_serializer:
try:
entity = entity_model.objects.get(pk=entity_identifier)
diff --git a/apiserver/plane/app/serializers/importer.py b/apiserver/plane/app/serializers/importer.py
index c058994d6..8997f6392 100644
--- a/apiserver/plane/app/serializers/importer.py
+++ b/apiserver/plane/app/serializers/importer.py
@@ -7,13 +7,9 @@ from plane.db.models import Importer
class ImporterSerializer(BaseSerializer):
- initiated_by_detail = UserLiteSerializer(
- source="initiated_by", read_only=True
- )
+ initiated_by_detail = UserLiteSerializer(source="initiated_by", read_only=True)
project_detail = ProjectLiteSerializer(source="project", read_only=True)
- workspace_detail = WorkspaceLiteSerializer(
- source="workspace", read_only=True
- )
+ workspace_detail = WorkspaceLiteSerializer(source="workspace", read_only=True)
class Meta:
model = Importer
diff --git a/apiserver/plane/app/serializers/intake.py b/apiserver/plane/app/serializers/intake.py
index 3800b13ab..8b8bbacf7 100644
--- a/apiserver/plane/app/serializers/intake.py
+++ b/apiserver/plane/app/serializers/intake.py
@@ -3,11 +3,7 @@ from rest_framework import serializers
# Module imports
from .base import BaseSerializer
-from .issue import (
- IssueIntakeSerializer,
- LabelLiteSerializer,
- IssueDetailSerializer,
-)
+from .issue import IssueIntakeSerializer, LabelLiteSerializer, IssueDetailSerializer
from .project import ProjectLiteSerializer
from .state import StateLiteSerializer
from .user import UserLiteSerializer
@@ -21,10 +17,7 @@ class IntakeSerializer(BaseSerializer):
class Meta:
model = Intake
fields = "__all__"
- read_only_fields = [
- "project",
- "workspace",
- ]
+ read_only_fields = ["project", "workspace"]
class IntakeIssueSerializer(BaseSerializer):
@@ -41,10 +34,7 @@ class IntakeIssueSerializer(BaseSerializer):
"issue",
"created_by",
]
- read_only_fields = [
- "project",
- "workspace",
- ]
+ read_only_fields = ["project", "workspace"]
def to_representation(self, instance):
# Pass the annotated fields to the Issue instance if they exist
@@ -70,10 +60,7 @@ class IntakeIssueDetailSerializer(BaseSerializer):
"source",
"issue",
]
- read_only_fields = [
- "project",
- "workspace",
- ]
+ read_only_fields = ["project", "workspace"]
def to_representation(self, instance):
# Pass the annotated fields to the Issue instance if they exist
@@ -95,12 +82,8 @@ class IntakeIssueLiteSerializer(BaseSerializer):
class IssueStateIntakeSerializer(BaseSerializer):
state_detail = StateLiteSerializer(read_only=True, source="state")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
- label_details = LabelLiteSerializer(
- read_only=True, source="labels", many=True
- )
- assignee_details = UserLiteSerializer(
- read_only=True, source="assignees", many=True
- )
+ label_details = LabelLiteSerializer(read_only=True, source="labels", many=True)
+ assignee_details = UserLiteSerializer(read_only=True, source="assignees", many=True)
sub_issues_count = serializers.IntegerField(read_only=True)
issue_intake = IntakeIssueLiteSerializer(read_only=True, many=True)
diff --git a/apiserver/plane/app/serializers/issue.py b/apiserver/plane/app/serializers/issue.py
index b0904834f..007f34849 100644
--- a/apiserver/plane/app/serializers/issue.py
+++ b/apiserver/plane/app/serializers/issue.py
@@ -60,12 +60,7 @@ class IssueProjectLiteSerializer(BaseSerializer):
class Meta:
model = Issue
- fields = [
- "id",
- "project_detail",
- "name",
- "sequence_id",
- ]
+ fields = ["id", "project_detail", "name", "sequence_id"]
read_only_fields = fields
@@ -74,16 +69,10 @@ class IssueProjectLiteSerializer(BaseSerializer):
class IssueCreateSerializer(BaseSerializer):
# ids
state_id = serializers.PrimaryKeyRelatedField(
- source="state",
- queryset=State.objects.all(),
- required=False,
- allow_null=True,
+ source="state", queryset=State.objects.all(), required=False, allow_null=True
)
parent_id = serializers.PrimaryKeyRelatedField(
- source="parent",
- queryset=Issue.objects.all(),
- required=False,
- allow_null=True,
+ source="parent", queryset=Issue.objects.all(), required=False, allow_null=True
)
label_ids = serializers.ListField(
child=serializers.PrimaryKeyRelatedField(queryset=Label.objects.all()),
@@ -124,9 +113,7 @@ class IssueCreateSerializer(BaseSerializer):
and data.get("target_date", None) is not None
and data.get("start_date", None) > data.get("target_date", None)
):
- raise serializers.ValidationError(
- "Start date cannot exceed target date"
- )
+ raise serializers.ValidationError("Start date cannot exceed target date")
return data
def create(self, validated_data):
@@ -138,10 +125,7 @@ class IssueCreateSerializer(BaseSerializer):
default_assignee_id = self.context["default_assignee_id"]
# Create Issue
- issue = Issue.objects.create(
- **validated_data,
- project_id=project_id,
- )
+ issue = Issue.objects.create(**validated_data, project_id=project_id)
# Issue Audit Users
created_by_id = issue.created_by_id
@@ -245,9 +229,7 @@ class IssueActivitySerializer(BaseSerializer):
actor_detail = UserLiteSerializer(read_only=True, source="actor")
issue_detail = IssueFlatSerializer(read_only=True, source="issue")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
- workspace_detail = WorkspaceLiteSerializer(
- read_only=True, source="workspace"
- )
+ workspace_detail = WorkspaceLiteSerializer(read_only=True, source="workspace")
class Meta:
model = IssueActivity
@@ -258,11 +240,7 @@ class IssueUserPropertySerializer(BaseSerializer):
class Meta:
model = IssueUserProperty
fields = "__all__"
- read_only_fields = [
- "user",
- "workspace",
- "project",
- ]
+ read_only_fields = ["user", "workspace", "project"]
class LabelSerializer(BaseSerializer):
@@ -277,30 +255,20 @@ class LabelSerializer(BaseSerializer):
"workspace_id",
"sort_order",
]
- read_only_fields = [
- "workspace",
- "project",
- ]
+ read_only_fields = ["workspace", "project"]
class LabelLiteSerializer(BaseSerializer):
class Meta:
model = Label
- fields = [
- "id",
- "name",
- "color",
- ]
+ fields = ["id", "name", "color"]
class IssueLabelSerializer(BaseSerializer):
class Meta:
model = IssueLabel
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- ]
+ read_only_fields = ["workspace", "project"]
class IssueRelationSerializer(BaseSerializer):
@@ -316,17 +284,8 @@ class IssueRelationSerializer(BaseSerializer):
class Meta:
model = IssueRelation
- fields = [
- "id",
- "project_id",
- "sequence_id",
- "relation_type",
- "name",
- ]
- read_only_fields = [
- "workspace",
- "project",
- ]
+ fields = ["id", "project_id", "sequence_id", "relation_type", "name"]
+ read_only_fields = ["workspace", "project"]
class RelatedIssueSerializer(BaseSerializer):
@@ -334,25 +293,14 @@ class RelatedIssueSerializer(BaseSerializer):
project_id = serializers.PrimaryKeyRelatedField(
source="issue.project_id", read_only=True
)
- sequence_id = serializers.IntegerField(
- source="issue.sequence_id", read_only=True
- )
+ sequence_id = serializers.IntegerField(source="issue.sequence_id", read_only=True)
name = serializers.CharField(source="issue.name", read_only=True)
relation_type = serializers.CharField(read_only=True)
class Meta:
model = IssueRelation
- fields = [
- "id",
- "project_id",
- "sequence_id",
- "relation_type",
- "name",
- ]
- read_only_fields = [
- "workspace",
- "project",
- ]
+ fields = ["id", "project_id", "sequence_id", "relation_type", "name"]
+ read_only_fields = ["workspace", "project"]
class IssueAssigneeSerializer(BaseSerializer):
@@ -460,8 +408,7 @@ class IssueLinkSerializer(BaseSerializer):
# Validation if url already exists
def create(self, validated_data):
if IssueLink.objects.filter(
- url=validated_data.get("url"),
- issue_id=validated_data.get("issue_id"),
+ url=validated_data.get("url"), issue_id=validated_data.get("issue_id")
).exists():
raise serializers.ValidationError(
{"error": "URL already exists for this Issue"}
@@ -471,8 +418,7 @@ class IssueLinkSerializer(BaseSerializer):
def update(self, instance, validated_data):
if (
IssueLink.objects.filter(
- url=validated_data.get("url"),
- issue_id=instance.issue_id,
+ url=validated_data.get("url"), issue_id=instance.issue_id
)
.exclude(pk=instance.id)
.exists()
@@ -500,7 +446,6 @@ class IssueLinkLiteSerializer(BaseSerializer):
class IssueAttachmentSerializer(BaseSerializer):
-
asset_url = serializers.CharField(read_only=True)
class Meta:
@@ -538,37 +483,20 @@ class IssueReactionSerializer(BaseSerializer):
class Meta:
model = IssueReaction
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- "issue",
- "actor",
- "deleted_at",
- ]
+ read_only_fields = ["workspace", "project", "issue", "actor", "deleted_at"]
class IssueReactionLiteSerializer(DynamicBaseSerializer):
class Meta:
model = IssueReaction
- fields = [
- "id",
- "actor",
- "issue",
- "reaction",
- ]
+ fields = ["id", "actor", "issue", "reaction"]
class CommentReactionSerializer(BaseSerializer):
class Meta:
model = CommentReaction
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- "comment",
- "actor",
- "deleted_at",
- ]
+ read_only_fields = ["workspace", "project", "comment", "actor", "deleted_at"]
class IssueVoteSerializer(BaseSerializer):
@@ -576,14 +504,7 @@ class IssueVoteSerializer(BaseSerializer):
class Meta:
model = IssueVote
- fields = [
- "issue",
- "vote",
- "workspace",
- "project",
- "actor",
- "actor_detail",
- ]
+ fields = ["issue", "vote", "workspace", "project", "actor", "actor_detail"]
read_only_fields = fields
@@ -591,9 +512,7 @@ class IssueCommentSerializer(BaseSerializer):
actor_detail = UserLiteSerializer(read_only=True, source="actor")
issue_detail = IssueFlatSerializer(read_only=True, source="issue")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
- workspace_detail = WorkspaceLiteSerializer(
- read_only=True, source="workspace"
- )
+ workspace_detail = WorkspaceLiteSerializer(read_only=True, source="workspace")
comment_reactions = CommentReactionSerializer(read_only=True, many=True)
is_member = serializers.BooleanField(read_only=True)
@@ -617,25 +536,15 @@ class IssueStateFlatSerializer(BaseSerializer):
class Meta:
model = Issue
- fields = [
- "id",
- "sequence_id",
- "name",
- "state_detail",
- "project_detail",
- ]
+ fields = ["id", "sequence_id", "name", "state_detail", "project_detail"]
# Issue Serializer with state details
class IssueStateSerializer(DynamicBaseSerializer):
- label_details = LabelLiteSerializer(
- read_only=True, source="labels", many=True
- )
+ label_details = LabelLiteSerializer(read_only=True, source="labels", many=True)
state_detail = StateLiteSerializer(read_only=True, source="state")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
- assignee_details = UserLiteSerializer(
- read_only=True, source="assignees", many=True
- )
+ assignee_details = UserLiteSerializer(read_only=True, source="assignees", many=True)
sub_issues_count = serializers.IntegerField(read_only=True)
attachment_count = serializers.IntegerField(read_only=True)
link_count = serializers.IntegerField(read_only=True)
@@ -646,10 +555,7 @@ class IssueStateSerializer(DynamicBaseSerializer):
class IssueIntakeSerializer(DynamicBaseSerializer):
- label_ids = serializers.ListField(
- child=serializers.UUIDField(),
- required=False,
- )
+ label_ids = serializers.ListField(child=serializers.UUIDField(), required=False)
class Meta:
model = Issue
@@ -669,20 +575,11 @@ class IssueIntakeSerializer(DynamicBaseSerializer):
class IssueSerializer(DynamicBaseSerializer):
# ids
cycle_id = serializers.PrimaryKeyRelatedField(read_only=True)
- module_ids = serializers.ListField(
- child=serializers.UUIDField(),
- required=False,
- )
+ module_ids = serializers.ListField(child=serializers.UUIDField(), required=False)
# Many to many
- label_ids = serializers.ListField(
- child=serializers.UUIDField(),
- required=False,
- )
- assignee_ids = serializers.ListField(
- child=serializers.UUIDField(),
- required=False,
- )
+ label_ids = serializers.ListField(child=serializers.UUIDField(), required=False)
+ assignee_ids = serializers.ListField(child=serializers.UUIDField(), required=False)
# Count items
sub_issues_count = serializers.IntegerField(read_only=True)
@@ -724,11 +621,7 @@ class IssueSerializer(DynamicBaseSerializer):
class IssueLiteSerializer(DynamicBaseSerializer):
class Meta:
model = Issue
- fields = [
- "id",
- "sequence_id",
- "project_id",
- ]
+ fields = ["id", "sequence_id", "project_id"]
read_only_fields = fields
@@ -737,10 +630,7 @@ class IssueDetailSerializer(IssueSerializer):
is_subscribed = serializers.BooleanField(read_only=True)
class Meta(IssueSerializer.Meta):
- fields = IssueSerializer.Meta.fields + [
- "description_html",
- "is_subscribed",
- ]
+ fields = IssueSerializer.Meta.fields + ["description_html", "is_subscribed"]
read_only_fields = fields
@@ -776,8 +666,4 @@ class IssueSubscriberSerializer(BaseSerializer):
class Meta:
model = IssueSubscriber
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- "issue",
- ]
+ read_only_fields = ["workspace", "project", "issue"]
diff --git a/apiserver/plane/app/serializers/module.py b/apiserver/plane/app/serializers/module.py
index 48ace6022..22ff44279 100644
--- a/apiserver/plane/app/serializers/module.py
+++ b/apiserver/plane/app/serializers/module.py
@@ -21,10 +21,7 @@ from plane.db.models import (
class ModuleWriteSerializer(BaseSerializer):
lead_id = serializers.PrimaryKeyRelatedField(
- source="lead",
- queryset=User.objects.all(),
- required=False,
- allow_null=True,
+ source="lead", queryset=User.objects.all(), required=False, allow_null=True
)
member_ids = serializers.ListField(
child=serializers.PrimaryKeyRelatedField(queryset=User.objects.all()),
@@ -48,9 +45,7 @@ class ModuleWriteSerializer(BaseSerializer):
def to_representation(self, instance):
data = super().to_representation(instance)
- data["member_ids"] = [
- str(member.id) for member in instance.members.all()
- ]
+ data["member_ids"] = [str(member.id) for member in instance.members.all()]
return data
def validate(self, data):
@@ -59,9 +54,7 @@ class ModuleWriteSerializer(BaseSerializer):
and data.get("target_date", None) is not None
and data.get("start_date", None) > data.get("target_date", None)
):
- raise serializers.ValidationError(
- "Start date cannot exceed target date"
- )
+ raise serializers.ValidationError("Start date cannot exceed target date")
return data
def create(self, validated_data):
@@ -71,9 +64,7 @@ class ModuleWriteSerializer(BaseSerializer):
module_name = validated_data.get("name")
if module_name:
# Lookup for the module name in the module table for that project
- if Module.objects.filter(
- name=module_name, project=project
- ).exists():
+ if Module.objects.filter(name=module_name, project=project).exists():
raise serializers.ValidationError(
{"error": "Module with this name already exists"}
)
@@ -104,9 +95,7 @@ class ModuleWriteSerializer(BaseSerializer):
if module_name:
# Lookup for the module name in the module table for that project
if (
- Module.objects.filter(
- name=module_name, project=instance.project
- )
+ Module.objects.filter(name=module_name, project=instance.project)
.exclude(id=instance.id)
.exists()
):
@@ -203,8 +192,7 @@ class ModuleLinkSerializer(BaseSerializer):
def create(self, validated_data):
validated_data["url"] = self.validate_url(validated_data.get("url"))
if ModuleLink.objects.filter(
- url=validated_data.get("url"),
- module_id=validated_data.get("module_id"),
+ url=validated_data.get("url"), module_id=validated_data.get("module_id")
).exists():
raise serializers.ValidationError({"error": "URL already exists."})
return super().create(validated_data)
@@ -213,8 +201,7 @@ class ModuleLinkSerializer(BaseSerializer):
validated_data["url"] = self.validate_url(validated_data.get("url"))
if (
ModuleLink.objects.filter(
- url=validated_data.get("url"),
- module_id=instance.module_id,
+ url=validated_data.get("url"), module_id=instance.module_id
)
.exclude(pk=instance.id)
.exists()
diff --git a/apiserver/plane/app/serializers/notification.py b/apiserver/plane/app/serializers/notification.py
index 2f79992f2..58007ec26 100644
--- a/apiserver/plane/app/serializers/notification.py
+++ b/apiserver/plane/app/serializers/notification.py
@@ -8,9 +8,7 @@ from rest_framework import serializers
class NotificationSerializer(BaseSerializer):
- triggered_by_details = UserLiteSerializer(
- read_only=True, source="triggered_by"
- )
+ triggered_by_details = UserLiteSerializer(read_only=True, source="triggered_by")
is_inbox_issue = serializers.BooleanField(read_only=True)
is_intake_issue = serializers.BooleanField(read_only=True)
is_mentioned_notification = serializers.BooleanField(read_only=True)
diff --git a/apiserver/plane/app/serializers/page.py b/apiserver/plane/app/serializers/page.py
index e7f273d40..b69221081 100644
--- a/apiserver/plane/app/serializers/page.py
+++ b/apiserver/plane/app/serializers/page.py
@@ -22,14 +22,8 @@ class PageSerializer(BaseSerializer):
required=False,
)
# Many to many
- label_ids = serializers.ListField(
- child=serializers.UUIDField(),
- required=False,
- )
- project_ids = serializers.ListField(
- child=serializers.UUIDField(),
- required=False,
- )
+ label_ids = serializers.ListField(child=serializers.UUIDField(), required=False)
+ project_ids = serializers.ListField(child=serializers.UUIDField(), required=False)
class Meta:
model = Page
@@ -54,10 +48,7 @@ class PageSerializer(BaseSerializer):
"label_ids",
"project_ids",
]
- read_only_fields = [
- "workspace",
- "owned_by",
- ]
+ read_only_fields = ["workspace", "owned_by"]
def create(self, validated_data):
labels = validated_data.pop("labels", None)
@@ -127,9 +118,7 @@ class PageDetailSerializer(PageSerializer):
description_html = serializers.CharField()
class Meta(PageSerializer.Meta):
- fields = PageSerializer.Meta.fields + [
- "description_html",
- ]
+ fields = PageSerializer.Meta.fields + ["description_html"]
class SubPageSerializer(BaseSerializer):
@@ -138,10 +127,7 @@ class SubPageSerializer(BaseSerializer):
class Meta:
model = PageLog
fields = "__all__"
- read_only_fields = [
- "workspace",
- "page",
- ]
+ read_only_fields = ["workspace", "page"]
def get_entity_details(self, obj):
entity_name = obj.entity_name
@@ -158,10 +144,7 @@ class PageLogSerializer(BaseSerializer):
class Meta:
model = PageLog
fields = "__all__"
- read_only_fields = [
- "workspace",
- "page",
- ]
+ read_only_fields = ["workspace", "page"]
class PageVersionSerializer(BaseSerializer):
@@ -178,10 +161,7 @@ class PageVersionSerializer(BaseSerializer):
"created_by",
"updated_by",
]
- read_only_fields = [
- "workspace",
- "page",
- ]
+ read_only_fields = ["workspace", "page"]
class PageVersionDetailSerializer(BaseSerializer):
@@ -201,7 +181,4 @@ class PageVersionDetailSerializer(BaseSerializer):
"created_by",
"updated_by",
]
- read_only_fields = [
- "workspace",
- "page",
- ]
+ read_only_fields = ["workspace", "page"]
diff --git a/apiserver/plane/app/serializers/project.py b/apiserver/plane/app/serializers/project.py
index ccf9251bc..cc7b7fbcb 100644
--- a/apiserver/plane/app/serializers/project.py
+++ b/apiserver/plane/app/serializers/project.py
@@ -4,10 +4,7 @@ from rest_framework import serializers
# Module imports
from .base import BaseSerializer, DynamicBaseSerializer
from plane.app.serializers.workspace import WorkspaceLiteSerializer
-from plane.app.serializers.user import (
- UserLiteSerializer,
- UserAdminLiteSerializer,
-)
+from plane.app.serializers.user import UserLiteSerializer, UserAdminLiteSerializer
from plane.db.models import (
Project,
ProjectMember,
@@ -19,32 +16,23 @@ from plane.db.models import (
class ProjectSerializer(BaseSerializer):
- workspace_detail = WorkspaceLiteSerializer(
- source="workspace", read_only=True
- )
+ workspace_detail = WorkspaceLiteSerializer(source="workspace", read_only=True)
inbox_view = serializers.BooleanField(read_only=True, source="intake_view")
class Meta:
model = Project
fields = "__all__"
- read_only_fields = [
- "workspace",
- "deleted_at",
- ]
+ read_only_fields = ["workspace", "deleted_at"]
def create(self, validated_data):
identifier = validated_data.get("identifier", "").strip().upper()
if identifier == "":
- raise serializers.ValidationError(
- detail="Project Identifier is required"
- )
+ raise serializers.ValidationError(detail="Project Identifier is required")
if ProjectIdentifier.objects.filter(
name=identifier, workspace_id=self.context["workspace_id"]
).exists():
- raise serializers.ValidationError(
- detail="Project Identifier is taken"
- )
+ raise serializers.ValidationError(detail="Project Identifier is taken")
project = Project.objects.create(
**validated_data, workspace_id=self.context["workspace_id"]
)
@@ -83,9 +71,7 @@ class ProjectSerializer(BaseSerializer):
return project
# If not same fail update
- raise serializers.ValidationError(
- detail="Project Identifier is already taken"
- )
+ raise serializers.ValidationError(detail="Project Identifier is already taken")
class ProjectLiteSerializer(BaseSerializer):
@@ -214,26 +200,16 @@ class ProjectMemberLiteSerializer(BaseSerializer):
class DeployBoardSerializer(BaseSerializer):
project_details = ProjectLiteSerializer(read_only=True, source="project")
- workspace_detail = WorkspaceLiteSerializer(
- read_only=True, source="workspace"
- )
+ workspace_detail = WorkspaceLiteSerializer(read_only=True, source="workspace")
class Meta:
model = DeployBoard
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- "anchor",
- ]
+ read_only_fields = ["workspace", "project", "anchor"]
class ProjectPublicMemberSerializer(BaseSerializer):
class Meta:
model = ProjectPublicMember
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- "member",
- ]
+ read_only_fields = ["workspace", "project", "member"]
diff --git a/apiserver/plane/app/serializers/state.py b/apiserver/plane/app/serializers/state.py
index 773d8e461..61af5cab7 100644
--- a/apiserver/plane/app/serializers/state.py
+++ b/apiserver/plane/app/serializers/state.py
@@ -19,19 +19,11 @@ class StateSerializer(BaseSerializer):
"description",
"sequence",
]
- read_only_fields = [
- "workspace",
- "project",
- ]
+ read_only_fields = ["workspace", "project"]
class StateLiteSerializer(BaseSerializer):
class Meta:
model = State
- fields = [
- "id",
- "name",
- "color",
- "group",
- ]
+ fields = ["id", "name", "color", "group"]
read_only_fields = fields
diff --git a/apiserver/plane/app/serializers/user.py b/apiserver/plane/app/serializers/user.py
index 993f74c82..ebc002c9c 100644
--- a/apiserver/plane/app/serializers/user.py
+++ b/apiserver/plane/app/serializers/user.py
@@ -2,13 +2,7 @@
from rest_framework import serializers
# Module import
-from plane.db.models import (
- Account,
- Profile,
- User,
- Workspace,
- WorkspaceMemberInvite,
-)
+from plane.db.models import Account, Profile, User, Workspace, WorkspaceMemberInvite
from .base import BaseSerializer
@@ -17,11 +11,7 @@ class UserSerializer(BaseSerializer):
class Meta:
model = User
# Exclude password field from the serializer
- fields = [
- field.name
- for field in User._meta.fields
- if field.name != "password"
- ]
+ fields = [field.name for field in User._meta.fields if field.name != "password"]
# Make all system fields and email read only
read_only_fields = [
"id",
@@ -56,7 +46,6 @@ class UserSerializer(BaseSerializer):
class UserMeSerializer(BaseSerializer):
-
class Meta:
model = User
fields = [
@@ -87,11 +76,7 @@ class UserMeSettingsSerializer(BaseSerializer):
class Meta:
model = User
- fields = [
- "id",
- "email",
- "workspace",
- ]
+ fields = ["id", "email", "workspace"]
read_only_fields = fields
def get_workspace(self, obj):
@@ -128,8 +113,7 @@ class UserMeSettingsSerializer(BaseSerializer):
else:
fallback_workspace = (
Workspace.objects.filter(
- workspace_member__member_id=obj.id,
- workspace_member__is_active=True,
+ workspace_member__member_id=obj.id, workspace_member__is_active=True
)
.order_by("created_at")
.first()
@@ -138,14 +122,10 @@ class UserMeSettingsSerializer(BaseSerializer):
"last_workspace_id": None,
"last_workspace_slug": None,
"fallback_workspace_id": (
- fallback_workspace.id
- if fallback_workspace is not None
- else None
+ fallback_workspace.id if fallback_workspace is not None else None
),
"fallback_workspace_slug": (
- fallback_workspace.slug
- if fallback_workspace is not None
- else None
+ fallback_workspace.slug if fallback_workspace is not None else None
),
"invites": workspace_invites,
}
@@ -163,10 +143,7 @@ class UserLiteSerializer(BaseSerializer):
"is_bot",
"display_name",
]
- read_only_fields = [
- "id",
- "is_bot",
- ]
+ read_only_fields = ["id", "is_bot"]
class UserAdminLiteSerializer(BaseSerializer):
@@ -183,10 +160,7 @@ class UserAdminLiteSerializer(BaseSerializer):
"email",
"last_login_medium",
]
- read_only_fields = [
- "id",
- "is_bot",
- ]
+ read_only_fields = ["id", "is_bot"]
class ChangePasswordSerializer(serializers.Serializer):
@@ -207,9 +181,7 @@ class ChangePasswordSerializer(serializers.Serializer):
if data.get("new_password") != data.get("confirm_password"):
raise serializers.ValidationError(
- {
- "error": "Confirm password should be same as the new password."
- }
+ {"error": "Confirm password should be same as the new password."}
)
return data
@@ -227,15 +199,11 @@ class ProfileSerializer(BaseSerializer):
class Meta:
model = Profile
fields = "__all__"
- read_only_fields = [
- "user",
- ]
+ read_only_fields = ["user"]
class AccountSerializer(BaseSerializer):
class Meta:
model = Account
fields = "__all__"
- read_only_fields = [
- "user",
- ]
+ read_only_fields = ["user"]
diff --git a/apiserver/plane/app/serializers/webhook.py b/apiserver/plane/app/serializers/webhook.py
index 918d1705c..fa4019f7a 100644
--- a/apiserver/plane/app/serializers/webhook.py
+++ b/apiserver/plane/app/serializers/webhook.py
@@ -47,13 +47,9 @@ class WebhookSerializer(DynamicBaseSerializer):
# Additional validation for multiple request domains and their subdomains
request = self.context.get("request")
- disallowed_domains = [
- "plane.so",
- ] # Add your disallowed domains here
+ disallowed_domains = ["plane.so"] # Add your disallowed domains here
if request:
- request_host = request.get_host().split(":")[
- 0
- ] # Remove port if present
+ request_host = request.get_host().split(":")[0] # Remove port if present
disallowed_domains.append(request_host)
# Check if hostname is a subdomain or exact match of any disallowed domain
@@ -99,9 +95,7 @@ class WebhookSerializer(DynamicBaseSerializer):
# Additional validation for multiple request domains and their subdomains
request = self.context.get("request")
- disallowed_domains = [
- "plane.so",
- ] # Add your disallowed domains here
+ disallowed_domains = ["plane.so"] # Add your disallowed domains here
if request:
request_host = request.get_host().split(":")[
0
@@ -122,10 +116,7 @@ class WebhookSerializer(DynamicBaseSerializer):
class Meta:
model = Webhook
fields = "__all__"
- read_only_fields = [
- "workspace",
- "secret_key",
- ]
+ read_only_fields = ["workspace", "secret_key"]
class WebhookLogSerializer(DynamicBaseSerializer):
diff --git a/apiserver/plane/app/serializers/workspace.py b/apiserver/plane/app/serializers/workspace.py
index 1a2b89bba..03e64e32a 100644
--- a/apiserver/plane/app/serializers/workspace.py
+++ b/apiserver/plane/app/serializers/workspace.py
@@ -47,11 +47,7 @@ class WorkSpaceSerializer(DynamicBaseSerializer):
class WorkspaceLiteSerializer(BaseSerializer):
class Meta:
model = Workspace
- fields = [
- "name",
- "slug",
- "id",
- ]
+ fields = ["name", "slug", "id"]
read_only_fields = fields
@@ -66,6 +62,7 @@ class WorkSpaceMemberSerializer(DynamicBaseSerializer):
class WorkspaceMemberMeSerializer(BaseSerializer):
draft_issue_count = serializers.IntegerField(read_only=True)
+
class Meta:
model = WorkspaceMember
fields = "__all__"
@@ -101,9 +98,7 @@ class WorkSpaceMemberInviteSerializer(BaseSerializer):
class TeamSerializer(BaseSerializer):
- members_detail = UserLiteSerializer(
- read_only=True, source="members", many=True
- )
+ members_detail = UserLiteSerializer(read_only=True, source="members", many=True)
members = serializers.ListField(
child=serializers.PrimaryKeyRelatedField(queryset=User.objects.all()),
write_only=True,
@@ -140,9 +135,7 @@ class TeamSerializer(BaseSerializer):
members = validated_data.pop("members")
TeamMember.objects.filter(team=instance).delete()
team_members = [
- TeamMember(
- member=member, team=instance, workspace=instance.workspace
- )
+ TeamMember(member=member, team=instance, workspace=instance.workspace)
for member in members
]
TeamMember.objects.bulk_create(team_members, batch_size=10)
@@ -154,17 +147,11 @@ class WorkspaceThemeSerializer(BaseSerializer):
class Meta:
model = WorkspaceTheme
fields = "__all__"
- read_only_fields = [
- "workspace",
- "actor",
- ]
+ read_only_fields = ["workspace", "actor"]
class WorkspaceUserPropertiesSerializer(BaseSerializer):
class Meta:
model = WorkspaceUserProperties
fields = "__all__"
- read_only_fields = [
- "workspace",
- "user",
- ]
+ read_only_fields = ["workspace", "user"]
diff --git a/apiserver/plane/app/urls/asset.py b/apiserver/plane/app/urls/asset.py
index eed379fd7..ec0f41b62 100644
--- a/apiserver/plane/app/urls/asset.py
+++ b/apiserver/plane/app/urls/asset.py
@@ -26,11 +26,7 @@ urlpatterns = [
FileAssetEndpoint.as_view(),
name="file-assets",
),
- path(
- "users/file-assets/",
- UserAssetsEndpoint.as_view(),
- name="user-file-assets",
- ),
+ path("users/file-assets/", UserAssetsEndpoint.as_view(), name="user-file-assets"),
path(
"users/file-assets//",
UserAssetsEndpoint.as_view(),
@@ -38,11 +34,7 @@ urlpatterns = [
),
path(
"workspaces/file-assets///restore/",
- FileAssetViewSet.as_view(
- {
- "post": "restore",
- }
- ),
+ FileAssetViewSet.as_view({"post": "restore"}),
name="file-assets-restore",
),
# V2 Endpoints
diff --git a/apiserver/plane/app/urls/cycle.py b/apiserver/plane/app/urls/cycle.py
index 0d62d0271..f188d0872 100644
--- a/apiserver/plane/app/urls/cycle.py
+++ b/apiserver/plane/app/urls/cycle.py
@@ -17,12 +17,7 @@ from plane.app.views import (
urlpatterns = [
path(
"workspaces//projects//cycles/",
- CycleViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ CycleViewSet.as_view({"get": "list", "post": "create"}),
name="project-cycle",
),
path(
@@ -39,12 +34,7 @@ urlpatterns = [
),
path(
"workspaces//projects//cycles//cycle-issues/",
- CycleIssueViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ CycleIssueViewSet.as_view({"get": "list", "post": "create"}),
name="project-issue-cycle",
),
path(
@@ -66,21 +56,12 @@ urlpatterns = [
),
path(
"workspaces//projects//user-favorite-cycles/",
- CycleFavoriteViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ CycleFavoriteViewSet.as_view({"get": "list", "post": "create"}),
name="user-favorite-cycle",
),
path(
"workspaces//projects//user-favorite-cycles//",
- CycleFavoriteViewSet.as_view(
- {
- "delete": "destroy",
- }
- ),
+ CycleFavoriteViewSet.as_view({"delete": "destroy"}),
name="user-favorite-cycle",
),
path(
diff --git a/apiserver/plane/app/urls/estimate.py b/apiserver/plane/app/urls/estimate.py
index 7db94aa46..8e5af2a85 100644
--- a/apiserver/plane/app/urls/estimate.py
+++ b/apiserver/plane/app/urls/estimate.py
@@ -16,42 +16,24 @@ urlpatterns = [
),
path(
"workspaces//projects//estimates/",
- BulkEstimatePointEndpoint.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ BulkEstimatePointEndpoint.as_view({"get": "list", "post": "create"}),
name="bulk-create-estimate-points",
),
path(
"workspaces//projects//estimates//",
BulkEstimatePointEndpoint.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="bulk-create-estimate-points",
),
path(
"workspaces//projects//estimates//estimate-points/",
- EstimatePointEndpoint.as_view(
- {
- "post": "create",
- }
- ),
+ EstimatePointEndpoint.as_view({"post": "create"}),
name="estimate-points",
),
path(
"workspaces//projects//estimates//estimate-points//",
- EstimatePointEndpoint.as_view(
- {
- "patch": "partial_update",
- "delete": "destroy",
- }
- ),
+ EstimatePointEndpoint.as_view({"patch": "partial_update", "delete": "destroy"}),
name="estimate-points",
),
]
diff --git a/apiserver/plane/app/urls/external.py b/apiserver/plane/app/urls/external.py
index 744c646ca..4972962d8 100644
--- a/apiserver/plane/app/urls/external.py
+++ b/apiserver/plane/app/urls/external.py
@@ -6,17 +6,13 @@ from plane.app.views import GPTIntegrationEndpoint, WorkspaceGPTIntegrationEndpo
urlpatterns = [
- path(
- "unsplash/",
- UnsplashEndpoint.as_view(),
- name="unsplash",
- ),
+ path("unsplash/", UnsplashEndpoint.as_view(), name="unsplash"),
path(
"workspaces//projects//ai-assistant/",
GPTIntegrationEndpoint.as_view(),
name="importer",
),
- path(
+ path(
"workspaces//ai-assistant/",
WorkspaceGPTIntegrationEndpoint.as_view(),
name="importer",
diff --git a/apiserver/plane/app/urls/intake.py b/apiserver/plane/app/urls/intake.py
index be2f3a053..397579262 100644
--- a/apiserver/plane/app/urls/intake.py
+++ b/apiserver/plane/app/urls/intake.py
@@ -1,94 +1,55 @@
from django.urls import path
-from plane.app.views import (
- IntakeViewSet,
- IntakeIssueViewSet,
-)
+from plane.app.views import IntakeViewSet, IntakeIssueViewSet
urlpatterns = [
path(
"workspaces//projects//intakes/",
- IntakeViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IntakeViewSet.as_view({"get": "list", "post": "create"}),
name="intake",
),
path(
"workspaces//projects//intakes//",
IntakeViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="intake",
),
path(
"workspaces//projects//intake-issues/",
- IntakeIssueViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IntakeIssueViewSet.as_view({"get": "list", "post": "create"}),
name="intake-issue",
),
path(
"workspaces//projects//intake-issues//",
IntakeIssueViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="intake-issue",
),
path(
"workspaces//projects//inboxes/",
- IntakeViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IntakeViewSet.as_view({"get": "list", "post": "create"}),
name="inbox",
),
path(
"workspaces//projects//inboxes//",
IntakeViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="inbox",
),
path(
"workspaces//projects//inbox-issues/",
- IntakeIssueViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IntakeIssueViewSet.as_view({"get": "list", "post": "create"}),
name="inbox-issue",
),
path(
"workspaces//projects//inbox-issues//",
IntakeIssueViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="inbox-issue",
),
diff --git a/apiserver/plane/app/urls/issue.py b/apiserver/plane/app/urls/issue.py
index e8ad4408d..07dfa5112 100644
--- a/apiserver/plane/app/urls/issue.py
+++ b/apiserver/plane/app/urls/issue.py
@@ -34,12 +34,7 @@ urlpatterns = [
),
path(
"workspaces//projects//issues/",
- IssueViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IssueViewSet.as_view({"get": "list", "post": "create"}),
name="project-issue",
),
path(
@@ -68,12 +63,7 @@ urlpatterns = [
),
path(
"workspaces//projects//issue-labels/",
- LabelViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ LabelViewSet.as_view({"get": "list", "post": "create"}),
name="project-issue-labels",
),
path(
@@ -111,12 +101,7 @@ urlpatterns = [
),
path(
"workspaces//projects//issues//issue-links/",
- IssueLinkViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IssueLinkViewSet.as_view({"get": "list", "post": "create"}),
name="project-issue-links",
),
path(
@@ -169,12 +154,7 @@ urlpatterns = [
## IssueComments
path(
"workspaces//projects//issues//comments/",
- IssueCommentViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IssueCommentViewSet.as_view({"get": "list", "post": "create"}),
name="project-issue-comment",
),
path(
@@ -193,12 +173,7 @@ urlpatterns = [
# Issue Subscribers
path(
"workspaces//projects//issues//issue-subscribers/",
- IssueSubscriberViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IssueSubscriberViewSet.as_view({"get": "list", "post": "create"}),
name="project-issue-subscribers",
),
path(
@@ -209,11 +184,7 @@ urlpatterns = [
path(
"workspaces//projects//issues//subscribe/",
IssueSubscriberViewSet.as_view(
- {
- "get": "subscription_status",
- "post": "subscribe",
- "delete": "unsubscribe",
- }
+ {"get": "subscription_status", "post": "subscribe", "delete": "unsubscribe"}
),
name="project-issue-subscribers",
),
@@ -221,42 +192,24 @@ urlpatterns = [
# Issue Reactions
path(
"workspaces//projects//issues//reactions/",
- IssueReactionViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IssueReactionViewSet.as_view({"get": "list", "post": "create"}),
name="project-issue-reactions",
),
path(
"workspaces//projects//issues//reactions//",
- IssueReactionViewSet.as_view(
- {
- "delete": "destroy",
- }
- ),
+ IssueReactionViewSet.as_view({"delete": "destroy"}),
name="project-issue-reactions",
),
## End Issue Reactions
# Comment Reactions
path(
"workspaces//projects//comments//reactions/",
- CommentReactionViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ CommentReactionViewSet.as_view({"get": "list", "post": "create"}),
name="project-issue-comment-reactions",
),
path(
"workspaces//projects//comments//reactions//",
- CommentReactionViewSet.as_view(
- {
- "delete": "destroy",
- }
- ),
+ CommentReactionViewSet.as_view({"delete": "destroy"}),
name="project-issue-comment-reactions",
),
## End Comment Reactions
@@ -270,21 +223,13 @@ urlpatterns = [
## Issue Archives
path(
"workspaces//projects//archived-issues/",
- IssueArchiveViewSet.as_view(
- {
- "get": "list",
- }
- ),
+ IssueArchiveViewSet.as_view({"get": "list"}),
name="project-issue-archive",
),
path(
"workspaces//projects//issues//archive/",
IssueArchiveViewSet.as_view(
- {
- "get": "retrieve",
- "post": "archive",
- "delete": "unarchive",
- }
+ {"get": "retrieve", "post": "archive", "delete": "unarchive"}
),
name="project-issue-archive-unarchive",
),
@@ -292,21 +237,12 @@ urlpatterns = [
## Issue Relation
path(
"workspaces//projects//issues//issue-relation/",
- IssueRelationViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IssueRelationViewSet.as_view({"get": "list", "post": "create"}),
name="issue-relation",
),
path(
"workspaces//projects//issues//remove-relation/",
- IssueRelationViewSet.as_view(
- {
- "post": "remove_relation",
- }
- ),
+ IssueRelationViewSet.as_view({"post": "remove_relation"}),
name="issue-relation",
),
## End Issue Relation
diff --git a/apiserver/plane/app/urls/module.py b/apiserver/plane/app/urls/module.py
index bf6c84b2f..75cbb14d6 100644
--- a/apiserver/plane/app/urls/module.py
+++ b/apiserver/plane/app/urls/module.py
@@ -14,12 +14,7 @@ from plane.app.views import (
urlpatterns = [
path(
"workspaces//projects//modules/",
- ModuleViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ ModuleViewSet.as_view({"get": "list", "post": "create"}),
name="project-modules",
),
path(
@@ -36,21 +31,12 @@ urlpatterns = [
),
path(
"workspaces//projects//issues//modules/",
- ModuleIssueViewSet.as_view(
- {
- "post": "create_issue_modules",
- }
- ),
+ ModuleIssueViewSet.as_view({"post": "create_issue_modules"}),
name="issue-module",
),
path(
"workspaces//projects//modules//issues/",
- ModuleIssueViewSet.as_view(
- {
- "post": "create_module_issues",
- "get": "list",
- }
- ),
+ ModuleIssueViewSet.as_view({"post": "create_module_issues", "get": "list"}),
name="project-module-issues",
),
path(
@@ -67,12 +53,7 @@ urlpatterns = [
),
path(
"workspaces//projects//modules//module-links/",
- ModuleLinkViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ ModuleLinkViewSet.as_view({"get": "list", "post": "create"}),
name="project-issue-module-links",
),
path(
@@ -89,21 +70,12 @@ urlpatterns = [
),
path(
"workspaces//projects//user-favorite-modules/",
- ModuleFavoriteViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ ModuleFavoriteViewSet.as_view({"get": "list", "post": "create"}),
name="user-favorite-module",
),
path(
"workspaces//projects//user-favorite-modules//",
- ModuleFavoriteViewSet.as_view(
- {
- "delete": "destroy",
- }
- ),
+ ModuleFavoriteViewSet.as_view({"delete": "destroy"}),
name="user-favorite-module",
),
path(
diff --git a/apiserver/plane/app/urls/notification.py b/apiserver/plane/app/urls/notification.py
index 0bbf4f3c7..cd5647ea4 100644
--- a/apiserver/plane/app/urls/notification.py
+++ b/apiserver/plane/app/urls/notification.py
@@ -12,42 +12,24 @@ from plane.app.views import (
urlpatterns = [
path(
"workspaces//users/notifications/",
- NotificationViewSet.as_view(
- {
- "get": "list",
- }
- ),
+ NotificationViewSet.as_view({"get": "list"}),
name="notifications",
),
path(
"workspaces//users/notifications//",
NotificationViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="notifications",
),
path(
"workspaces//users/notifications//read/",
- NotificationViewSet.as_view(
- {
- "post": "mark_read",
- "delete": "mark_unread",
- }
- ),
+ NotificationViewSet.as_view({"post": "mark_read", "delete": "mark_unread"}),
name="notifications",
),
path(
"workspaces//users/notifications//archive/",
- NotificationViewSet.as_view(
- {
- "post": "archive",
- "delete": "unarchive",
- }
- ),
+ NotificationViewSet.as_view({"post": "archive", "delete": "unarchive"}),
name="notifications",
),
path(
@@ -57,11 +39,7 @@ urlpatterns = [
),
path(
"workspaces//users/notifications/mark-all-read/",
- MarkAllReadNotificationViewSet.as_view(
- {
- "post": "create",
- }
- ),
+ MarkAllReadNotificationViewSet.as_view({"post": "create"}),
name="mark-all-read-notifications",
),
path(
diff --git a/apiserver/plane/app/urls/page.py b/apiserver/plane/app/urls/page.py
index 7c1ac5dfe..b49f1d4a2 100644
--- a/apiserver/plane/app/urls/page.py
+++ b/apiserver/plane/app/urls/page.py
@@ -14,66 +14,38 @@ from plane.app.views import (
urlpatterns = [
path(
"workspaces//projects//pages/",
- PageViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ PageViewSet.as_view({"get": "list", "post": "create"}),
name="project-pages",
),
path(
"workspaces//projects//pages//",
PageViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="project-pages",
),
# favorite pages
path(
"workspaces//projects//favorite-pages//",
- PageFavoriteViewSet.as_view(
- {
- "post": "create",
- "delete": "destroy",
- }
- ),
+ PageFavoriteViewSet.as_view({"post": "create", "delete": "destroy"}),
name="user-favorite-pages",
),
# archived pages
path(
"workspaces//projects//pages//archive/",
- PageViewSet.as_view(
- {
- "post": "archive",
- "delete": "unarchive",
- }
- ),
+ PageViewSet.as_view({"post": "archive", "delete": "unarchive"}),
name="project-page-archive-unarchive",
),
# lock and unlock
path(
"workspaces//projects//pages//lock/",
- PageViewSet.as_view(
- {
- "post": "lock",
- "delete": "unlock",
- }
- ),
+ PageViewSet.as_view({"post": "lock", "delete": "unlock"}),
name="project-pages-lock-unlock",
),
# private and public page
path(
"workspaces//projects//pages//access/",
- PageViewSet.as_view(
- {
- "post": "access",
- }
- ),
+ PageViewSet.as_view({"post": "access"}),
name="project-pages-access",
),
path(
@@ -93,12 +65,7 @@ urlpatterns = [
),
path(
"workspaces//projects//pages//description/",
- PagesDescriptionViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- }
- ),
+ PagesDescriptionViewSet.as_view({"get": "retrieve", "patch": "partial_update"}),
name="page-description",
),
path(
diff --git a/apiserver/plane/app/urls/project.py b/apiserver/plane/app/urls/project.py
index 0807c7616..3f41caee8 100644
--- a/apiserver/plane/app/urls/project.py
+++ b/apiserver/plane/app/urls/project.py
@@ -21,12 +21,7 @@ from plane.app.views import (
urlpatterns = [
path(
"workspaces//projects/",
- ProjectViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ ProjectViewSet.as_view({"get": "list", "post": "create"}),
name="project",
),
path(
@@ -48,32 +43,17 @@ urlpatterns = [
),
path(
"workspaces//projects//invitations/",
- ProjectInvitationsViewset.as_view(
- {
- "get": "list",
- "post": "create",
- },
- ),
+ ProjectInvitationsViewset.as_view({"get": "list", "post": "create"}),
name="project-member-invite",
),
path(
"workspaces//projects//invitations//",
- ProjectInvitationsViewset.as_view(
- {
- "get": "retrieve",
- "delete": "destroy",
- }
- ),
+ ProjectInvitationsViewset.as_view({"get": "retrieve", "delete": "destroy"}),
name="project-member-invite",
),
path(
"users/me/workspaces//projects/invitations/",
- UserProjectInvitationsViewset.as_view(
- {
- "get": "list",
- "post": "create",
- },
- ),
+ UserProjectInvitationsViewset.as_view({"get": "list", "post": "create"}),
name="user-project-invitations",
),
path(
@@ -88,32 +68,19 @@ urlpatterns = [
),
path(
"workspaces//projects//members/",
- ProjectMemberViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ ProjectMemberViewSet.as_view({"get": "list", "post": "create"}),
name="project-member",
),
path(
"workspaces//projects//members//",
ProjectMemberViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="project-member",
),
path(
"workspaces//projects//members/leave/",
- ProjectMemberViewSet.as_view(
- {
- "post": "leave",
- }
- ),
+ ProjectMemberViewSet.as_view({"post": "leave"}),
name="project-member",
),
path(
@@ -133,21 +100,12 @@ urlpatterns = [
),
path(
"workspaces//user-favorite-projects/",
- ProjectFavoritesViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ ProjectFavoritesViewSet.as_view({"get": "list", "post": "create"}),
name="project-favorite",
),
path(
"workspaces//user-favorite-projects//",
- ProjectFavoritesViewSet.as_view(
- {
- "delete": "destroy",
- }
- ),
+ ProjectFavoritesViewSet.as_view({"delete": "destroy"}),
name="project-favorite",
),
path(
@@ -157,22 +115,13 @@ urlpatterns = [
),
path(
"workspaces//projects//project-deploy-boards/",
- DeployBoardViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ DeployBoardViewSet.as_view({"get": "list", "post": "create"}),
name="project-deploy-board",
),
path(
"workspaces//projects//project-deploy-boards//",
DeployBoardViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="project-deploy-board",
),
diff --git a/apiserver/plane/app/urls/search.py b/apiserver/plane/app/urls/search.py
index 05a79994e..bbea8093d 100644
--- a/apiserver/plane/app/urls/search.py
+++ b/apiserver/plane/app/urls/search.py
@@ -1,10 +1,7 @@
from django.urls import path
-from plane.app.views import (
- GlobalSearchEndpoint,
- IssueSearchEndpoint,
-)
+from plane.app.views import GlobalSearchEndpoint, IssueSearchEndpoint
urlpatterns = [
diff --git a/apiserver/plane/app/urls/state.py b/apiserver/plane/app/urls/state.py
index 9fec70ea1..b9ffd0341 100644
--- a/apiserver/plane/app/urls/state.py
+++ b/apiserver/plane/app/urls/state.py
@@ -7,32 +7,19 @@ from plane.app.views import StateViewSet
urlpatterns = [
path(
"workspaces//projects//states/",
- StateViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ StateViewSet.as_view({"get": "list", "post": "create"}),
name="project-states",
),
path(
"workspaces//projects//states//",
StateViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="project-state",
),
path(
"workspaces//projects//states//mark-default/",
- StateViewSet.as_view(
- {
- "post": "mark_as_default",
- }
- ),
+ StateViewSet.as_view({"post": "mark_as_default"}),
name="project-state",
),
]
diff --git a/apiserver/plane/app/urls/user.py b/apiserver/plane/app/urls/user.py
index fd18ea87b..443961d0e 100644
--- a/apiserver/plane/app/urls/user.py
+++ b/apiserver/plane/app/urls/user.py
@@ -22,60 +22,30 @@ urlpatterns = [
path(
"users/me/",
UserEndpoint.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "deactivate",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "deactivate"}
),
name="users",
),
- path(
- "users/session/",
- UserSessionEndpoint.as_view(),
- name="user-session",
- ),
+ path("users/session/", UserSessionEndpoint.as_view(), name="user-session"),
path(
"users/me/settings/",
- UserEndpoint.as_view(
- {
- "get": "retrieve_user_settings",
- }
- ),
+ UserEndpoint.as_view({"get": "retrieve_user_settings"}),
name="users",
),
# Profile
- path(
- "users/me/profile/",
- ProfileEndpoint.as_view(),
- name="accounts",
- ),
+ path("users/me/profile/", ProfileEndpoint.as_view(), name="accounts"),
# End profile
# Accounts
- path(
- "users/me/accounts/",
- AccountEndpoint.as_view(),
- name="accounts",
- ),
- path(
- "users/me/accounts//",
- AccountEndpoint.as_view(),
- name="accounts",
- ),
+ path("users/me/accounts/", AccountEndpoint.as_view(), name="accounts"),
+ path("users/me/accounts//", AccountEndpoint.as_view(), name="accounts"),
## End Accounts
path(
"users/me/instance-admin/",
- UserEndpoint.as_view(
- {
- "get": "retrieve_instance_admin",
- }
- ),
+ UserEndpoint.as_view({"get": "retrieve_instance_admin"}),
name="users",
),
path(
- "users/me/onboard/",
- UpdateUserOnBoardedEndpoint.as_view(),
- name="user-onboard",
+ "users/me/onboard/", UpdateUserOnBoardedEndpoint.as_view(), name="user-onboard"
),
path(
"users/me/tour-completed/",
@@ -83,15 +53,11 @@ urlpatterns = [
name="user-tour",
),
path(
- "users/me/activities/",
- UserActivityEndpoint.as_view(),
- name="user-activities",
+ "users/me/activities/", UserActivityEndpoint.as_view(), name="user-activities"
),
# user workspaces
path(
- "users/me/workspaces/",
- UserWorkSpacesEndpoint.as_view(),
- name="user-workspace",
+ "users/me/workspaces/", UserWorkSpacesEndpoint.as_view(), name="user-workspace"
),
# User Graphs
path(
diff --git a/apiserver/plane/app/urls/views.py b/apiserver/plane/app/urls/views.py
index a2f8e2ac8..063e39c3d 100644
--- a/apiserver/plane/app/urls/views.py
+++ b/apiserver/plane/app/urls/views.py
@@ -12,12 +12,7 @@ from plane.app.views import (
urlpatterns = [
path(
"workspaces//projects//views/",
- IssueViewViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IssueViewViewSet.as_view({"get": "list", "post": "create"}),
name="project-view",
),
path(
@@ -34,12 +29,7 @@ urlpatterns = [
),
path(
"workspaces//views/",
- WorkspaceViewViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ WorkspaceViewViewSet.as_view({"get": "list", "post": "create"}),
name="global-view",
),
path(
@@ -56,30 +46,17 @@ urlpatterns = [
),
path(
"workspaces//issues/",
- WorkspaceViewIssuesViewSet.as_view(
- {
- "get": "list",
- }
- ),
+ WorkspaceViewIssuesViewSet.as_view({"get": "list"}),
name="global-view-issues",
),
path(
"workspaces//projects//user-favorite-views/",
- IssueViewFavoriteViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IssueViewFavoriteViewSet.as_view({"get": "list", "post": "create"}),
name="user-favorite-view",
),
path(
"workspaces//projects//user-favorite-views//",
- IssueViewFavoriteViewSet.as_view(
- {
- "delete": "destroy",
- }
- ),
+ IssueViewFavoriteViewSet.as_view({"delete": "destroy"}),
name="user-favorite-view",
),
]
diff --git a/apiserver/plane/app/urls/webhook.py b/apiserver/plane/app/urls/webhook.py
index 16cc48be8..e21ec7261 100644
--- a/apiserver/plane/app/urls/webhook.py
+++ b/apiserver/plane/app/urls/webhook.py
@@ -8,11 +8,7 @@ from plane.app.views import (
urlpatterns = [
- path(
- "workspaces//webhooks/",
- WebhookEndpoint.as_view(),
- name="webhooks",
- ),
+ path("workspaces//webhooks/", WebhookEndpoint.as_view(), name="webhooks"),
path(
"workspaces//webhooks//",
WebhookEndpoint.as_view(),
diff --git a/apiserver/plane/app/urls/workspace.py b/apiserver/plane/app/urls/workspace.py
index fb6f4c13a..00e996995 100644
--- a/apiserver/plane/app/urls/workspace.py
+++ b/apiserver/plane/app/urls/workspace.py
@@ -39,12 +39,7 @@ urlpatterns = [
),
path(
"workspaces/",
- WorkSpaceViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ WorkSpaceViewSet.as_view({"get": "list", "post": "create"}),
name="workspace",
),
path(
@@ -61,34 +56,20 @@ urlpatterns = [
),
path(
"workspaces//invitations/",
- WorkspaceInvitationsViewset.as_view(
- {
- "get": "list",
- "post": "create",
- },
- ),
+ WorkspaceInvitationsViewset.as_view({"get": "list", "post": "create"}),
name="workspace-invitations",
),
path(
"workspaces//invitations//",
WorkspaceInvitationsViewset.as_view(
- {
- "delete": "destroy",
- "get": "retrieve",
- "patch": "partial_update",
- }
+ {"delete": "destroy", "get": "retrieve", "patch": "partial_update"}
),
name="workspace-invitations",
),
# user workspace invitations
path(
"users/me/workspaces/invitations/",
- UserWorkspaceInvitationsViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- },
- ),
+ UserWorkspaceInvitationsViewSet.as_view({"get": "list", "post": "create"}),
name="user-workspace-invitations",
),
path(
@@ -110,31 +91,18 @@ urlpatterns = [
path(
"workspaces//members//",
WorkSpaceMemberViewSet.as_view(
- {
- "patch": "partial_update",
- "delete": "destroy",
- "get": "retrieve",
- }
+ {"patch": "partial_update", "delete": "destroy", "get": "retrieve"}
),
name="workspace-member",
),
path(
"workspaces//members/leave/",
- WorkSpaceMemberViewSet.as_view(
- {
- "post": "leave",
- },
- ),
+ WorkSpaceMemberViewSet.as_view({"post": "leave"}),
name="leave-workspace-members",
),
path(
"workspaces//teams/",
- TeamMemberViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ TeamMemberViewSet.as_view({"get": "list", "post": "create"}),
name="workspace-team-members",
),
path(
@@ -166,22 +134,13 @@ urlpatterns = [
),
path(
"workspaces//workspace-themes/",
- WorkspaceThemeViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ WorkspaceThemeViewSet.as_view({"get": "list", "post": "create"}),
name="workspace-themes",
),
path(
"workspaces//workspace-themes//",
WorkspaceThemeViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="workspace-themes",
),
@@ -257,22 +216,13 @@ urlpatterns = [
),
path(
"workspaces//draft-issues/",
- WorkspaceDraftIssueViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ WorkspaceDraftIssueViewSet.as_view({"get": "list", "post": "create"}),
name="workspace-draft-issues",
),
path(
"workspaces//draft-issues//",
WorkspaceDraftIssueViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="workspace-drafts-issues",
),
diff --git a/apiserver/plane/app/views/__init__.py b/apiserver/plane/app/views/__init__.py
index 159686fa3..c21000a4e 100644
--- a/apiserver/plane/app/views/__init__.py
+++ b/apiserver/plane/app/views/__init__.py
@@ -59,12 +59,8 @@ from .workspace.invite import (
WorkspaceJoinEndpoint,
UserWorkspaceInvitationsViewSet,
)
-from .workspace.label import (
- WorkspaceLabelsEndpoint,
-)
-from .workspace.state import (
- WorkspaceStatesEndpoint,
-)
+from .workspace.label import WorkspaceLabelsEndpoint
+from .workspace.state import WorkspaceStatesEndpoint
from .workspace.user import (
UserLastProjectWithWorkspaceEndpoint,
WorkspaceUserProfileIssuesEndpoint,
@@ -75,15 +71,9 @@ from .workspace.user import (
UserActivityGraphEndpoint,
UserIssueCompletedGraphEndpoint,
)
-from .workspace.estimate import (
- WorkspaceEstimatesEndpoint,
-)
-from .workspace.module import (
- WorkspaceModulesEndpoint,
-)
-from .workspace.cycle import (
- WorkspaceCyclesEndpoint,
-)
+from .workspace.estimate import WorkspaceEstimatesEndpoint
+from .workspace.module import WorkspaceModulesEndpoint
+from .workspace.cycle import WorkspaceCyclesEndpoint
from .state.base import StateViewSet
from .view.base import (
@@ -103,18 +93,10 @@ from .cycle.base import (
CycleAnalyticsEndpoint,
CycleProgressEndpoint,
)
-from .cycle.issue import (
- CycleIssueViewSet,
-)
-from .cycle.archive import (
- CycleArchiveUnarchiveEndpoint,
-)
+from .cycle.issue import CycleIssueViewSet
+from .cycle.archive import CycleArchiveUnarchiveEndpoint
-from .asset.base import (
- FileAssetEndpoint,
- UserAssetsEndpoint,
- FileAssetViewSet,
-)
+from .asset.base import FileAssetEndpoint, UserAssetsEndpoint, FileAssetViewSet
from .asset.v2 import (
WorkspaceFileAssetEndpoint,
UserAssetsV2Endpoint,
@@ -134,9 +116,7 @@ from .issue.base import (
IssueBulkUpdateDateEndpoint,
)
-from .issue.activity import (
- IssueActivityEndpoint,
-)
+from .issue.activity import IssueActivityEndpoint
from .issue.archive import IssueArchiveViewSet, BulkArchiveIssuesEndpoint
@@ -146,35 +126,19 @@ from .issue.attachment import (
IssueAttachmentV2Endpoint,
)
-from .issue.comment import (
- IssueCommentViewSet,
- CommentReactionViewSet,
-)
+from .issue.comment import IssueCommentViewSet, CommentReactionViewSet
-from .issue.label import (
- LabelViewSet,
- BulkCreateIssueLabelsEndpoint,
-)
+from .issue.label import LabelViewSet, BulkCreateIssueLabelsEndpoint
-from .issue.link import (
- IssueLinkViewSet,
-)
+from .issue.link import IssueLinkViewSet
-from .issue.relation import (
- IssueRelationViewSet,
-)
+from .issue.relation import IssueRelationViewSet
-from .issue.reaction import (
- IssueReactionViewSet,
-)
+from .issue.reaction import IssueReactionViewSet
-from .issue.sub_issue import (
- SubIssuesEndpoint,
-)
+from .issue.sub_issue import SubIssuesEndpoint
-from .issue.subscriber import (
- IssueSubscriberViewSet,
-)
+from .issue.subscriber import IssueSubscriberViewSet
from .module.base import (
ModuleViewSet,
@@ -183,18 +147,11 @@ from .module.base import (
ModuleUserPropertiesEndpoint,
)
-from .module.issue import (
- ModuleIssueViewSet,
-)
+from .module.issue import ModuleIssueViewSet
-from .module.archive import (
- ModuleArchiveUnarchiveEndpoint,
-)
+from .module.archive import ModuleArchiveUnarchiveEndpoint
-from .api import (
- ApiTokenEndpoint,
- ServiceApiTokenEndpoint,
-)
+from .api import ApiTokenEndpoint, ServiceApiTokenEndpoint
from .page.base import (
PageViewSet,
diff --git a/apiserver/plane/app/views/analytic/base.py b/apiserver/plane/app/views/analytic/base.py
index 49728cde8..a36458406 100644
--- a/apiserver/plane/app/views/analytic/base.py
+++ b/apiserver/plane/app/views/analytic/base.py
@@ -22,14 +22,7 @@ from plane.app.permissions import allow_permission, ROLE
class AnalyticsEndpoint(BaseAPIView):
-
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ],
- level="WORKSPACE",
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def get(self, request, slug):
x_axis = request.GET.get("x_axis", False)
y_axis = request.GET.get("y_axis", False)
@@ -50,10 +43,7 @@ class AnalyticsEndpoint(BaseAPIView):
"completed_at",
]
- valid_yaxis = [
- "issue_count",
- "estimate",
- ]
+ valid_yaxis = ["issue_count", "estimate"]
# Check for x-axis and y-axis as thery are required parameters
if (
@@ -70,9 +60,7 @@ class AnalyticsEndpoint(BaseAPIView):
)
# If segment is present it cannot be same as x-axis
- if segment and (
- segment not in valid_xaxis_segment or x_axis == segment
- ):
+ if segment and (segment not in valid_xaxis_segment or x_axis == segment):
return Response(
{
"error": "Both segment and x axis cannot be same and segment should be valid"
@@ -97,10 +85,7 @@ class AnalyticsEndpoint(BaseAPIView):
state_details = {}
if x_axis in ["state_id"] or segment in ["state_id"]:
state_details = (
- Issue.issue_objects.filter(
- workspace__slug=slug,
- **filters,
- )
+ Issue.issue_objects.filter(workspace__slug=slug, **filters)
.distinct("state_id")
.order_by("state_id")
.values("state_id", "state__name", "state__color")
@@ -163,9 +148,7 @@ class AnalyticsEndpoint(BaseAPIView):
)
cycle_details = {}
- if x_axis in ["issue_cycle__cycle_id"] or segment in [
- "issue_cycle__cycle_id"
- ]:
+ if x_axis in ["issue_cycle__cycle_id"] or segment in ["issue_cycle__cycle_id"]:
cycle_details = (
Issue.issue_objects.filter(
workspace__slug=slug,
@@ -175,10 +158,7 @@ class AnalyticsEndpoint(BaseAPIView):
)
.distinct("issue_cycle__cycle_id")
.order_by("issue_cycle__cycle_id")
- .values(
- "issue_cycle__cycle_id",
- "issue_cycle__cycle__name",
- )
+ .values("issue_cycle__cycle_id", "issue_cycle__cycle__name")
)
module_details = {}
@@ -194,10 +174,7 @@ class AnalyticsEndpoint(BaseAPIView):
)
.distinct("issue_module__module_id")
.order_by("issue_module__module_id")
- .values(
- "issue_module__module_id",
- "issue_module__module__name",
- )
+ .values("issue_module__module_id", "issue_module__module__name")
)
return Response(
@@ -217,9 +194,7 @@ class AnalyticsEndpoint(BaseAPIView):
class AnalyticViewViewset(BaseViewSet):
- permission_classes = [
- WorkSpaceAdminPermission,
- ]
+ permission_classes = [WorkSpaceAdminPermission]
model = AnalyticView
serializer_class = AnalyticViewSerializer
@@ -229,25 +204,14 @@ class AnalyticViewViewset(BaseViewSet):
def get_queryset(self):
return self.filter_queryset(
- super()
- .get_queryset()
- .filter(workspace__slug=self.kwargs.get("slug"))
+ super().get_queryset().filter(workspace__slug=self.kwargs.get("slug"))
)
class SavedAnalyticEndpoint(BaseAPIView):
-
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ],
- level="WORKSPACE",
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def get(self, request, slug, analytic_id):
- analytic_view = AnalyticView.objects.get(
- pk=analytic_id, workspace__slug=slug
- )
+ analytic_view = AnalyticView.objects.get(pk=analytic_id, workspace__slug=slug)
filter = analytic_view.query
queryset = Issue.issue_objects.filter(**filter)
@@ -273,14 +237,7 @@ class SavedAnalyticEndpoint(BaseAPIView):
class ExportAnalyticsEndpoint(BaseAPIView):
-
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ],
- level="WORKSPACE",
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def post(self, request, slug):
x_axis = request.data.get("x_axis", False)
y_axis = request.data.get("y_axis", False)
@@ -301,10 +258,7 @@ class ExportAnalyticsEndpoint(BaseAPIView):
"completed_at",
]
- valid_yaxis = [
- "issue_count",
- "estimate",
- ]
+ valid_yaxis = ["issue_count", "estimate"]
# Check for x-axis and y-axis as thery are required parameters
if (
@@ -321,9 +275,7 @@ class ExportAnalyticsEndpoint(BaseAPIView):
)
# If segment is present it cannot be same as x-axis
- if segment and (
- segment not in valid_xaxis_segment or x_axis == segment
- ):
+ if segment and (segment not in valid_xaxis_segment or x_axis == segment):
return Response(
{
"error": "Both segment and x axis cannot be same and segment should be valid"
@@ -344,13 +296,10 @@ class ExportAnalyticsEndpoint(BaseAPIView):
class DefaultAnalyticsEndpoint(BaseAPIView):
-
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE")
def get(self, request, slug):
filters = issue_filters(request.GET, "GET")
- base_issues = Issue.issue_objects.filter(
- workspace__slug=slug, **filters
- )
+ base_issues = Issue.issue_objects.filter(workspace__slug=slug, **filters)
total_issues = base_issues.count()
@@ -363,9 +312,7 @@ class DefaultAnalyticsEndpoint(BaseAPIView):
)
open_issues_groups = ["backlog", "unstarted", "started"]
- open_issues_queryset = state_groups.filter(
- state__group__in=open_issues_groups
- )
+ open_issues_queryset = state_groups.filter(state__group__in=open_issues_groups)
open_issues = open_issues_queryset.count()
open_issues_classified = (
@@ -407,8 +354,7 @@ class DefaultAnalyticsEndpoint(BaseAPIView):
),
# If `avatar_asset` is None, fall back to using `avatar` field directly
When(
- created_by__avatar_asset__isnull=True,
- then="created_by__avatar",
+ created_by__avatar_asset__isnull=True, then="created_by__avatar"
),
default=Value(None),
output_field=models.CharField(),
@@ -441,8 +387,7 @@ class DefaultAnalyticsEndpoint(BaseAPIView):
),
# If `avatar_asset` is None, fall back to using `avatar` field directly
When(
- assignees__avatar_asset__isnull=True,
- then="assignees__avatar",
+ assignees__avatar_asset__isnull=True, then="assignees__avatar"
),
default=Value(None),
output_field=models.CharField(),
@@ -469,8 +414,7 @@ class DefaultAnalyticsEndpoint(BaseAPIView):
),
# If `avatar_asset` is None, fall back to using `avatar` field directly
When(
- assignees__avatar_asset__isnull=True,
- then="assignees__avatar",
+ assignees__avatar_asset__isnull=True, then="assignees__avatar"
),
default=Value(None),
output_field=models.CharField(),
@@ -479,9 +423,7 @@ class DefaultAnalyticsEndpoint(BaseAPIView):
.order_by("-count")
)
- open_estimate_sum = open_issues_queryset.aggregate(sum=Sum("point"))[
- "sum"
- ]
+ open_estimate_sum = open_issues_queryset.aggregate(sum=Sum("point"))["sum"]
total_estimate_sum = base_issues.aggregate(sum=Sum("point"))["sum"]
return Response(
diff --git a/apiserver/plane/app/views/api.py b/apiserver/plane/app/views/api.py
index fe7259fbb..732d96832 100644
--- a/apiserver/plane/app/views/api.py
+++ b/apiserver/plane/app/views/api.py
@@ -13,9 +13,7 @@ from plane.app.permissions import WorkspaceOwnerPermission
class ApiTokenEndpoint(BaseAPIView):
- permission_classes = [
- WorkspaceOwnerPermission,
- ]
+ permission_classes = [WorkspaceOwnerPermission]
def post(self, request, slug):
label = request.data.get("label", str(uuid4().hex))
@@ -37,10 +35,7 @@ class ApiTokenEndpoint(BaseAPIView):
serializer = APITokenSerializer(api_token)
# Token will be only visible while creating
- return Response(
- serializer.data,
- status=status.HTTP_201_CREATED,
- )
+ return Response(serializer.data, status=status.HTTP_201_CREATED)
def get(self, request, slug, pk=None):
if pk is None:
@@ -58,23 +53,14 @@ class ApiTokenEndpoint(BaseAPIView):
def delete(self, request, slug, pk):
api_token = APIToken.objects.get(
- workspace__slug=slug,
- user=request.user,
- pk=pk,
- is_service=False,
+ workspace__slug=slug, user=request.user, pk=pk, is_service=False
)
api_token.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
def patch(self, request, slug, pk):
- api_token = APIToken.objects.get(
- workspace__slug=slug,
- user=request.user,
- pk=pk,
- )
- serializer = APITokenSerializer(
- api_token, data=request.data, partial=True
- )
+ api_token = APIToken.objects.get(workspace__slug=slug, user=request.user, pk=pk)
+ serializer = APITokenSerializer(api_token, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
@@ -82,25 +68,17 @@ class ApiTokenEndpoint(BaseAPIView):
class ServiceApiTokenEndpoint(BaseAPIView):
- permission_classes = [
- WorkspaceOwnerPermission,
- ]
+ permission_classes = [WorkspaceOwnerPermission]
def post(self, request, slug):
workspace = Workspace.objects.get(slug=slug)
api_token = APIToken.objects.filter(
- workspace=workspace,
- is_service=True,
+ workspace=workspace, is_service=True
).first()
if api_token:
- return Response(
- {
- "token": str(api_token.token),
- },
- status=status.HTTP_200_OK,
- )
+ return Response({"token": str(api_token.token)}, status=status.HTTP_200_OK)
else:
# Check the user type
user_type = 1 if request.user.is_bot else 0
@@ -114,9 +92,5 @@ class ServiceApiTokenEndpoint(BaseAPIView):
is_service=True,
)
return Response(
- {
- "token": str(api_token.token),
- },
- status=status.HTTP_201_CREATED,
+ {"token": str(api_token.token)}, status=status.HTTP_201_CREATED
)
-
diff --git a/apiserver/plane/app/views/asset/base.py b/apiserver/plane/app/views/asset/base.py
index ebf6bc164..d30f0bb26 100644
--- a/apiserver/plane/app/views/asset/base.py
+++ b/apiserver/plane/app/views/asset/base.py
@@ -10,11 +10,7 @@ from plane.app.serializers import FileAssetSerializer
class FileAssetEndpoint(BaseAPIView):
- parser_classes = (
- MultiPartParser,
- FormParser,
- JSONParser,
- )
+ parser_classes = (MultiPartParser, FormParser, JSONParser)
"""
A viewset for viewing and editing task instances.
@@ -28,8 +24,7 @@ class FileAssetEndpoint(BaseAPIView):
files, context={"request": request}, many=True
)
return Response(
- {"data": serializer.data, "status": True},
- status=status.HTTP_200_OK,
+ {"data": serializer.data, "status": True}, status=status.HTTP_200_OK
)
else:
return Response(
@@ -67,16 +62,11 @@ class UserAssetsEndpoint(BaseAPIView):
parser_classes = (MultiPartParser, FormParser)
def get(self, request, asset_key):
- files = FileAsset.objects.filter(
- asset=asset_key, created_by=request.user
- )
+ files = FileAsset.objects.filter(asset=asset_key, created_by=request.user)
if files.exists():
- serializer = FileAssetSerializer(
- files, context={"request": request}
- )
+ serializer = FileAssetSerializer(files, context={"request": request})
return Response(
- {"data": serializer.data, "status": True},
- status=status.HTTP_200_OK,
+ {"data": serializer.data, "status": True}, status=status.HTTP_200_OK
)
else:
return Response(
@@ -92,9 +82,7 @@ class UserAssetsEndpoint(BaseAPIView):
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, asset_key):
- file_asset = FileAsset.objects.get(
- asset=asset_key, created_by=request.user
- )
+ file_asset = FileAsset.objects.get(asset=asset_key, created_by=request.user)
file_asset.is_deleted = True
file_asset.save(update_fields=["is_deleted"])
return Response(status=status.HTTP_204_NO_CONTENT)
diff --git a/apiserver/plane/app/views/asset/v2.py b/apiserver/plane/app/views/asset/v2.py
index 16e82de59..827c95908 100644
--- a/apiserver/plane/app/views/asset/v2.py
+++ b/apiserver/plane/app/views/asset/v2.py
@@ -13,12 +13,7 @@ from rest_framework.permissions import AllowAny
# Module imports
from ..base import BaseAPIView
-from plane.db.models import (
- FileAsset,
- Workspace,
- Project,
- User,
-)
+from plane.db.models import FileAsset, Workspace, Project, User
from plane.settings.storage import S3Storage
from plane.app.permissions import allow_permission, ROLE
from plane.utils.cache import invalidate_cache_directly
@@ -49,10 +44,7 @@ class UserAssetsV2Endpoint(BaseAPIView):
user.avatar_asset_id = asset_id
user.save()
invalidate_cache_directly(
- path="/api/users/me/",
- url_params=False,
- user=True,
- request=request,
+ path="/api/users/me/", url_params=False, user=True, request=request
)
invalidate_cache_directly(
path="/api/users/me/settings/",
@@ -72,10 +64,7 @@ class UserAssetsV2Endpoint(BaseAPIView):
user.cover_image_asset_id = asset_id
user.save()
invalidate_cache_directly(
- path="/api/users/me/",
- url_params=False,
- user=True,
- request=request,
+ path="/api/users/me/", url_params=False, user=True, request=request
)
invalidate_cache_directly(
path="/api/users/me/settings/",
@@ -93,10 +82,7 @@ class UserAssetsV2Endpoint(BaseAPIView):
user.avatar_asset_id = None
user.save()
invalidate_cache_directly(
- path="/api/users/me/",
- url_params=False,
- user=True,
- request=request,
+ path="/api/users/me/", url_params=False, user=True, request=request
)
invalidate_cache_directly(
path="/api/users/me/settings/",
@@ -111,10 +97,7 @@ class UserAssetsV2Endpoint(BaseAPIView):
user.cover_image_asset_id = None
user.save()
invalidate_cache_directly(
- path="/api/users/me/",
- url_params=False,
- user=True,
- request=request,
+ path="/api/users/me/", url_params=False, user=True, request=request
)
invalidate_cache_directly(
path="/api/users/me/settings/",
@@ -138,20 +121,12 @@ class UserAssetsV2Endpoint(BaseAPIView):
# Check if the entity type is allowed
if not entity_type or entity_type not in ["USER_AVATAR", "USER_COVER"]:
return Response(
- {
- "error": "Invalid entity type.",
- "status": False,
- },
+ {"error": "Invalid entity type.", "status": False},
status=status.HTTP_400_BAD_REQUEST,
)
# Check if the file type is allowed
- allowed_types = [
- "image/jpeg",
- "image/png",
- "image/webp",
- "image/jpg",
- ]
+ allowed_types = ["image/jpeg", "image/png", "image/webp", "image/jpg"]
if type not in allowed_types:
return Response(
{
@@ -166,11 +141,7 @@ class UserAssetsV2Endpoint(BaseAPIView):
# Create a File Asset
asset = FileAsset.objects.create(
- attributes={
- "name": name,
- "type": type,
- "size": size_limit,
- },
+ attributes={"name": name, "type": type, "size": size_limit},
asset=asset_key,
size=size_limit,
user=request.user,
@@ -182,9 +153,7 @@ class UserAssetsV2Endpoint(BaseAPIView):
storage = S3Storage(request=request)
# Generate a presigned URL to share an S3 object
presigned_url = storage.generate_presigned_post(
- object_name=asset_key,
- file_type=type,
- file_size=size_limit,
+ object_name=asset_key, file_type=type, file_size=size_limit
)
# Return the presigned URL
return Response(
@@ -235,45 +204,33 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
def get_entity_id_field(self, entity_type, entity_id):
# Workspace Logo
if entity_type == FileAsset.EntityTypeContext.WORKSPACE_LOGO:
- return {
- "workspace_id": entity_id,
- }
+ return {"workspace_id": entity_id}
# Project Cover
if entity_type == FileAsset.EntityTypeContext.PROJECT_COVER:
- return {
- "project_id": entity_id,
- }
+ return {"project_id": entity_id}
# User Avatar and Cover
if entity_type in [
FileAsset.EntityTypeContext.USER_AVATAR,
FileAsset.EntityTypeContext.USER_COVER,
]:
- return {
- "user_id": entity_id,
- }
+ return {"user_id": entity_id}
# Issue Attachment and Description
if entity_type in [
FileAsset.EntityTypeContext.ISSUE_ATTACHMENT,
FileAsset.EntityTypeContext.ISSUE_DESCRIPTION,
]:
- return {
- "issue_id": entity_id,
- }
+ return {"issue_id": entity_id}
# Page Description
if entity_type == FileAsset.EntityTypeContext.PAGE_DESCRIPTION:
- return {
- "page_id": entity_id,
- }
+ return {"page_id": entity_id}
# Comment Description
if entity_type == FileAsset.EntityTypeContext.COMMENT_DESCRIPTION:
- return {
- "comment_id": entity_id,
- }
+ return {"comment_id": entity_id}
return {}
def asset_delete(self, asset_id):
@@ -301,10 +258,7 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
workspace.logo_asset_id = asset_id
workspace.save()
invalidate_cache_directly(
- path="/api/workspaces/",
- url_params=False,
- user=False,
- request=request,
+ path="/api/workspaces/", url_params=False, user=False, request=request
)
invalidate_cache_directly(
path="/api/users/me/workspaces/",
@@ -313,10 +267,7 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
request=request,
)
invalidate_cache_directly(
- path="/api/instances/",
- url_params=False,
- user=False,
- request=request,
+ path="/api/instances/", url_params=False, user=False, request=request
)
return
@@ -345,10 +296,7 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
workspace.logo_asset_id = None
workspace.save()
invalidate_cache_directly(
- path="/api/workspaces/",
- url_params=False,
- user=False,
- request=request,
+ path="/api/workspaces/", url_params=False, user=False, request=request
)
invalidate_cache_directly(
path="/api/users/me/workspaces/",
@@ -357,10 +305,7 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
request=request,
)
invalidate_cache_directly(
- path="/api/instances/",
- url_params=False,
- user=False,
- request=request,
+ path="/api/instances/", url_params=False, user=False, request=request
)
return
# Project Cover
@@ -384,10 +329,7 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
# Check if the entity type is allowed
if entity_type not in FileAsset.EntityTypeContext.values:
return Response(
- {
- "error": "Invalid entity type.",
- "status": False,
- },
+ {"error": "Invalid entity type.", "status": False},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -419,11 +361,7 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
# Create a File Asset
asset = FileAsset.objects.create(
- attributes={
- "name": name,
- "type": type,
- "size": size_limit,
- },
+ attributes={"name": name, "type": type, "size": size_limit},
asset=asset_key,
size=size_limit,
workspace=workspace,
@@ -438,9 +376,7 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
storage = S3Storage(request=request)
# Generate a presigned URL to share an S3 object
presigned_url = storage.generate_presigned_post(
- object_name=asset_key,
- file_type=type,
- file_size=size_limit,
+ object_name=asset_key, file_type=type, file_size=size_limit
)
# Return the presigned URL
return Response(
@@ -491,18 +427,14 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
# Check if the asset is uploaded
if not asset.is_uploaded:
return Response(
- {
- "error": "The requested asset could not be found.",
- },
+ {"error": "The requested asset could not be found."},
status=status.HTTP_404_NOT_FOUND,
)
# Get the presigned URL
storage = S3Storage(request=request)
# Generate a presigned URL to share an S3 object
- signed_url = storage.generate_presigned_url(
- object_name=asset.asset.name,
- )
+ signed_url = storage.generate_presigned_url(object_name=asset.asset.name)
# Redirect to the signed URL
return HttpResponseRedirect(signed_url)
@@ -510,9 +442,7 @@ class WorkspaceFileAssetEndpoint(BaseAPIView):
class StaticFileAssetEndpoint(BaseAPIView):
"""This endpoint is used to get the signed URL for a static asset."""
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request, asset_id):
# get the asset id
@@ -521,9 +451,7 @@ class StaticFileAssetEndpoint(BaseAPIView):
# Check if the asset is uploaded
if not asset.is_uploaded:
return Response(
- {
- "error": "The requested asset could not be found.",
- },
+ {"error": "The requested asset could not be found."},
status=status.HTTP_404_NOT_FOUND,
)
@@ -535,19 +463,14 @@ class StaticFileAssetEndpoint(BaseAPIView):
FileAsset.EntityTypeContext.PROJECT_COVER,
]:
return Response(
- {
- "error": "Invalid entity type.",
- "status": False,
- },
+ {"error": "Invalid entity type.", "status": False},
status=status.HTTP_400_BAD_REQUEST,
)
# Get the presigned URL
storage = S3Storage(request=request)
# Generate a presigned URL to share an S3 object
- signed_url = storage.generate_presigned_url(
- object_name=asset.asset.name,
- )
+ signed_url = storage.generate_presigned_url(object_name=asset.asset.name)
# Redirect to the signed URL
return HttpResponseRedirect(signed_url)
@@ -569,50 +492,34 @@ class ProjectAssetEndpoint(BaseAPIView):
def get_entity_id_field(self, entity_type, entity_id):
if entity_type == FileAsset.EntityTypeContext.WORKSPACE_LOGO:
- return {
- "workspace_id": entity_id,
- }
+ return {"workspace_id": entity_id}
if entity_type == FileAsset.EntityTypeContext.PROJECT_COVER:
- return {
- "project_id": entity_id,
- }
+ return {"project_id": entity_id}
if entity_type in [
FileAsset.EntityTypeContext.USER_AVATAR,
FileAsset.EntityTypeContext.USER_COVER,
]:
- return {
- "user_id": entity_id,
- }
+ return {"user_id": entity_id}
if entity_type in [
FileAsset.EntityTypeContext.ISSUE_ATTACHMENT,
FileAsset.EntityTypeContext.ISSUE_DESCRIPTION,
]:
- return {
- "issue_id": entity_id,
- }
+ return {"issue_id": entity_id}
if entity_type == FileAsset.EntityTypeContext.PAGE_DESCRIPTION:
- return {
- "page_id": entity_id,
- }
+ return {"page_id": entity_id}
if entity_type == FileAsset.EntityTypeContext.COMMENT_DESCRIPTION:
- return {
- "comment_id": entity_id,
- }
+ return {"comment_id": entity_id}
if entity_type == FileAsset.EntityTypeContext.DRAFT_ISSUE_DESCRIPTION:
- return {
- "draft_issue_id": entity_id,
- }
+ return {"draft_issue_id": entity_id}
return {}
- @allow_permission(
- [ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST],
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def post(self, request, slug, project_id):
name = request.data.get("name")
type = request.data.get("type", "image/jpeg")
@@ -623,10 +530,7 @@ class ProjectAssetEndpoint(BaseAPIView):
# Check if the entity type is allowed
if entity_type not in FileAsset.EntityTypeContext.values:
return Response(
- {
- "error": "Invalid entity type.",
- "status": False,
- },
+ {"error": "Invalid entity type.", "status": False},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -658,11 +562,7 @@ class ProjectAssetEndpoint(BaseAPIView):
# Create a File Asset
asset = FileAsset.objects.create(
- attributes={
- "name": name,
- "type": type,
- "size": size_limit,
- },
+ attributes={"name": name, "type": type, "size": size_limit},
asset=asset_key,
size=size_limit,
workspace=workspace,
@@ -676,9 +576,7 @@ class ProjectAssetEndpoint(BaseAPIView):
storage = S3Storage(request=request)
# Generate a presigned URL to share an S3 object
presigned_url = storage.generate_presigned_post(
- object_name=asset_key,
- file_type=type,
- file_size=size_limit,
+ object_name=asset_key, file_type=type, file_size=size_limit
)
# Return the presigned URL
return Response(
@@ -690,14 +588,10 @@ class ProjectAssetEndpoint(BaseAPIView):
status=status.HTTP_200_OK,
)
- @allow_permission(
- [ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST],
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def patch(self, request, slug, project_id, pk):
# get the asset id
- asset = FileAsset.objects.get(
- id=pk,
- )
+ asset = FileAsset.objects.get(id=pk)
# get the storage metadata
asset.is_uploaded = True
# get the storage metadata
@@ -714,9 +608,7 @@ class ProjectAssetEndpoint(BaseAPIView):
def delete(self, request, slug, project_id, pk):
# Get the asset
asset = FileAsset.objects.get(
- id=pk,
- workspace__slug=slug,
- project_id=project_id,
+ id=pk, workspace__slug=slug, project_id=project_id
)
# Check deleted assets
asset.is_deleted = True
@@ -729,32 +621,25 @@ class ProjectAssetEndpoint(BaseAPIView):
def get(self, request, slug, project_id, pk):
# get the asset id
asset = FileAsset.objects.get(
- workspace__slug=slug,
- project_id=project_id,
- pk=pk,
+ workspace__slug=slug, project_id=project_id, pk=pk
)
# Check if the asset is uploaded
if not asset.is_uploaded:
return Response(
- {
- "error": "The requested asset could not be found.",
- },
+ {"error": "The requested asset could not be found."},
status=status.HTTP_404_NOT_FOUND,
)
# Get the presigned URL
storage = S3Storage(request=request)
# Generate a presigned URL to share an S3 object
- signed_url = storage.generate_presigned_url(
- object_name=asset.asset.name,
- )
+ signed_url = storage.generate_presigned_url(object_name=asset.asset.name)
# Redirect to the signed URL
return HttpResponseRedirect(signed_url)
class ProjectBulkAssetEndpoint(BaseAPIView):
-
def save_project_cover(self, asset, project_id):
project = Project.objects.get(id=project_id)
project.cover_image_asset_id = asset.id
@@ -767,60 +652,36 @@ class ProjectBulkAssetEndpoint(BaseAPIView):
# Check if the asset ids are provided
if not asset_ids:
return Response(
- {
- "error": "No asset ids provided.",
- },
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "No asset ids provided."}, status=status.HTTP_400_BAD_REQUEST
)
# get the asset id
- assets = FileAsset.objects.filter(
- id__in=asset_ids,
- workspace__slug=slug,
- )
+ assets = FileAsset.objects.filter(id__in=asset_ids, workspace__slug=slug)
# Get the first asset
asset = assets.first()
if not asset:
return Response(
- {
- "error": "The requested asset could not be found.",
- },
+ {"error": "The requested asset could not be found."},
status=status.HTTP_404_NOT_FOUND,
)
# Check if the asset is uploaded
if asset.entity_type == FileAsset.EntityTypeContext.PROJECT_COVER:
- assets.update(
- project_id=project_id,
- )
+ assets.update(project_id=project_id)
[self.save_project_cover(asset, project_id) for asset in assets]
if asset.entity_type == FileAsset.EntityTypeContext.ISSUE_DESCRIPTION:
- assets.update(
- issue_id=entity_id,
- )
+ assets.update(issue_id=entity_id)
- if (
- asset.entity_type
- == FileAsset.EntityTypeContext.COMMENT_DESCRIPTION
- ):
- assets.update(
- comment_id=entity_id,
- )
+ if asset.entity_type == FileAsset.EntityTypeContext.COMMENT_DESCRIPTION:
+ assets.update(comment_id=entity_id)
if asset.entity_type == FileAsset.EntityTypeContext.PAGE_DESCRIPTION:
- assets.update(
- page_id=entity_id,
- )
+ assets.update(page_id=entity_id)
- if (
- asset.entity_type
- == FileAsset.EntityTypeContext.DRAFT_ISSUE_DESCRIPTION
- ):
- assets.update(
- draft_issue_id=entity_id,
- )
+ if asset.entity_type == FileAsset.EntityTypeContext.DRAFT_ISSUE_DESCRIPTION:
+ assets.update(draft_issue_id=entity_id)
return Response(status=status.HTTP_204_NO_CONTENT)
diff --git a/apiserver/plane/app/views/base.py b/apiserver/plane/app/views/base.py
index 45488b64e..92c374966 100644
--- a/apiserver/plane/app/views/base.py
+++ b/apiserver/plane/app/views/base.py
@@ -43,18 +43,11 @@ class TimezoneMixin:
class BaseViewSet(TimezoneMixin, ModelViewSet, BasePaginator):
model = None
- permission_classes = [
- IsAuthenticated,
- ]
+ permission_classes = [IsAuthenticated]
- filter_backends = (
- DjangoFilterBackend,
- SearchFilter,
- )
+ filter_backends = (DjangoFilterBackend, SearchFilter)
- authentication_classes = [
- BaseSessionAuthentication,
- ]
+ authentication_classes = [BaseSessionAuthentication]
filterset_fields = []
@@ -65,9 +58,7 @@ class BaseViewSet(TimezoneMixin, ModelViewSet, BasePaginator):
return self.model.objects.all()
except Exception as e:
log_exception(e)
- raise APIException(
- "Please check the view", status.HTTP_400_BAD_REQUEST
- )
+ raise APIException("Please check the view", status.HTTP_400_BAD_REQUEST)
def handle_exception(self, exc):
"""
@@ -146,35 +137,24 @@ class BaseViewSet(TimezoneMixin, ModelViewSet, BasePaginator):
@property
def fields(self):
fields = [
- field
- for field in self.request.GET.get("fields", "").split(",")
- if field
+ field for field in self.request.GET.get("fields", "").split(",") if field
]
return fields if fields else None
@property
def expand(self):
expand = [
- expand
- for expand in self.request.GET.get("expand", "").split(",")
- if expand
+ expand for expand in self.request.GET.get("expand", "").split(",") if expand
]
return expand if expand else None
class BaseAPIView(TimezoneMixin, APIView, BasePaginator):
- permission_classes = [
- IsAuthenticated,
- ]
+ permission_classes = [IsAuthenticated]
- filter_backends = (
- DjangoFilterBackend,
- SearchFilter,
- )
+ filter_backends = (DjangoFilterBackend, SearchFilter)
- authentication_classes = [
- BaseSessionAuthentication,
- ]
+ authentication_classes = [BaseSessionAuthentication]
filterset_fields = []
@@ -251,17 +231,13 @@ class BaseAPIView(TimezoneMixin, APIView, BasePaginator):
@property
def fields(self):
fields = [
- field
- for field in self.request.GET.get("fields", "").split(",")
- if field
+ field for field in self.request.GET.get("fields", "").split(",") if field
]
return fields if fields else None
@property
def expand(self):
expand = [
- expand
- for expand in self.request.GET.get("expand", "").split(",")
- if expand
+ expand for expand in self.request.GET.get("expand", "").split(",") if expand
]
return expand if expand else None
diff --git a/apiserver/plane/app/views/cycle/archive.py b/apiserver/plane/app/views/cycle/archive.py
index d75e60e91..f58ad9aea 100644
--- a/apiserver/plane/app/views/cycle/archive.py
+++ b/apiserver/plane/app/views/cycle/archive.py
@@ -34,7 +34,6 @@ from .. import BaseAPIView
class CycleArchiveUnarchiveEndpoint(BaseAPIView):
-
def get_queryset(self):
favorite_subquery = UserFavorite.objects.filter(
user=self.request.user,
@@ -52,9 +51,7 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
)
.values("issue_cycle__cycle_id")
.annotate(
- backlog_estimate_point=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ backlog_estimate_point=Sum(Cast("estimate_point__value", FloatField()))
)
.values("backlog_estimate_point")[:1]
)
@@ -82,9 +79,7 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
)
.values("issue_cycle__cycle_id")
.annotate(
- started_estimate_point=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ started_estimate_point=Sum(Cast("estimate_point__value", FloatField()))
)
.values("started_estimate_point")[:1]
)
@@ -126,9 +121,7 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
)
.values("issue_cycle__cycle_id")
.annotate(
- total_estimate_points=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ total_estimate_points=Sum(Cast("estimate_point__value", FloatField()))
)
.values("total_estimate_points")[:1]
)
@@ -153,9 +146,7 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
.prefetch_related(
Prefetch(
"issue_cycle__issue__labels",
- queryset=Label.objects.only(
- "name", "color", "id"
- ).distinct(),
+ queryset=Label.objects.only("name", "color", "id").distinct(),
)
)
.annotate(is_favorite=Exists(favorite_subquery))
@@ -237,9 +228,7 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
& Q(end_date__gte=timezone.now()),
then=Value("CURRENT"),
),
- When(
- start_date__gt=timezone.now(), then=Value("UPCOMING")
- ),
+ When(start_date__gt=timezone.now(), then=Value("UPCOMING")),
When(end_date__lt=timezone.now(), then=Value("COMPLETED")),
When(
Q(start_date__isnull=True) & Q(end_date__isnull=True),
@@ -254,9 +243,7 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
ArrayAgg(
"issue_cycle__issue__assignees__id",
distinct=True,
- filter=~Q(
- issue_cycle__issue__assignees__id__isnull=True
- ),
+ filter=~Q(issue_cycle__issue__assignees__id__isnull=True),
),
Value([], output_field=ArrayField(UUIDField())),
)
@@ -265,48 +252,42 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
backlog_estimate_points=Coalesce(
Subquery(backlog_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
unstarted_estimate_points=Coalesce(
Subquery(unstarted_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
started_estimate_points=Coalesce(
Subquery(started_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
cancelled_estimate_points=Coalesce(
Subquery(cancelled_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
completed_estimate_points=Coalesce(
Subquery(completed_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
total_estimate_points=Coalesce(
- Subquery(total_estimate_point),
- Value(0, output_field=FloatField()),
- ),
+ Subquery(total_estimate_point), Value(0, output_field=FloatField())
+ )
)
.order_by("-is_favorite", "name")
.distinct()
)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def get(self, request, slug, project_id, pk=None):
if pk is None:
queryset = (
@@ -342,9 +323,7 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
return Response(queryset, status=status.HTTP_200_OK)
else:
queryset = (
- self.get_queryset()
- .filter(archived_at__isnull=False)
- .filter(pk=pk)
+ self.get_queryset().filter(archived_at__isnull=False).filter(pk=pk)
)
data = (
self.get_queryset()
@@ -437,9 +416,7 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
)
.values("display_name", "assignee_id", "avatar_url")
.annotate(
- total_estimates=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ total_estimates=Sum(Cast("estimate_point__value", FloatField()))
)
.annotate(
completed_estimates=Sum(
@@ -476,9 +453,7 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
.annotate(label_id=F("labels__id"))
.values("label_name", "color", "label_id")
.annotate(
- total_estimates=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ total_estimates=Sum(Cast("estimate_point__value", FloatField()))
)
.annotate(
completed_estimates=Sum(
@@ -509,14 +484,12 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
}
if data["start_date"] and data["end_date"]:
- data["estimate_distribution"]["completion_chart"] = (
- burndown_plot(
- queryset=queryset,
- slug=slug,
- project_id=project_id,
- plot_type="points",
- cycle_id=pk,
- )
+ data["estimate_distribution"]["completion_chart"] = burndown_plot(
+ queryset=queryset,
+ slug=slug,
+ project_id=project_id,
+ plot_type="points",
+ cycle_id=pk,
)
# Assignee Distribution
@@ -560,12 +533,8 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
)
.annotate(
total_issues=Count(
- "id",
- filter=Q(
- archived_at__isnull=True,
- is_draft=False,
- ),
- ),
+ "id", filter=Q(archived_at__isnull=True, is_draft=False)
+ )
)
.annotate(
completed_issues=Count(
@@ -604,12 +573,8 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
.values("label_name", "color", "label_id")
.annotate(
total_issues=Count(
- "id",
- filter=Q(
- archived_at__isnull=True,
- is_draft=False,
- ),
- ),
+ "id", filter=Q(archived_at__isnull=True, is_draft=False)
+ )
)
.annotate(
completed_issues=Count(
@@ -649,10 +614,7 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
cycle_id=pk,
)
- return Response(
- data,
- status=status.HTTP_200_OK,
- )
+ return Response(data, status=status.HTTP_200_OK)
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def post(self, request, slug, project_id, cycle_id):
@@ -675,8 +637,7 @@ class CycleArchiveUnarchiveEndpoint(BaseAPIView):
workspace__slug=slug,
).delete()
return Response(
- {"archived_at": str(cycle.archived_at)},
- status=status.HTTP_200_OK,
+ {"archived_at": str(cycle.archived_at)}, status=status.HTTP_200_OK
)
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
diff --git a/apiserver/plane/app/views/cycle/base.py b/apiserver/plane/app/views/cycle/base.py
index 006440010..61ea9eed4 100644
--- a/apiserver/plane/app/views/cycle/base.py
+++ b/apiserver/plane/app/views/cycle/base.py
@@ -89,9 +89,7 @@ class CycleViewSet(BaseViewSet):
.prefetch_related(
Prefetch(
"issue_cycle__issue__labels",
- queryset=Label.objects.only(
- "name", "color", "id"
- ).distinct(),
+ queryset=Label.objects.only("name", "color", "id").distinct(),
)
)
.annotate(is_favorite=Exists(favorite_subquery))
@@ -125,9 +123,7 @@ class CycleViewSet(BaseViewSet):
& Q(end_date__gte=timezone.now()),
then=Value("CURRENT"),
),
- When(
- start_date__gt=timezone.now(), then=Value("UPCOMING")
- ),
+ When(start_date__gt=timezone.now(), then=Value("UPCOMING")),
When(end_date__lt=timezone.now(), then=Value("COMPLETED")),
When(
Q(start_date__isnull=True) & Q(end_date__isnull=True),
@@ -142,9 +138,7 @@ class CycleViewSet(BaseViewSet):
ArrayAgg(
"issue_cycle__issue__assignees__id",
distinct=True,
- filter=~Q(
- issue_cycle__issue__assignees__id__isnull=True
- )
+ filter=~Q(issue_cycle__issue__assignees__id__isnull=True)
& (
Q(
issue_cycle__issue__issue_assignee__deleted_at__isnull=True
@@ -169,8 +163,7 @@ class CycleViewSet(BaseViewSet):
# Current Cycle
if cycle_view == "current":
queryset = queryset.filter(
- start_date__lte=timezone.now(),
- end_date__gte=timezone.now(),
+ start_date__lte=timezone.now(), end_date__gte=timezone.now()
)
data = queryset.values(
@@ -241,10 +234,7 @@ class CycleViewSet(BaseViewSet):
):
serializer = CycleWriteSerializer(data=request.data)
if serializer.is_valid():
- serializer.save(
- project_id=project_id,
- owned_by=request.user,
- )
+ serializer.save(project_id=project_id, owned_by=request.user)
cycle = (
self.get_queryset()
.filter(pk=serializer.data["id"])
@@ -288,9 +278,7 @@ class CycleViewSet(BaseViewSet):
origin=request.META.get("HTTP_ORIGIN"),
)
return Response(cycle, status=status.HTTP_201_CREATED)
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(
{
@@ -321,9 +309,7 @@ class CycleViewSet(BaseViewSet):
if "sort_order" in request_data:
# Can only change sort order for a completed cycle``
request_data = {
- "sort_order": request_data.get(
- "sort_order", cycle.sort_order
- )
+ "sort_order": request_data.get("sort_order", cycle.sort_order)
}
else:
return Response(
@@ -333,9 +319,7 @@ class CycleViewSet(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST,
)
- serializer = CycleWriteSerializer(
- cycle, data=request.data, partial=True
- )
+ serializer = CycleWriteSerializer(cycle, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
cycle = queryset.values(
@@ -379,16 +363,9 @@ class CycleViewSet(BaseViewSet):
return Response(cycle, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def retrieve(self, request, slug, project_id, pk):
- queryset = (
- self.get_queryset().filter(archived_at__isnull=True).filter(pk=pk)
- )
+ queryset = self.get_queryset().filter(archived_at__isnull=True).filter(pk=pk)
data = (
self.get_queryset()
.filter(pk=pk)
@@ -436,8 +413,7 @@ class CycleViewSet(BaseViewSet):
if data is None:
return Response(
- {"error": "Cycle not found"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Cycle not found"}, status=status.HTTP_404_NOT_FOUND
)
queryset = queryset.first()
@@ -449,16 +425,11 @@ class CycleViewSet(BaseViewSet):
user_id=request.user.id,
project_id=project_id,
)
- return Response(
- data,
- status=status.HTTP_200_OK,
- )
+ return Response(data, status=status.HTTP_200_OK)
@allow_permission([ROLE.ADMIN], creator=True, model=Cycle)
def destroy(self, request, slug, project_id, pk):
- cycle = Cycle.objects.get(
- workspace__slug=slug, project_id=project_id, pk=pk
- )
+ cycle = Cycle.objects.get(workspace__slug=slug, project_id=project_id, pk=pk)
if cycle.owned_by_id != request.user.id and not (
ProjectMember.objects.filter(
workspace__slug=slug,
@@ -474,9 +445,9 @@ class CycleViewSet(BaseViewSet):
)
cycle_issues = list(
- CycleIssue.objects.filter(
- cycle_id=self.kwargs.get("pk")
- ).values_list("issue", flat=True)
+ CycleIssue.objects.filter(cycle_id=self.kwargs.get("pk")).values_list(
+ "issue", flat=True
+ )
)
issue_activity.delay(
@@ -707,9 +678,7 @@ class TransferCycleIssueEndpoint(BaseAPIView):
)
.values("display_name", "assignee_id", "avatar_url")
.annotate(
- total_estimates=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ total_estimates=Sum(Cast("estimate_point__value", FloatField()))
)
.annotate(
completed_estimates=Sum(
@@ -738,9 +707,7 @@ class TransferCycleIssueEndpoint(BaseAPIView):
{
"display_name": item["display_name"],
"assignee_id": (
- str(item["assignee_id"])
- if item["assignee_id"]
- else None
+ str(item["assignee_id"]) if item["assignee_id"] else None
),
"avatar": item.get("avatar"),
"avatar_url": item.get("avatar_url"),
@@ -763,9 +730,7 @@ class TransferCycleIssueEndpoint(BaseAPIView):
.annotate(label_id=F("labels__id"))
.values("label_name", "color", "label_id")
.annotate(
- total_estimates=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ total_estimates=Sum(Cast("estimate_point__value", FloatField()))
)
.annotate(
completed_estimates=Sum(
@@ -802,9 +767,7 @@ class TransferCycleIssueEndpoint(BaseAPIView):
{
"label_name": item["label_name"],
"color": item["color"],
- "label_id": (
- str(item["label_id"]) if item["label_id"] else None
- ),
+ "label_id": (str(item["label_id"]) if item["label_id"] else None),
"total_estimates": item["total_estimates"],
"completed_estimates": item["completed_estimates"],
"pending_estimates": item["pending_estimates"],
@@ -835,8 +798,7 @@ class TransferCycleIssueEndpoint(BaseAPIView):
),
# If `avatar_asset` is None, fall back to using `avatar` field directly
When(
- assignees__avatar_asset__isnull=True,
- then="assignees__avatar",
+ assignees__avatar_asset__isnull=True, then="assignees__avatar"
),
default=Value(None),
output_field=models.CharField(),
@@ -845,12 +807,8 @@ class TransferCycleIssueEndpoint(BaseAPIView):
.values("display_name", "assignee_id", "avatar_url")
.annotate(
total_issues=Count(
- "id",
- filter=Q(
- archived_at__isnull=True,
- is_draft=False,
- ),
- ),
+ "id", filter=Q(archived_at__isnull=True, is_draft=False)
+ )
)
.annotate(
completed_issues=Count(
@@ -904,12 +862,8 @@ class TransferCycleIssueEndpoint(BaseAPIView):
.values("label_name", "color", "label_id")
.annotate(
total_issues=Count(
- "id",
- filter=Q(
- archived_at__isnull=True,
- is_draft=False,
- ),
- ),
+ "id", filter=Q(archived_at__isnull=True, is_draft=False)
+ )
)
.annotate(
completed_issues=Count(
@@ -939,9 +893,7 @@ class TransferCycleIssueEndpoint(BaseAPIView):
{
"label_name": item["label_name"],
"color": item["color"],
- "label_id": (
- str(item["label_id"]) if item["label_id"] else None
- ),
+ "label_id": (str(item["label_id"]) if item["label_id"] else None),
"total_issues": item["total_issues"],
"completed_issues": item["completed_issues"],
"pending_issues": item["pending_issues"],
@@ -986,10 +938,7 @@ class TransferCycleIssueEndpoint(BaseAPIView):
}
current_cycle.save(update_fields=["progress_snapshot"])
- if (
- new_cycle.end_date is not None
- and new_cycle.end_date < timezone.now()
- ):
+ if new_cycle.end_date is not None and new_cycle.end_date < timezone.now():
return Response(
{
"error": "The cycle where the issues are transferred is already completed"
@@ -1052,9 +1001,7 @@ class CycleUserPropertiesEndpoint(BaseAPIView):
workspace__slug=slug,
)
- cycle_properties.filters = request.data.get(
- "filters", cycle_properties.filters
- )
+ cycle_properties.filters = request.data.get("filters", cycle_properties.filters)
cycle_properties.display_filters = request.data.get(
"display_filters", cycle_properties.display_filters
)
@@ -1089,9 +1036,7 @@ class CycleProgressEndpoint(BaseAPIView):
workspace__slug=slug,
project_id=project_id,
)
- .annotate(
- value_as_float=Cast("estimate_point__value", FloatField())
- )
+ .annotate(value_as_float=Cast("estimate_point__value", FloatField()))
.aggregate(
backlog_estimate_point=Sum(
Case(
@@ -1129,9 +1074,7 @@ class CycleProgressEndpoint(BaseAPIView):
)
),
total_estimate_points=Sum(
- "value_as_float",
- default=Value(0),
- output_field=FloatField(),
+ "value_as_float", default=Value(0), output_field=FloatField()
),
)
)
@@ -1185,17 +1128,13 @@ class CycleProgressEndpoint(BaseAPIView):
return Response(
{
- "backlog_estimate_points": aggregate_estimates[
- "backlog_estimate_point"
- ]
+ "backlog_estimate_points": aggregate_estimates["backlog_estimate_point"]
or 0,
"unstarted_estimate_points": aggregate_estimates[
"unstarted_estimate_point"
]
or 0,
- "started_estimate_points": aggregate_estimates[
- "started_estimate_point"
- ]
+ "started_estimate_points": aggregate_estimates["started_estimate_point"]
or 0,
"cancelled_estimate_points": aggregate_estimates[
"cancelled_estimate_point"
@@ -1205,9 +1144,7 @@ class CycleProgressEndpoint(BaseAPIView):
"completed_estimate_points"
]
or 0,
- "total_estimate_points": aggregate_estimates[
- "total_estimate_points"
- ],
+ "total_estimate_points": aggregate_estimates["total_estimate_points"],
"backlog_issues": backlog_issues,
"total_issues": total_issues,
"completed_issues": completed_issues,
@@ -1220,15 +1157,12 @@ class CycleProgressEndpoint(BaseAPIView):
class CycleAnalyticsEndpoint(BaseAPIView):
-
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def get(self, request, slug, project_id, cycle_id):
analytic_type = request.GET.get("type", "issues")
cycle = (
Cycle.objects.filter(
- workspace__slug=slug,
- project_id=project_id,
- id=cycle_id,
+ workspace__slug=slug, project_id=project_id, id=cycle_id
)
.annotate(
total_issues=Count(
@@ -1294,9 +1228,7 @@ class CycleAnalyticsEndpoint(BaseAPIView):
)
.values("display_name", "assignee_id", "avatar_url")
.annotate(
- total_estimates=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ total_estimates=Sum(Cast("estimate_point__value", FloatField()))
)
.annotate(
completed_estimates=Sum(
@@ -1333,9 +1265,7 @@ class CycleAnalyticsEndpoint(BaseAPIView):
.annotate(label_id=F("labels__id"))
.values("label_name", "color", "label_id")
.annotate(
- total_estimates=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ total_estimates=Sum(Cast("estimate_point__value", FloatField()))
)
.annotate(
completed_estimates=Sum(
@@ -1402,7 +1332,7 @@ class CycleAnalyticsEndpoint(BaseAPIView):
total_issues=Count(
"assignee_id",
filter=Q(archived_at__isnull=True, is_draft=False),
- ),
+ )
)
.annotate(
completed_issues=Count(
@@ -1440,8 +1370,7 @@ class CycleAnalyticsEndpoint(BaseAPIView):
.values("label_name", "color", "label_id")
.annotate(
total_issues=Count(
- "label_id",
- filter=Q(archived_at__isnull=True, is_draft=False),
+ "label_id", filter=Q(archived_at__isnull=True, is_draft=False)
)
)
.annotate(
diff --git a/apiserver/plane/app/views/cycle/issue.py b/apiserver/plane/app/views/cycle/issue.py
index 6066d9045..6e131d428 100644
--- a/apiserver/plane/app/views/cycle/issue.py
+++ b/apiserver/plane/app/views/cycle/issue.py
@@ -15,17 +15,9 @@ from rest_framework.response import Response
# Module imports
from .. import BaseViewSet
-from plane.app.serializers import (
- CycleIssueSerializer,
-)
+from plane.app.serializers import CycleIssueSerializer
from plane.bgtasks.issue_activities_task import issue_activity
-from plane.db.models import (
- Cycle,
- CycleIssue,
- Issue,
- FileAsset,
- IssueLink,
-)
+from plane.db.models import Cycle, CycleIssue, Issue, FileAsset, IssueLink
from plane.utils.grouper import (
issue_group_values,
issue_on_results,
@@ -33,14 +25,10 @@ from plane.utils.grouper import (
)
from plane.utils.issue_filters import issue_filters
from plane.utils.order_queryset import order_issue_queryset
-from plane.utils.paginator import (
- GroupedOffsetPaginator,
- SubGroupedOffsetPaginator,
-)
+from plane.utils.paginator import GroupedOffsetPaginator, SubGroupedOffsetPaginator
from plane.app.permissions import allow_permission, ROLE
-
class CycleIssueViewSet(BaseViewSet):
serializer_class = CycleIssueSerializer
model = CycleIssue
@@ -48,19 +36,14 @@ class CycleIssueViewSet(BaseViewSet):
webhook_event = "cycle_issue"
bulk = True
- filterset_fields = [
- "issue__labels__id",
- "issue__assignees__id",
- ]
+ filterset_fields = ["issue__labels__id", "issue__assignees__id"]
def get_queryset(self):
return self.filter_queryset(
super()
.get_queryset()
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("issue_id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("issue_id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -82,29 +65,20 @@ class CycleIssueViewSet(BaseViewSet):
)
@method_decorator(gzip_page)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def list(self, request, slug, project_id, cycle_id):
order_by_param = request.GET.get("order_by", "created_at")
filters = issue_filters(request.query_params, "GET")
issue_queryset = (
Issue.issue_objects.filter(
- issue_cycle__cycle_id=cycle_id,
- issue_cycle__deleted_at__isnull=True,
+ issue_cycle__cycle_id=cycle_id, issue_cycle__deleted_at__isnull=True
)
.filter(project_id=project_id)
.filter(workspace__slug=slug)
.filter(**filters)
.select_related("workspace", "project", "state", "parent")
.prefetch_related(
- "assignees",
- "labels",
- "issue_module__module",
- "issue_cycle__cycle",
+ "assignees", "labels", "issue_module__module", "issue_cycle__cycle"
)
.filter(**filters)
.annotate(
@@ -130,9 +104,7 @@ class CycleIssueViewSet(BaseViewSet):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -144,8 +116,7 @@ class CycleIssueViewSet(BaseViewSet):
issue_queryset = issue_queryset.filter(**filters)
# Issue queryset
issue_queryset, order_by_param = order_issue_queryset(
- issue_queryset=issue_queryset,
- order_by_param=order_by_param,
+ issue_queryset=issue_queryset, order_by_param=order_by_param
)
# Group by
@@ -154,9 +125,7 @@ class CycleIssueViewSet(BaseViewSet):
# issue queryset
issue_queryset = issue_queryset_grouper(
- queryset=issue_queryset,
- group_by=group_by,
- sub_group_by=sub_group_by,
+ queryset=issue_queryset, group_by=group_by, sub_group_by=sub_group_by
)
if group_by:
@@ -176,9 +145,7 @@ class CycleIssueViewSet(BaseViewSet):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=SubGroupedOffsetPaginator,
group_by_fields=issue_group_values(
@@ -212,9 +179,7 @@ class CycleIssueViewSet(BaseViewSet):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=GroupedOffsetPaginator,
group_by_fields=issue_group_values(
@@ -250,8 +215,7 @@ class CycleIssueViewSet(BaseViewSet):
if not issues:
return Response(
- {"error": "Issues are required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Issues are required"}, status=status.HTTP_400_BAD_REQUEST
)
cycle = Cycle.objects.get(
@@ -268,13 +232,9 @@ class CycleIssueViewSet(BaseViewSet):
# Get all CycleIssues already created
cycle_issues = list(
- CycleIssue.objects.filter(
- ~Q(cycle_id=cycle_id), issue_id__in=issues
- )
+ CycleIssue.objects.filter(~Q(cycle_id=cycle_id), issue_id__in=issues)
)
- existing_issues = [
- str(cycle_issue.issue_id) for cycle_issue in cycle_issues
- ]
+ existing_issues = [str(cycle_issue.issue_id) for cycle_issue in cycle_issues]
new_issues = list(set(issues) - set(existing_issues))
# New issues to create
@@ -313,9 +273,7 @@ class CycleIssueViewSet(BaseViewSet):
)
# Update the cycle issues
- CycleIssue.objects.bulk_update(
- updated_records, ["cycle_id"], batch_size=100
- )
+ CycleIssue.objects.bulk_update(updated_records, ["cycle_id"], batch_size=100)
# Capture Issue Activity
issue_activity.delay(
type="cycle.activity.created",
diff --git a/apiserver/plane/app/views/dashboard/base.py b/apiserver/plane/app/views/dashboard/base.py
index 238cb67a5..8ccce092e 100644
--- a/apiserver/plane/app/views/dashboard/base.py
+++ b/apiserver/plane/app/views/dashboard/base.py
@@ -227,7 +227,7 @@ def dashboard_assigned_issues(self, request, slug):
distinct=True,
filter=Q(
~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ & Q(label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -260,10 +260,7 @@ def dashboard_assigned_issues(self, request, slug):
)
if WorkspaceMember.objects.filter(
- workspace__slug=slug,
- member=request.user,
- role=5,
- is_active=True,
+ workspace__slug=slug, member=request.user, role=5, is_active=True
).exists():
assigned_issues = assigned_issues.filter(created_by=request.user)
@@ -271,10 +268,7 @@ def dashboard_assigned_issues(self, request, slug):
priority_order = ["urgent", "high", "medium", "low", "none"]
assigned_issues = assigned_issues.annotate(
priority_order=Case(
- *[
- When(priority=p, then=Value(i))
- for i, p in enumerate(priority_order)
- ],
+ *[When(priority=p, then=Value(i)) for i, p in enumerate(priority_order)],
output_field=CharField(),
)
).order_by("priority_order")
@@ -300,9 +294,7 @@ def dashboard_assigned_issues(self, request, slug):
completed_issues_count = assigned_issues.filter(
state__group__in=["completed"]
).count()
- completed_issues = assigned_issues.filter(
- state__group__in=["completed"]
- )[:5]
+ completed_issues = assigned_issues.filter(state__group__in=["completed"])[:5]
return Response(
{
"issues": IssueSerializer(
@@ -407,7 +399,7 @@ def dashboard_created_issues(self, request, slug):
distinct=True,
filter=Q(
~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ & Q(label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -444,10 +436,7 @@ def dashboard_created_issues(self, request, slug):
priority_order = ["urgent", "high", "medium", "low", "none"]
created_issues = created_issues.annotate(
priority_order=Case(
- *[
- When(priority=p, then=Value(i))
- for i, p in enumerate(priority_order)
- ],
+ *[When(priority=p, then=Value(i)) for i, p in enumerate(priority_order)],
output_field=CharField(),
)
).order_by("priority_order")
@@ -473,9 +462,7 @@ def dashboard_created_issues(self, request, slug):
completed_issues_count = created_issues.filter(
state__group__in=["completed"]
).count()
- completed_issues = created_issues.filter(
- state__group__in=["completed"]
- )[:5]
+ completed_issues = created_issues.filter(state__group__in=["completed"])[:5]
return Response(
{
"issues": IssueSerializer(completed_issues, many=True).data,
@@ -530,10 +517,7 @@ def dashboard_issues_by_state_groups(self, request, slug):
extra_filters = {}
if WorkspaceMember.objects.filter(
- workspace__slug=slug,
- member=request.user,
- role=5,
- is_active=True,
+ workspace__slug=slug, member=request.user, role=5, is_active=True
).exists():
extra_filters = {"created_by": request.user}
@@ -570,10 +554,7 @@ def dashboard_issues_by_priority(self, request, slug):
extra_filters = {}
if WorkspaceMember.objects.filter(
- workspace__slug=slug,
- member=request.user,
- role=5,
- is_active=True,
+ workspace__slug=slug, member=request.user, role=5, is_active=True
).exists():
extra_filters = {"created_by": request.user}
@@ -598,8 +579,7 @@ def dashboard_issues_by_priority(self, request, slug):
# Prepare output including all groups with their counts
output_data = [
- {"priority": group, "count": count}
- for group, count in all_groups.items()
+ {"priority": group, "count": count} for group, count in all_groups.items()
]
return Response(output_data, status=status.HTTP_200_OK)
@@ -616,8 +596,7 @@ def dashboard_recent_activity(self, request, slug):
).select_related("actor", "workspace", "issue", "project")[:8]
return Response(
- IssueActivitySerializer(queryset, many=True).data,
- status=status.HTTP_200_OK,
+ IssueActivitySerializer(queryset, many=True).data, status=status.HTTP_200_OK
)
@@ -647,22 +626,14 @@ def dashboard_recent_projects(self, request, slug):
).exclude(id__in=unique_project_ids)
# Append additional project IDs to the existing list
- unique_project_ids.update(
- additional_projects.values_list("id", flat=True)
- )
+ unique_project_ids.update(additional_projects.values_list("id", flat=True))
- return Response(
- list(unique_project_ids)[:4],
- status=status.HTTP_200_OK,
- )
+ return Response(list(unique_project_ids)[:4], status=status.HTTP_200_OK)
def dashboard_recent_collaborators(self, request, slug):
project_members_with_activities = (
- WorkspaceMember.objects.filter(
- workspace__slug=slug,
- is_active=True,
- )
+ WorkspaceMember.objects.filter(workspace__slug=slug, is_active=True)
.annotate(
active_issue_count=Count(
Case(
@@ -687,10 +658,7 @@ def dashboard_recent_collaborators(self, request, slug):
.order_by("-active_issue_count")
.distinct()
)
- return Response(
- (project_members_with_activities),
- status=status.HTTP_200_OK,
- )
+ return Response((project_members_with_activities), status=status.HTTP_200_OK)
class DashboardEndpoint(BaseAPIView):
@@ -739,14 +707,13 @@ class DashboardEndpoint(BaseAPIView):
updated_dashboard_widgets = []
for widget_key in widgets_to_fetch:
- widget = Widget.objects.filter(
- key=widget_key
- ).values_list("id", flat=True)
+ widget = Widget.objects.filter(key=widget_key).values_list(
+ "id", flat=True
+ )
if widget:
updated_dashboard_widgets.append(
DashboardWidget(
- widget_id=widget,
- dashboard_id=dashboard.id,
+ widget_id=widget, dashboard_id=dashboard.id
)
)
@@ -813,11 +780,7 @@ class DashboardEndpoint(BaseAPIView):
func = WIDGETS_MAPPER.get(widget_key)
if func is not None:
- response = func(
- self,
- request=request,
- slug=slug,
- )
+ response = func(self, request=request, slug=slug)
if isinstance(response, Response):
return response
@@ -830,8 +793,7 @@ class DashboardEndpoint(BaseAPIView):
class WidgetsEndpoint(BaseAPIView):
def patch(self, request, dashboard_id, widget_id):
dashboard_widget = DashboardWidget.objects.filter(
- widget_id=widget_id,
- dashboard_id=dashboard_id,
+ widget_id=widget_id, dashboard_id=dashboard_id
).first()
dashboard_widget.is_visible = request.data.get(
"is_visible", dashboard_widget.is_visible
@@ -839,10 +801,6 @@ class WidgetsEndpoint(BaseAPIView):
dashboard_widget.sort_order = request.data.get(
"sort_order", dashboard_widget.sort_order
)
- dashboard_widget.filters = request.data.get(
- "filters", dashboard_widget.filters
- )
+ dashboard_widget.filters = request.data.get("filters", dashboard_widget.filters)
dashboard_widget.save()
- return Response(
- {"message": "successfully updated"}, status=status.HTTP_200_OK
- )
+ return Response({"message": "successfully updated"}, status=status.HTTP_200_OK)
diff --git a/apiserver/plane/app/views/error_404.py b/apiserver/plane/app/views/error_404.py
index 3c31474e0..97c3c59f7 100644
--- a/apiserver/plane/app/views/error_404.py
+++ b/apiserver/plane/app/views/error_404.py
@@ -1,5 +1,6 @@
# views.py
from django.http import JsonResponse
+
def custom_404_view(request, exception=None):
return JsonResponse({"error": "Page not found."}, status=404)
diff --git a/apiserver/plane/app/views/estimate/base.py b/apiserver/plane/app/views/estimate/base.py
index 80943c05e..c0e931ca6 100644
--- a/apiserver/plane/app/views/estimate/base.py
+++ b/apiserver/plane/app/views/estimate/base.py
@@ -11,11 +11,7 @@ from rest_framework import status
# Module imports
from ..base import BaseViewSet, BaseAPIView
-from plane.app.permissions import (
- ProjectEntityPermission,
- allow_permission,
- ROLE,
-)
+from plane.app.permissions import ProjectEntityPermission, allow_permission, ROLE
from plane.db.models import Project, Estimate, EstimatePoint, Issue
from plane.app.serializers import (
EstimateSerializer,
@@ -32,13 +28,7 @@ def generate_random_name(length=10):
class ProjectEstimatePointEndpoint(BaseAPIView):
-
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def get(self, request, slug, project_id):
project = Project.objects.get(workspace__slug=slug, pk=project_id)
if project.estimate_id is not None:
@@ -53,17 +43,13 @@ class ProjectEstimatePointEndpoint(BaseAPIView):
class BulkEstimatePointEndpoint(BaseViewSet):
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
model = Estimate
serializer_class = EstimateSerializer
def list(self, request, slug, project_id):
estimates = (
- Estimate.objects.filter(
- workspace__slug=slug, project_id=project_id
- )
+ Estimate.objects.filter(workspace__slug=slug, project_id=project_id)
.prefetch_related("points")
.select_related("workspace", "project")
)
@@ -91,9 +77,7 @@ class BulkEstimatePointEndpoint(BaseViewSet):
data=request.data.get("estimate_points"), many=True
)
if not serializer.is_valid():
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
estimate_points = EstimatePoint.objects.bulk_create(
[
@@ -121,16 +105,12 @@ class BulkEstimatePointEndpoint(BaseViewSet):
pk=estimate_id, workspace__slug=slug, project_id=project_id
)
serializer = EstimateReadSerializer(estimate)
- return Response(
- serializer.data,
- status=status.HTTP_200_OK,
- )
+ return Response(serializer.data, status=status.HTTP_200_OK)
@invalidate_cache(
path="/api/workspaces/:slug/estimates/", url_params=True, user=False
)
def partial_update(self, request, slug, project_id, estimate_id):
-
if not len(request.data.get("estimate_points", [])):
return Response(
{"error": "Estimate points are required"},
@@ -140,20 +120,15 @@ class BulkEstimatePointEndpoint(BaseViewSet):
estimate = Estimate.objects.get(pk=estimate_id)
if request.data.get("estimate"):
- estimate.name = request.data.get("estimate").get(
- "name", estimate.name
- )
- estimate.type = request.data.get("estimate").get(
- "type", estimate.type
- )
+ estimate.name = request.data.get("estimate").get("name", estimate.name)
+ estimate.type = request.data.get("estimate").get("type", estimate.type)
estimate.save()
estimate_points_data = request.data.get("estimate_points", [])
estimate_points = EstimatePoint.objects.filter(
pk__in=[
- estimate_point.get("id")
- for estimate_point in estimate_points_data
+ estimate_point.get("id") for estimate_point in estimate_points_data
],
workspace__slug=slug,
project_id=project_id,
@@ -178,16 +153,11 @@ class BulkEstimatePointEndpoint(BaseViewSet):
updated_estimate_points.append(estimate_point)
EstimatePoint.objects.bulk_update(
- updated_estimate_points,
- ["key", "value"],
- batch_size=10,
+ updated_estimate_points, ["key", "value"], batch_size=10
)
estimate_serializer = EstimateReadSerializer(estimate)
- return Response(
- estimate_serializer.data,
- status=status.HTTP_200_OK,
- )
+ return Response(estimate_serializer.data, status=status.HTTP_200_OK)
@invalidate_cache(
path="/api/workspaces/:slug/estimates/", url_params=True, user=False
@@ -201,7 +171,6 @@ class BulkEstimatePointEndpoint(BaseViewSet):
class EstimatePointEndpoint(BaseViewSet):
-
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def create(self, request, slug, project_id, estimate_id):
# TODO: add a key validation if the same key already exists
@@ -213,18 +182,13 @@ class EstimatePointEndpoint(BaseViewSet):
key = request.data.get("key", 0)
value = request.data.get("value", "")
estimate_point = EstimatePoint.objects.create(
- estimate_id=estimate_id,
- project_id=project_id,
- key=key,
- value=value,
+ estimate_id=estimate_id, project_id=project_id, key=key, value=value
)
serializer = EstimatePointSerializer(estimate_point).data
return Response(serializer, status=status.HTTP_200_OK)
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
- def partial_update(
- self, request, slug, project_id, estimate_id, estimate_point_id
- ):
+ def partial_update(self, request, slug, project_id, estimate_id, estimate_point_id):
# TODO: add a key validation if the same key already exists
estimate_point = EstimatePoint.objects.get(
pk=estimate_point_id,
@@ -236,21 +200,15 @@ class EstimatePointEndpoint(BaseViewSet):
estimate_point, data=request.data, partial=True
)
if not serializer.is_valid():
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
- def destroy(
- self, request, slug, project_id, estimate_id, estimate_point_id
- ):
+ def destroy(self, request, slug, project_id, estimate_id, estimate_point_id):
new_estimate_id = request.data.get("new_estimate_id", None)
estimate_points = EstimatePoint.objects.filter(
- estimate_id=estimate_id,
- project_id=project_id,
- workspace__slug=slug,
+ estimate_id=estimate_id, project_id=project_id, workspace__slug=slug
)
# update all the issues with the new estimate
if new_estimate_id:
@@ -265,10 +223,8 @@ class EstimatePointEndpoint(BaseViewSet):
requested_data=json.dumps(
{
"estimate_point": (
- str(new_estimate_id)
- if new_estimate_id
- else None
- ),
+ str(new_estimate_id) if new_estimate_id else None
+ )
}
),
actor_id=str(request.user.id),
@@ -280,7 +236,7 @@ class EstimatePointEndpoint(BaseViewSet):
str(issue.estimate_point_id)
if issue.estimate_point_id
else None
- ),
+ )
}
),
epoch=int(timezone.now().timestamp()),
@@ -295,11 +251,7 @@ class EstimatePointEndpoint(BaseViewSet):
for issue in issues:
issue_activity.delay(
type="issue.activity.updated",
- requested_data=json.dumps(
- {
- "estimate_point": None,
- }
- ),
+ requested_data=json.dumps({"estimate_point": None}),
actor_id=str(request.user.id),
issue_id=issue.id,
project_id=str(project_id),
@@ -309,16 +261,14 @@ class EstimatePointEndpoint(BaseViewSet):
str(issue.estimate_point_id)
if issue.estimate_point_id
else None
- ),
+ )
}
),
epoch=int(timezone.now().timestamp()),
)
# delete the estimate point
- old_estimate_point = EstimatePoint.objects.filter(
- pk=estimate_point_id
- ).first()
+ old_estimate_point = EstimatePoint.objects.filter(pk=estimate_point_id).first()
# rearrange the estimate points
updated_estimate_points = []
@@ -328,9 +278,7 @@ class EstimatePointEndpoint(BaseViewSet):
updated_estimate_points.append(estimate_point)
EstimatePoint.objects.bulk_update(
- updated_estimate_points,
- ["key"],
- batch_size=10,
+ updated_estimate_points, ["key"], batch_size=10
)
old_estimate_point.delete()
diff --git a/apiserver/plane/app/views/exporter/base.py b/apiserver/plane/app/views/exporter/base.py
index 39255bd1e..8e683e56d 100644
--- a/apiserver/plane/app/views/exporter/base.py
+++ b/apiserver/plane/app/views/exporter/base.py
@@ -51,9 +51,7 @@ class ExportIssuesEndpoint(BaseAPIView):
slug=slug,
)
return Response(
- {
- "message": "Once the export is ready you will be able to download it"
- },
+ {"message": "Once the export is ready you will be able to download it"},
status=status.HTTP_200_OK,
)
else:
@@ -62,18 +60,13 @@ class ExportIssuesEndpoint(BaseAPIView):
status=status.HTTP_400_BAD_REQUEST,
)
- @allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE"
- )
+ @allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def get(self, request, slug):
exporter_history = ExporterHistory.objects.filter(
- workspace__slug=slug,
- type="issue_exports",
+ workspace__slug=slug, type="issue_exports"
).select_related("workspace", "initiated_by")
- if request.GET.get("per_page", False) and request.GET.get(
- "cursor", False
- ):
+ if request.GET.get("per_page", False) and request.GET.get("cursor", False):
return self.paginate(
order_by=request.GET.get("order_by", "-created_at"),
request=request,
diff --git a/apiserver/plane/app/views/external/base.py b/apiserver/plane/app/views/external/base.py
index 6ae3f37ba..1dfbc421a 100644
--- a/apiserver/plane/app/views/external/base.py
+++ b/apiserver/plane/app/views/external/base.py
@@ -13,15 +13,11 @@ from rest_framework import status
from ..base import BaseAPIView
from plane.app.permissions import allow_permission, ROLE
from plane.db.models import Workspace, Project
-from plane.app.serializers import (
- ProjectLiteSerializer,
- WorkspaceLiteSerializer,
-)
+from plane.app.serializers import ProjectLiteSerializer, WorkspaceLiteSerializer
from plane.license.utils.instance_value import get_configuration_value
class GPTIntegrationEndpoint(BaseAPIView):
-
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def post(self, request, slug, project_id):
OPENAI_API_KEY, GPT_ENGINE = get_configuration_value(
@@ -50,19 +46,15 @@ class GPTIntegrationEndpoint(BaseAPIView):
if not task:
return Response(
- {"error": "Task is required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Task is required"}, status=status.HTTP_400_BAD_REQUEST
)
final_text = task + "\n" + prompt
- client = OpenAI(
- api_key=OPENAI_API_KEY,
- )
+ client = OpenAI(api_key=OPENAI_API_KEY)
response = client.chat.completions.create(
- model=GPT_ENGINE,
- messages=[{"role": "user", "content": final_text}],
+ model=GPT_ENGINE, messages=[{"role": "user", "content": final_text}]
)
workspace = Workspace.objects.get(slug=slug)
@@ -82,10 +74,7 @@ class GPTIntegrationEndpoint(BaseAPIView):
class WorkspaceGPTIntegrationEndpoint(BaseAPIView):
-
- @allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE"
- )
+ @allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def post(self, request, slug):
OPENAI_API_KEY, GPT_ENGINE = get_configuration_value(
[
@@ -113,29 +102,21 @@ class WorkspaceGPTIntegrationEndpoint(BaseAPIView):
if not task:
return Response(
- {"error": "Task is required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Task is required"}, status=status.HTTP_400_BAD_REQUEST
)
final_text = task + "\n" + prompt
- client = OpenAI(
- api_key=OPENAI_API_KEY,
- )
+ client = OpenAI(api_key=OPENAI_API_KEY)
response = client.chat.completions.create(
- model=GPT_ENGINE,
- messages=[{"role": "user", "content": final_text}],
+ model=GPT_ENGINE, messages=[{"role": "user", "content": final_text}]
)
text = response.choices[0].message.content.strip()
text_html = text.replace("\n", "
")
return Response(
- {
- "response": text,
- "response_html": text_html,
- },
- status=status.HTTP_200_OK,
+ {"response": text, "response_html": text_html}, status=status.HTTP_200_OK
)
@@ -164,9 +145,7 @@ class UnsplashEndpoint(BaseAPIView):
else f"https://api.unsplash.com/photos/?client_id={UNSPLASH_ACCESS_KEY}&page={page}&per_page={per_page}"
)
- headers = {
- "Content-Type": "application/json",
- }
+ headers = {"Content-Type": "application/json"}
resp = requests.get(url=url, headers=headers)
return Response(resp.json(), status=resp.status_code)
diff --git a/apiserver/plane/app/views/intake/base.py b/apiserver/plane/app/views/intake/base.py
index 9e420c007..8647117c5 100644
--- a/apiserver/plane/app/views/intake/base.py
+++ b/apiserver/plane/app/views/intake/base.py
@@ -40,7 +40,6 @@ from plane.bgtasks.issue_activities_task import issue_activity
class IntakeViewSet(BaseViewSet):
-
serializer_class = IntakeSerializer
model = Intake
@@ -54,8 +53,7 @@ class IntakeViewSet(BaseViewSet):
)
.annotate(
pending_issue_count=Count(
- "issue_intake",
- filter=Q(issue_intake__status=-2),
+ "issue_intake", filter=Q(issue_intake__status=-2)
)
)
.select_related("workspace", "project")
@@ -64,10 +62,7 @@ class IntakeViewSet(BaseViewSet):
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def list(self, request, slug, project_id):
intake = self.get_queryset().first()
- return Response(
- IntakeSerializer(intake).data,
- status=status.HTTP_200_OK,
- )
+ return Response(IntakeSerializer(intake).data, status=status.HTTP_200_OK)
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def perform_create(self, serializer):
@@ -89,13 +84,10 @@ class IntakeViewSet(BaseViewSet):
class IntakeIssueViewSet(BaseViewSet):
-
serializer_class = IntakeIssueSerializer
model = IntakeIssue
- filterset_fields = [
- "statulls",
- ]
+ filterset_fields = ["statulls"]
def get_queryset(self):
return (
@@ -136,9 +128,7 @@ class IntakeIssueViewSet(BaseViewSet):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -150,7 +140,7 @@ class IntakeIssueViewSet(BaseViewSet):
distinct=True,
filter=Q(
~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ & Q(label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -194,9 +184,7 @@ class IntakeIssueViewSet(BaseViewSet):
intake_id=intake_id.id, project_id=project_id, **filters
)
.select_related("issue")
- .prefetch_related(
- "issue__labels",
- )
+ .prefetch_related("issue__labels")
.annotate(
label_ids=Coalesce(
ArrayAgg(
@@ -235,8 +223,7 @@ class IntakeIssueViewSet(BaseViewSet):
request=request,
queryset=(intake_issue),
on_results=lambda intake_issues: IntakeIssueSerializer(
- intake_issues,
- many=True,
+ intake_issues, many=True
).data,
)
@@ -244,8 +231,7 @@ class IntakeIssueViewSet(BaseViewSet):
def create(self, request, slug, project_id):
if not request.data.get("issue", {}).get("name", False):
return Response(
- {"error": "Name is required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Name is required"}, status=status.HTTP_400_BAD_REQUEST
)
# Check for valid priority
@@ -257,8 +243,7 @@ class IntakeIssueViewSet(BaseViewSet):
"none",
]:
return Response(
- {"error": "Invalid priority"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Invalid priority"}, status=status.HTTP_400_BAD_REQUEST
)
# create an issue
@@ -298,10 +283,7 @@ class IntakeIssueViewSet(BaseViewSet):
)
intake_issue = (
IntakeIssue.objects.select_related("issue")
- .prefetch_related(
- "issue__labels",
- "issue__assignees",
- )
+ .prefetch_related("issue__labels", "issue__assignees")
.annotate(
label_ids=Coalesce(
ArrayAgg(
@@ -309,9 +291,7 @@ class IntakeIssueViewSet(BaseViewSet):
distinct=True,
filter=Q(
~Q(issue__labels__id__isnull=True)
- & Q(
- issue__label_issue__deleted_at__isnull=True
- )
+ & Q(issue__label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -321,9 +301,7 @@ class IntakeIssueViewSet(BaseViewSet):
"issue__assignees__id",
distinct=True,
filter=~Q(issue__assignees__id__isnull=True)
- & Q(
- issue__assignees__member_project__is_active=True
- ),
+ & Q(issue__assignees__member_project__is_active=True),
),
Value([], output_field=ArrayField(UUIDField())),
),
@@ -337,9 +315,7 @@ class IntakeIssueViewSet(BaseViewSet):
serializer = IntakeIssueDetailSerializer(intake_issue)
return Response(serializer.data, status=status.HTTP_200_OK)
else:
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@allow_permission(allowed_roles=[ROLE.ADMIN], creator=True, model=Issue)
def partial_update(self, request, slug, project_id, pk):
@@ -394,11 +370,7 @@ class IntakeIssueViewSet(BaseViewSet):
),
Value([], output_field=ArrayField(UUIDField())),
),
- ).get(
- pk=intake_issue.issue_id,
- workspace__slug=slug,
- project_id=project_id,
- )
+ ).get(pk=intake_issue.issue_id, workspace__slug=slug, project_id=project_id)
# Only allow guests to edit name and description
if project_member.role <= 5:
issue_data = {
@@ -406,9 +378,7 @@ class IntakeIssueViewSet(BaseViewSet):
"description_html": issue_data.get(
"description_html", issue.description_html
),
- "description": issue_data.get(
- "description", issue.description
- ),
+ "description": issue_data.get("description", issue.description),
}
issue_serializer = IssueCreateSerializer(
@@ -459,9 +429,7 @@ class IntakeIssueViewSet(BaseViewSet):
project_id=project_id,
)
state = State.objects.filter(
- group="cancelled",
- workspace__slug=slug,
- project_id=project_id,
+ group="cancelled", workspace__slug=slug, project_id=project_id
).first()
if state is not None:
issue.state = state
@@ -479,9 +447,7 @@ class IntakeIssueViewSet(BaseViewSet):
if issue.state.is_triage:
# Move to default state
state = State.objects.filter(
- workspace__slug=slug,
- project_id=project_id,
- default=True,
+ workspace__slug=slug, project_id=project_id, default=True
).first()
if state is not None:
issue.state = state
@@ -489,9 +455,7 @@ class IntakeIssueViewSet(BaseViewSet):
# create a activity for status change
issue_activity.delay(
type="intake.activity.created",
- requested_data=json.dumps(
- request.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(request.data, cls=DjangoJSONEncoder),
actor_id=str(request.user.id),
issue_id=str(pk),
project_id=str(project_id),
@@ -504,10 +468,7 @@ class IntakeIssueViewSet(BaseViewSet):
intake_issue = (
IntakeIssue.objects.select_related("issue")
- .prefetch_related(
- "issue__labels",
- "issue__assignees",
- )
+ .prefetch_related("issue__labels", "issue__assignees")
.annotate(
label_ids=Coalesce(
ArrayAgg(
@@ -515,9 +476,7 @@ class IntakeIssueViewSet(BaseViewSet):
distinct=True,
filter=Q(
~Q(issue__labels__id__isnull=True)
- & Q(
- issue__label_issue__deleted_at__isnull=True
- )
+ & Q(issue__label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -528,37 +487,23 @@ class IntakeIssueViewSet(BaseViewSet):
distinct=True,
filter=Q(
~Q(issue__assignees__id__isnull=True)
- & Q(
- issue__issue_assignee__deleted_at__isnull=True
- )
+ & Q(issue__issue_assignee__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
),
)
- .get(
- intake_id=intake_id.id,
- issue_id=pk,
- project_id=project_id,
- )
+ .get(intake_id=intake_id.id, issue_id=pk, project_id=project_id)
)
serializer = IntakeIssueDetailSerializer(intake_issue).data
return Response(serializer, status=status.HTTP_200_OK)
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
serializer = IntakeIssueDetailSerializer(intake_issue).data
return Response(serializer, status=status.HTTP_200_OK)
@allow_permission(
- allowed_roles=[
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ],
- creator=True,
- model=Issue,
+ allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], creator=True, model=Issue
)
def retrieve(self, request, slug, project_id, pk):
intake_id = Intake.objects.filter(
@@ -567,10 +512,7 @@ class IntakeIssueViewSet(BaseViewSet):
project = Project.objects.get(pk=project_id)
intake_issue = (
IntakeIssue.objects.select_related("issue")
- .prefetch_related(
- "issue__labels",
- "issue__assignees",
- )
+ .prefetch_related("issue__labels", "issue__assignees")
.annotate(
label_ids=Coalesce(
ArrayAgg(
@@ -613,10 +555,7 @@ class IntakeIssueViewSet(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST,
)
issue = IntakeIssueDetailSerializer(intake_issue).data
- return Response(
- issue,
- status=status.HTTP_200_OK,
- )
+ return Response(issue, status=status.HTTP_200_OK)
@allow_permission(allowed_roles=[ROLE.ADMIN], creator=True, model=Issue)
def destroy(self, request, slug, project_id, pk):
diff --git a/apiserver/plane/app/views/issue/activity.py b/apiserver/plane/app/views/issue/activity.py
index f46cb87f3..1b6629e47 100644
--- a/apiserver/plane/app/views/issue/activity.py
+++ b/apiserver/plane/app/views/issue/activity.py
@@ -2,10 +2,7 @@
from itertools import chain
# Django imports
-from django.db.models import (
- Prefetch,
- Q,
-)
+from django.db.models import Prefetch, Q
from django.utils.decorators import method_decorator
from django.views.decorators.gzip import gzip_page
@@ -15,35 +12,16 @@ from rest_framework import status
# Module imports
from .. import BaseAPIView
-from plane.app.serializers import (
- IssueActivitySerializer,
- IssueCommentSerializer,
-)
-from plane.app.permissions import (
- ProjectEntityPermission,
- allow_permission,
- ROLE,
-)
-from plane.db.models import (
- IssueActivity,
- IssueComment,
- CommentReaction,
-)
+from plane.app.serializers import IssueActivitySerializer, IssueCommentSerializer
+from plane.app.permissions import ProjectEntityPermission, allow_permission, ROLE
+from plane.db.models import IssueActivity, IssueComment, CommentReaction
class IssueActivityEndpoint(BaseAPIView):
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
@method_decorator(gzip_page)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def get(self, request, slug, project_id, issue_id):
filters = {}
if request.GET.get("created_at__gt", None) is not None:
@@ -79,9 +57,7 @@ class IssueActivityEndpoint(BaseAPIView):
)
)
)
- issue_activities = IssueActivitySerializer(
- issue_activities, many=True
- ).data
+ issue_activities = IssueActivitySerializer(issue_activities, many=True).data
issue_comments = IssueCommentSerializer(issue_comments, many=True).data
if request.GET.get("activity_type", None) == "issue-property":
diff --git a/apiserver/plane/app/views/issue/archive.py b/apiserver/plane/app/views/issue/archive.py
index 292d9d617..4f1e357da 100644
--- a/apiserver/plane/app/views/issue/archive.py
+++ b/apiserver/plane/app/views/issue/archive.py
@@ -12,9 +12,7 @@ from django.views.decorators.gzip import gzip_page
from rest_framework import status
from rest_framework.response import Response
-from plane.app.permissions import (
- ProjectEntityPermission,
-)
+from plane.app.permissions import ProjectEntityPermission
from plane.app.serializers import (
IssueFlatSerializer,
IssueSerializer,
@@ -27,7 +25,7 @@ from plane.db.models import (
IssueLink,
IssueSubscriber,
IssueReaction,
- CycleIssue
+ CycleIssue,
)
from plane.utils.grouper import (
issue_group_values,
@@ -36,10 +34,7 @@ from plane.utils.grouper import (
)
from plane.utils.issue_filters import issue_filters
from plane.utils.order_queryset import order_issue_queryset
-from plane.utils.paginator import (
- GroupedOffsetPaginator,
- SubGroupedOffsetPaginator,
-)
+from plane.utils.paginator import GroupedOffsetPaginator, SubGroupedOffsetPaginator
from plane.app.permissions import allow_permission, ROLE
from plane.utils.error_codes import ERROR_CODES
@@ -88,9 +83,7 @@ class IssueArchiveViewSet(BaseViewSet):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -98,12 +91,7 @@ class IssueArchiveViewSet(BaseViewSet):
)
@method_decorator(gzip_page)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def list(self, request, slug, project_id):
filters = issue_filters(request.query_params, "GET")
show_sub_issues = request.GET.get("show_sub_issues", "true")
@@ -119,8 +107,7 @@ class IssueArchiveViewSet(BaseViewSet):
)
# Issue queryset
issue_queryset, order_by_param = order_issue_queryset(
- issue_queryset=issue_queryset,
- order_by_param=order_by_param,
+ issue_queryset=issue_queryset, order_by_param=order_by_param
)
# Group by
@@ -129,9 +116,7 @@ class IssueArchiveViewSet(BaseViewSet):
# issue queryset
issue_queryset = issue_queryset_grouper(
- queryset=issue_queryset,
- group_by=group_by,
- sub_group_by=sub_group_by,
+ queryset=issue_queryset, group_by=group_by, sub_group_by=sub_group_by
)
if group_by:
@@ -151,9 +136,7 @@ class IssueArchiveViewSet(BaseViewSet):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=SubGroupedOffsetPaginator,
group_by_fields=issue_group_values(
@@ -187,9 +170,7 @@ class IssueArchiveViewSet(BaseViewSet):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=GroupedOffsetPaginator,
group_by_fields=issue_group_values(
@@ -219,12 +200,7 @@ class IssueArchiveViewSet(BaseViewSet):
),
)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def retrieve(self, request, slug, project_id, pk=None):
issue = (
self.get_queryset()
@@ -232,9 +208,7 @@ class IssueArchiveViewSet(BaseViewSet):
.prefetch_related(
Prefetch(
"issue_reactions",
- queryset=IssueReaction.objects.select_related(
- "issue", "actor"
- ),
+ queryset=IssueReaction.objects.select_related("issue", "actor"),
)
)
.prefetch_related(
@@ -265,24 +239,17 @@ class IssueArchiveViewSet(BaseViewSet):
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def archive(self, request, slug, project_id, pk=None):
issue = Issue.issue_objects.get(
- workspace__slug=slug,
- project_id=project_id,
- pk=pk,
+ workspace__slug=slug, project_id=project_id, pk=pk
)
if issue.state.group not in ["completed", "cancelled"]:
return Response(
- {
- "error": "Can only archive completed or cancelled state group issue"
- },
+ {"error": "Can only archive completed or cancelled state group issue"},
status=status.HTTP_400_BAD_REQUEST,
)
issue_activity.delay(
type="issue.activity.updated",
requested_data=json.dumps(
- {
- "archived_at": str(timezone.now().date()),
- "automation": False,
- }
+ {"archived_at": str(timezone.now().date()), "automation": False}
),
actor_id=str(request.user.id),
issue_id=str(issue.id),
@@ -329,9 +296,7 @@ class IssueArchiveViewSet(BaseViewSet):
class BulkArchiveIssuesEndpoint(BaseAPIView):
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def post(self, request, slug, project_id):
@@ -339,8 +304,7 @@ class BulkArchiveIssuesEndpoint(BaseAPIView):
if not len(issue_ids):
return Response(
- {"error": "Issue IDs are required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Issue IDs are required"}, status=status.HTTP_400_BAD_REQUEST
)
issues = Issue.objects.filter(
@@ -351,9 +315,7 @@ class BulkArchiveIssuesEndpoint(BaseAPIView):
if issue.state.group not in ["completed", "cancelled"]:
return Response(
{
- "error_code": ERROR_CODES[
- "INVALID_ARCHIVE_STATE_GROUP"
- ],
+ "error_code": ERROR_CODES["INVALID_ARCHIVE_STATE_GROUP"],
"error_message": "INVALID_ARCHIVE_STATE_GROUP",
},
status=status.HTTP_400_BAD_REQUEST,
@@ -361,10 +323,7 @@ class BulkArchiveIssuesEndpoint(BaseAPIView):
issue_activity.delay(
type="issue.activity.updated",
requested_data=json.dumps(
- {
- "archived_at": str(timezone.now().date()),
- "automation": False,
- }
+ {"archived_at": str(timezone.now().date()), "automation": False}
),
actor_id=str(request.user.id),
issue_id=str(issue.id),
@@ -381,6 +340,5 @@ class BulkArchiveIssuesEndpoint(BaseAPIView):
Issue.objects.bulk_update(bulk_archive_issues, ["archived_at"])
return Response(
- {"archived_at": str(timezone.now().date())},
- status=status.HTTP_200_OK,
+ {"archived_at": str(timezone.now().date())}, status=status.HTTP_200_OK
)
diff --git a/apiserver/plane/app/views/issue/attachment.py b/apiserver/plane/app/views/issue/attachment.py
index 48b80c6cb..4427227f1 100644
--- a/apiserver/plane/app/views/issue/attachment.py
+++ b/apiserver/plane/app/views/issue/attachment.py
@@ -45,10 +45,7 @@ class IssueAttachmentEndpoint(BaseAPIView):
actor_id=str(self.request.user.id),
issue_id=str(self.kwargs.get("issue_id", None)),
project_id=str(self.kwargs.get("project_id", None)),
- current_instance=json.dumps(
- serializer.data,
- cls=DjangoJSONEncoder,
- ),
+ current_instance=json.dumps(serializer.data, cls=DjangoJSONEncoder),
epoch=int(timezone.now().timestamp()),
notification=True,
origin=request.META.get("HTTP_ORIGIN"),
@@ -75,13 +72,7 @@ class IssueAttachmentEndpoint(BaseAPIView):
return Response(status=status.HTTP_204_NO_CONTENT)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def get(self, request, slug, project_id, issue_id):
issue_attachments = FileAsset.objects.filter(
issue_id=issue_id, workspace__slug=slug, project_id=project_id
@@ -91,7 +82,6 @@ class IssueAttachmentEndpoint(BaseAPIView):
class IssueAttachmentV2Endpoint(BaseAPIView):
-
serializer_class = IssueAttachmentSerializer
model = FileAsset
@@ -103,10 +93,7 @@ class IssueAttachmentV2Endpoint(BaseAPIView):
if not type or type not in settings.ATTACHMENT_MIME_TYPES:
return Response(
- {
- "error": "Invalid file type.",
- "status": False,
- },
+ {"error": "Invalid file type.", "status": False},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -121,11 +108,7 @@ class IssueAttachmentV2Endpoint(BaseAPIView):
# Create a File Asset
asset = FileAsset.objects.create(
- attributes={
- "name": name,
- "type": type,
- "size": size_limit,
- },
+ attributes={"name": name, "type": type, "size": size_limit},
asset=asset_key,
size=size_limit,
workspace_id=workspace.id,
@@ -139,9 +122,7 @@ class IssueAttachmentV2Endpoint(BaseAPIView):
storage = S3Storage(request=request)
# Generate a presigned URL to share an S3 object
presigned_url = storage.generate_presigned_post(
- object_name=asset_key,
- file_type=type,
- file_size=size_limit,
+ object_name=asset_key, file_type=type, file_size=size_limit
)
# Return the presigned URL
return Response(
@@ -177,13 +158,7 @@ class IssueAttachmentV2Endpoint(BaseAPIView):
return Response(status=status.HTTP_204_NO_CONTENT)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def get(self, request, slug, project_id, issue_id, pk=None):
if pk:
# Get the asset
@@ -194,10 +169,7 @@ class IssueAttachmentV2Endpoint(BaseAPIView):
# Check if the asset is uploaded
if not asset.is_uploaded:
return Response(
- {
- "error": "The asset is not uploaded.",
- "status": False,
- },
+ {"error": "The asset is not uploaded.", "status": False},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -221,13 +193,7 @@ class IssueAttachmentV2Endpoint(BaseAPIView):
serializer = IssueAttachmentSerializer(issue_attachments, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def patch(self, request, slug, project_id, issue_id, pk):
issue_attachment = FileAsset.objects.get(
pk=pk, workspace__slug=slug, project_id=project_id
@@ -242,10 +208,7 @@ class IssueAttachmentV2Endpoint(BaseAPIView):
actor_id=str(self.request.user.id),
issue_id=str(self.kwargs.get("issue_id", None)),
project_id=str(self.kwargs.get("project_id", None)),
- current_instance=json.dumps(
- serializer.data,
- cls=DjangoJSONEncoder,
- ),
+ current_instance=json.dumps(serializer.data, cls=DjangoJSONEncoder),
epoch=int(timezone.now().timestamp()),
notification=True,
origin=request.META.get("HTTP_ORIGIN"),
diff --git a/apiserver/plane/app/views/issue/base.py b/apiserver/plane/app/views/issue/base.py
index c30f889ba..3d548aeac 100644
--- a/apiserver/plane/app/views/issue/base.py
+++ b/apiserver/plane/app/views/issue/base.py
@@ -54,10 +54,7 @@ from plane.utils.grouper import (
)
from plane.utils.issue_filters import issue_filters
from plane.utils.order_queryset import order_issue_queryset
-from plane.utils.paginator import (
- GroupedOffsetPaginator,
- SubGroupedOffsetPaginator,
-)
+from plane.utils.paginator import GroupedOffsetPaginator, SubGroupedOffsetPaginator
from .. import BaseAPIView, BaseViewSet
from plane.utils.user_timezone_converter import user_timezone_converter
from plane.bgtasks.recent_visited_task import recent_visited_task
@@ -72,13 +69,10 @@ class IssueListEndpoint(BaseAPIView):
if not issue_ids:
return Response(
- {"error": "Issues are required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Issues are required"}, status=status.HTTP_400_BAD_REQUEST
)
- issue_ids = [
- issue_id for issue_id in issue_ids.split(",") if issue_id != ""
- ]
+ issue_ids = [issue_id for issue_id in issue_ids.split(",") if issue_id != ""]
queryset = (
Issue.issue_objects.filter(
@@ -110,9 +104,7 @@ class IssueListEndpoint(BaseAPIView):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -125,8 +117,7 @@ class IssueListEndpoint(BaseAPIView):
issue_queryset = queryset.filter(**filters)
# Issue queryset
issue_queryset, _ = order_issue_queryset(
- issue_queryset=issue_queryset,
- order_by_param=order_by_param,
+ issue_queryset=issue_queryset, order_by_param=order_by_param
)
# Group by
@@ -135,9 +126,7 @@ class IssueListEndpoint(BaseAPIView):
# issue queryset
issue_queryset = issue_queryset_grouper(
- queryset=issue_queryset,
- group_by=group_by,
- sub_group_by=sub_group_by,
+ queryset=issue_queryset, group_by=group_by, sub_group_by=sub_group_by
)
recent_visited_task.delay(
@@ -199,21 +188,13 @@ class IssueViewSet(BaseViewSet):
model = Issue
webhook_event = "issue"
- search_fields = [
- "name",
- ]
+ search_fields = ["name"]
- filterset_fields = [
- "state__name",
- "assignees__id",
- "workspace__id",
- ]
+ filterset_fields = ["state__name", "assignees__id", "workspace__id"]
def get_queryset(self):
return (
- Issue.issue_objects.filter(
- project_id=self.kwargs.get("project_id")
- )
+ Issue.issue_objects.filter(project_id=self.kwargs.get("project_id"))
.filter(workspace__slug=self.kwargs.get("slug"))
.select_related("workspace", "project", "state", "parent")
.prefetch_related("assignees", "labels", "issue_module__module")
@@ -240,9 +221,7 @@ class IssueViewSet(BaseViewSet):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -254,9 +233,7 @@ class IssueViewSet(BaseViewSet):
def list(self, request, slug, project_id):
extra_filters = {}
if request.GET.get("updated_at__gt", None) is not None:
- extra_filters = {
- "updated_at__gt": request.GET.get("updated_at__gt")
- }
+ extra_filters = {"updated_at__gt": request.GET.get("updated_at__gt")}
project = Project.objects.get(pk=project_id, workspace__slug=slug)
filters = issue_filters(request.query_params, "GET")
@@ -267,8 +244,7 @@ class IssueViewSet(BaseViewSet):
# Issue queryset
issue_queryset, order_by_param = order_issue_queryset(
- issue_queryset=issue_queryset,
- order_by_param=order_by_param,
+ issue_queryset=issue_queryset, order_by_param=order_by_param
)
# Group by
@@ -277,9 +253,7 @@ class IssueViewSet(BaseViewSet):
# issue queryset
issue_queryset = issue_queryset_grouper(
- queryset=issue_queryset,
- group_by=group_by,
- sub_group_by=sub_group_by,
+ queryset=issue_queryset, group_by=group_by, sub_group_by=sub_group_by
)
recent_visited_task.delay(
@@ -316,9 +290,7 @@ class IssueViewSet(BaseViewSet):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=SubGroupedOffsetPaginator,
group_by_fields=issue_group_values(
@@ -351,9 +323,7 @@ class IssueViewSet(BaseViewSet):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=GroupedOffsetPaginator,
group_by_fields=issue_group_values(
@@ -401,9 +371,7 @@ class IssueViewSet(BaseViewSet):
# Track the issue
issue_activity.delay(
type="issue.activity.created",
- requested_data=json.dumps(
- self.request.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(self.request.data, cls=DjangoJSONEncoder),
actor_id=str(request.user.id),
issue_id=str(serializer.data.get("id", None)),
project_id=str(project_id),
@@ -414,9 +382,7 @@ class IssueViewSet(BaseViewSet):
)
issue = (
issue_queryset_grouper(
- queryset=self.get_queryset().filter(
- pk=serializer.data["id"]
- ),
+ queryset=self.get_queryset().filter(pk=serializer.data["id"]),
group_by=None,
sub_group_by=None,
)
@@ -468,21 +434,13 @@ class IssueViewSet(BaseViewSet):
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@allow_permission(
- allowed_roles=[
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ],
- creator=True,
- model=Issue,
+ allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], creator=True, model=Issue
)
def retrieve(self, request, slug, project_id, pk=None):
project = Project.objects.get(pk=project_id, workspace__slug=slug)
issue = (
- Issue.objects.filter(
- project_id=self.kwargs.get("project_id")
- )
+ Issue.objects.filter(project_id=self.kwargs.get("project_id"))
.filter(workspace__slug=self.kwargs.get("slug"))
.select_related("workspace", "project", "state", "parent")
.prefetch_related("assignees", "labels", "issue_module__module")
@@ -511,13 +469,11 @@ class IssueViewSet(BaseViewSet):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
- )
+ )
.filter(pk=pk)
.annotate(
label_ids=Coalesce(
@@ -526,7 +482,7 @@ class IssueViewSet(BaseViewSet):
distinct=True,
filter=Q(
~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ & Q(label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -559,9 +515,7 @@ class IssueViewSet(BaseViewSet):
.prefetch_related(
Prefetch(
"issue_reactions",
- queryset=IssueReaction.objects.select_related(
- "issue", "actor"
- ),
+ queryset=IssueReaction.objects.select_related("issue", "actor"),
)
)
.prefetch_related(
@@ -632,7 +586,7 @@ class IssueViewSet(BaseViewSet):
distinct=True,
filter=Q(
~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ & Q(label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -668,8 +622,7 @@ class IssueViewSet(BaseViewSet):
if not issue:
return Response(
- {"error": "Issue not found"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Issue not found"}, status=status.HTTP_404_NOT_FOUND
)
current_instance = json.dumps(
@@ -677,9 +630,7 @@ class IssueViewSet(BaseViewSet):
)
requested_data = json.dumps(self.request.data, cls=DjangoJSONEncoder)
- serializer = IssueCreateSerializer(
- issue, data=request.data, partial=True
- )
+ serializer = IssueCreateSerializer(issue, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
issue_activity.delay(
@@ -707,9 +658,7 @@ class IssueViewSet(BaseViewSet):
@allow_permission([ROLE.ADMIN], creator=True, model=Issue)
def destroy(self, request, slug, project_id, pk=None):
- issue = Issue.objects.get(
- workspace__slug=slug, project_id=project_id, pk=pk
- )
+ issue = Issue.objects.get(workspace__slug=slug, project_id=project_id, pk=pk)
issue.delete()
issue_activity.delay(
@@ -730,13 +679,10 @@ class IssueUserDisplayPropertyEndpoint(BaseAPIView):
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def patch(self, request, slug, project_id):
issue_property = IssueUserProperty.objects.get(
- user=request.user,
- project_id=project_id,
+ user=request.user, project_id=project_id
)
- issue_property.filters = request.data.get(
- "filters", issue_property.filters
- )
+ issue_property.filters = request.data.get("filters", issue_property.filters)
issue_property.display_filters = request.data.get(
"display_filters", issue_property.display_filters
)
@@ -747,13 +693,7 @@ class IssueUserDisplayPropertyEndpoint(BaseAPIView):
serializer = IssueUserPropertySerializer(issue_property)
return Response(serializer.data, status=status.HTTP_201_CREATED)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def get(self, request, slug, project_id):
issue_property, _ = IssueUserProperty.objects.get_or_create(
user=request.user, project_id=project_id
@@ -769,8 +709,7 @@ class BulkDeleteIssuesEndpoint(BaseAPIView):
if not len(issue_ids):
return Response(
- {"error": "Issue IDs are required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Issue IDs are required"}, status=status.HTTP_400_BAD_REQUEST
)
issues = Issue.issue_objects.filter(
@@ -794,10 +733,7 @@ class DeletedIssuesListViewSet(BaseAPIView):
if request.GET.get("updated_at__gt", None) is not None:
filters = {"updated_at__gt": request.GET.get("updated_at__gt")}
deleted_issues = (
- Issue.all_objects.filter(
- workspace__slug=slug,
- project_id=project_id,
- )
+ Issue.all_objects.filter(workspace__slug=slug, project_id=project_id)
.filter(Q(archived_at__isnull=False) | Q(deleted_at__isnull=False))
.filter(**filters)
.values_list("id", flat=True)
@@ -816,9 +752,7 @@ class IssuePaginatedViewSet(BaseViewSet):
)
return (
- issue_queryset.select_related(
- "workspace", "project", "state", "parent"
- )
+ issue_queryset.select_related("workspace", "project", "state", "parent")
.prefetch_related("assignees", "labels", "issue_module__module")
.annotate(
cycle_id=Subquery(
@@ -843,9 +777,7 @@ class IssuePaginatedViewSet(BaseViewSet):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -935,7 +867,7 @@ class IssuePaginatedViewSet(BaseViewSet):
distinct=True,
filter=Q(
~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ & Q(label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -983,9 +915,7 @@ class IssueDetailEndpoint(BaseAPIView):
def get(self, request, slug, project_id):
filters = issue_filters(request.query_params, "GET")
issue = (
- Issue.issue_objects.filter(
- workspace__slug=slug, project_id=project_id
- )
+ Issue.issue_objects.filter(workspace__slug=slug, project_id=project_id)
.select_related("workspace", "project", "state", "parent")
.prefetch_related("assignees", "labels", "issue_module__module")
.annotate(
@@ -1002,7 +932,7 @@ class IssueDetailEndpoint(BaseAPIView):
distinct=True,
filter=Q(
~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ & Q(label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -1048,9 +978,7 @@ class IssueDetailEndpoint(BaseAPIView):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -1060,27 +988,20 @@ class IssueDetailEndpoint(BaseAPIView):
order_by_param = request.GET.get("order_by", "-created_at")
# Issue queryset
issue, order_by_param = order_issue_queryset(
- issue_queryset=issue,
- order_by_param=order_by_param,
+ issue_queryset=issue, order_by_param=order_by_param
)
return self.paginate(
request=request,
order_by=order_by_param,
queryset=(issue),
on_results=lambda issue: IssueSerializer(
- issue,
- many=True,
- fields=self.fields,
- expand=self.expand,
+ issue, many=True, fields=self.fields, expand=self.expand
).data,
)
class IssueBulkUpdateDateEndpoint(BaseAPIView):
-
- def validate_dates(
- self, current_start, current_target, new_start, new_target
- ):
+ def validate_dates(self, current_start, current_target, new_start, new_target):
"""
Validate that start date is before target date.
"""
@@ -1093,7 +1014,6 @@ class IssueBulkUpdateDateEndpoint(BaseAPIView):
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def post(self, request, slug, project_id):
-
updates = request.data.get("updates", [])
issue_ids = [update["id"] for update in updates]
@@ -1118,21 +1038,15 @@ class IssueBulkUpdateDateEndpoint(BaseAPIView):
)
if not validate_dates:
return Response(
- {
- "message": "Start date cannot exceed target date",
- },
+ {"message": "Start date cannot exceed target date"},
status=status.HTTP_400_BAD_REQUEST,
)
if start_date:
issue_activity.delay(
type="issue.activity.updated",
- requested_data=json.dumps(
- {"start_date": update.get("start_date")}
- ),
- current_instance=json.dumps(
- {"start_date": str(issue.start_date)}
- ),
+ requested_data=json.dumps({"start_date": update.get("start_date")}),
+ current_instance=json.dumps({"start_date": str(issue.start_date)}),
issue_id=str(issue_id),
actor_id=str(request.user.id),
project_id=str(project_id),
@@ -1159,11 +1073,8 @@ class IssueBulkUpdateDateEndpoint(BaseAPIView):
issues_to_update.append(issue)
# Bulk update issues
- Issue.objects.bulk_update(
- issues_to_update, ["start_date", "target_date"]
- )
+ Issue.objects.bulk_update(issues_to_update, ["start_date", "target_date"])
return Response(
- {"message": "Issues updated successfully"},
- status=status.HTTP_200_OK,
+ {"message": "Issues updated successfully"}, status=status.HTTP_200_OK
)
diff --git a/apiserver/plane/app/views/issue/comment.py b/apiserver/plane/app/views/issue/comment.py
index 12964dc3a..d072bb881 100644
--- a/apiserver/plane/app/views/issue/comment.py
+++ b/apiserver/plane/app/views/issue/comment.py
@@ -12,18 +12,9 @@ from rest_framework import status
# Module imports
from .. import BaseViewSet
-from plane.app.serializers import (
- IssueCommentSerializer,
- CommentReactionSerializer,
-)
+from plane.app.serializers import IssueCommentSerializer, CommentReactionSerializer
from plane.app.permissions import allow_permission, ROLE
-from plane.db.models import (
- IssueComment,
- ProjectMember,
- CommentReaction,
- Project,
- Issue,
-)
+from plane.db.models import IssueComment, ProjectMember, CommentReaction, Project, Issue
from plane.bgtasks.issue_activities_task import issue_activity
@@ -32,10 +23,7 @@ class IssueCommentViewSet(BaseViewSet):
model = IssueComment
webhook_event = "issue_comment"
- filterset_fields = [
- "issue__id",
- "workspace__id",
- ]
+ filterset_fields = ["issue__id", "workspace__id"]
def get_queryset(self):
return self.filter_queryset(
@@ -65,13 +53,7 @@ class IssueCommentViewSet(BaseViewSet):
.distinct()
)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def create(self, request, slug, project_id, issue_id):
project = Project.objects.get(pk=project_id)
issue = Issue.objects.get(pk=issue_id)
@@ -93,15 +75,11 @@ class IssueCommentViewSet(BaseViewSet):
serializer = IssueCommentSerializer(data=request.data)
if serializer.is_valid():
serializer.save(
- project_id=project_id,
- issue_id=issue_id,
- actor=request.user,
+ project_id=project_id, issue_id=issue_id, actor=request.user
)
issue_activity.delay(
type="comment.activity.created",
- requested_data=json.dumps(
- serializer.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(serializer.data, cls=DjangoJSONEncoder),
actor_id=str(self.request.user.id),
issue_id=str(self.kwargs.get("issue_id")),
project_id=str(self.kwargs.get("project_id")),
@@ -113,22 +91,14 @@ class IssueCommentViewSet(BaseViewSet):
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
- @allow_permission(
- allowed_roles=[ROLE.ADMIN],
- creator=True,
- model=IssueComment,
- )
+ @allow_permission(allowed_roles=[ROLE.ADMIN], creator=True, model=IssueComment)
def partial_update(self, request, slug, project_id, issue_id, pk):
issue_comment = IssueComment.objects.get(
- workspace__slug=slug,
- project_id=project_id,
- issue_id=issue_id,
- pk=pk,
+ workspace__slug=slug, project_id=project_id, issue_id=issue_id, pk=pk
)
requested_data = json.dumps(self.request.data, cls=DjangoJSONEncoder)
current_instance = json.dumps(
- IssueCommentSerializer(issue_comment).data,
- cls=DjangoJSONEncoder,
+ IssueCommentSerializer(issue_comment).data, cls=DjangoJSONEncoder
)
serializer = IssueCommentSerializer(
issue_comment, data=request.data, partial=True
@@ -149,19 +119,13 @@ class IssueCommentViewSet(BaseViewSet):
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
- @allow_permission(
- allowed_roles=[ROLE.ADMIN], creator=True, model=IssueComment
- )
+ @allow_permission(allowed_roles=[ROLE.ADMIN], creator=True, model=IssueComment)
def destroy(self, request, slug, project_id, issue_id, pk):
issue_comment = IssueComment.objects.get(
- workspace__slug=slug,
- project_id=project_id,
- issue_id=issue_id,
- pk=pk,
+ workspace__slug=slug, project_id=project_id, issue_id=issue_id, pk=pk
)
current_instance = json.dumps(
- IssueCommentSerializer(issue_comment).data,
- cls=DjangoJSONEncoder,
+ IssueCommentSerializer(issue_comment).data, cls=DjangoJSONEncoder
)
issue_comment.delete()
issue_activity.delay(
@@ -198,20 +162,12 @@ class CommentReactionViewSet(BaseViewSet):
.distinct()
)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def create(self, request, slug, project_id, comment_id):
serializer = CommentReactionSerializer(data=request.data)
if serializer.is_valid():
serializer.save(
- project_id=project_id,
- actor_id=request.user.id,
- comment_id=comment_id,
+ project_id=project_id, actor_id=request.user.id, comment_id=comment_id
)
issue_activity.delay(
type="comment_reaction.activity.created",
@@ -227,13 +183,7 @@ class CommentReactionViewSet(BaseViewSet):
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def destroy(self, request, slug, project_id, comment_id, reaction_code):
comment_reaction = CommentReaction.objects.get(
workspace__slug=slug,
diff --git a/apiserver/plane/app/views/issue/label.py b/apiserver/plane/app/views/issue/label.py
index 7a72932ff..b8a960161 100644
--- a/apiserver/plane/app/views/issue/label.py
+++ b/apiserver/plane/app/views/issue/label.py
@@ -12,19 +12,14 @@ from rest_framework import status
from .. import BaseViewSet, BaseAPIView
from plane.app.serializers import LabelSerializer
from plane.app.permissions import allow_permission, ProjectBasePermission, ROLE
-from plane.db.models import (
- Project,
- Label,
-)
+from plane.db.models import Project, Label
from plane.utils.cache import invalidate_cache
class LabelViewSet(BaseViewSet):
serializer_class = LabelSerializer
model = Label
- permission_classes = [
- ProjectBasePermission,
- ]
+ permission_classes = [ProjectBasePermission]
def get_queryset(self):
return self.filter_queryset(
@@ -40,39 +35,27 @@ class LabelViewSet(BaseViewSet):
.order_by("sort_order")
)
- @invalidate_cache(
- path="/api/workspaces/:slug/labels/", url_params=True, user=False
- )
+ @invalidate_cache(path="/api/workspaces/:slug/labels/", url_params=True, user=False)
@allow_permission([ROLE.ADMIN])
def create(self, request, slug, project_id):
try:
serializer = LabelSerializer(data=request.data)
if serializer.is_valid():
serializer.save(project_id=project_id)
- return Response(
- serializer.data, status=status.HTTP_201_CREATED
- )
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.data, status=status.HTTP_201_CREATED)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except IntegrityError:
return Response(
- {
- "error": "Label with the same name already exists in the project"
- },
+ {"error": "Label with the same name already exists in the project"},
status=status.HTTP_400_BAD_REQUEST,
)
- @invalidate_cache(
- path="/api/workspaces/:slug/labels/", url_params=True, user=False
- )
+ @invalidate_cache(path="/api/workspaces/:slug/labels/", url_params=True, user=False)
@allow_permission([ROLE.ADMIN])
def partial_update(self, request, *args, **kwargs):
return super().partial_update(request, *args, **kwargs)
- @invalidate_cache(
- path="/api/workspaces/:slug/labels/", url_params=True, user=False
- )
+ @invalidate_cache(path="/api/workspaces/:slug/labels/", url_params=True, user=False)
@allow_permission([ROLE.ADMIN])
def destroy(self, request, *args, **kwargs):
return super().destroy(request, *args, **kwargs)
diff --git a/apiserver/plane/app/views/issue/link.py b/apiserver/plane/app/views/issue/link.py
index 1a4110a2f..85faa8368 100644
--- a/apiserver/plane/app/views/issue/link.py
+++ b/apiserver/plane/app/views/issue/link.py
@@ -18,9 +18,7 @@ from plane.bgtasks.issue_activities_task import issue_activity
class IssueLinkViewSet(BaseViewSet):
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
model = IssueLink
serializer_class = IssueLinkSerializer
@@ -44,15 +42,10 @@ class IssueLinkViewSet(BaseViewSet):
def create(self, request, slug, project_id, issue_id):
serializer = IssueLinkSerializer(data=request.data)
if serializer.is_valid():
- serializer.save(
- project_id=project_id,
- issue_id=issue_id,
- )
+ serializer.save(project_id=project_id, issue_id=issue_id)
issue_activity.delay(
type="link.activity.created",
- requested_data=json.dumps(
- serializer.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(serializer.data, cls=DjangoJSONEncoder),
actor_id=str(self.request.user.id),
issue_id=str(self.kwargs.get("issue_id")),
project_id=str(self.kwargs.get("project_id")),
@@ -66,19 +59,13 @@ class IssueLinkViewSet(BaseViewSet):
def partial_update(self, request, slug, project_id, issue_id, pk):
issue_link = IssueLink.objects.get(
- workspace__slug=slug,
- project_id=project_id,
- issue_id=issue_id,
- pk=pk,
+ workspace__slug=slug, project_id=project_id, issue_id=issue_id, pk=pk
)
requested_data = json.dumps(request.data, cls=DjangoJSONEncoder)
current_instance = json.dumps(
- IssueLinkSerializer(issue_link).data,
- cls=DjangoJSONEncoder,
- )
- serializer = IssueLinkSerializer(
- issue_link, data=request.data, partial=True
+ IssueLinkSerializer(issue_link).data, cls=DjangoJSONEncoder
)
+ serializer = IssueLinkSerializer(issue_link, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
issue_activity.delay(
@@ -97,14 +84,10 @@ class IssueLinkViewSet(BaseViewSet):
def destroy(self, request, slug, project_id, issue_id, pk):
issue_link = IssueLink.objects.get(
- workspace__slug=slug,
- project_id=project_id,
- issue_id=issue_id,
- pk=pk,
+ workspace__slug=slug, project_id=project_id, issue_id=issue_id, pk=pk
)
current_instance = json.dumps(
- IssueLinkSerializer(issue_link).data,
- cls=DjangoJSONEncoder,
+ IssueLinkSerializer(issue_link).data, cls=DjangoJSONEncoder
)
issue_activity.delay(
type="link.activity.deleted",
diff --git a/apiserver/plane/app/views/issue/reaction.py b/apiserver/plane/app/views/issue/reaction.py
index a43f7bda6..7fe53b456 100644
--- a/apiserver/plane/app/views/issue/reaction.py
+++ b/apiserver/plane/app/views/issue/reaction.py
@@ -42,9 +42,7 @@ class IssueReactionViewSet(BaseViewSet):
serializer = IssueReactionSerializer(data=request.data)
if serializer.is_valid():
serializer.save(
- issue_id=issue_id,
- project_id=project_id,
- actor=request.user,
+ issue_id=issue_id, project_id=project_id, actor=request.user
)
issue_activity.delay(
type="issue_reaction.activity.created",
@@ -76,10 +74,7 @@ class IssueReactionViewSet(BaseViewSet):
issue_id=str(self.kwargs.get("issue_id", None)),
project_id=str(self.kwargs.get("project_id", None)),
current_instance=json.dumps(
- {
- "reaction": str(reaction_code),
- "identifier": str(issue_reaction.id),
- }
+ {"reaction": str(reaction_code), "identifier": str(issue_reaction.id)}
),
epoch=int(timezone.now().timestamp()),
notification=True,
diff --git a/apiserver/plane/app/views/issue/relation.py b/apiserver/plane/app/views/issue/relation.py
index 67bfeff1f..35d88a54b 100644
--- a/apiserver/plane/app/views/issue/relation.py
+++ b/apiserver/plane/app/views/issue/relation.py
@@ -3,16 +3,7 @@ import json
# Django imports
from django.utils import timezone
-from django.db.models import (
- Q,
- OuterRef,
- F,
- Func,
- UUIDField,
- Value,
- CharField,
- Subquery,
-)
+from django.db.models import Q, OuterRef, F, Func, UUIDField, Value, CharField, Subquery
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models.functions import Coalesce
from django.contrib.postgres.aggregates import ArrayAgg
@@ -24,10 +15,7 @@ from rest_framework import status
# Module imports
from .. import BaseViewSet
-from plane.app.serializers import (
- IssueRelationSerializer,
- RelatedIssueSerializer,
-)
+from plane.app.serializers import IssueRelationSerializer, RelatedIssueSerializer
from plane.app.permissions import ProjectEntityPermission
from plane.db.models import (
Project,
@@ -44,9 +32,7 @@ from plane.utils.issue_relation_mapper import get_actual_relation
class IssueRelationViewSet(BaseViewSet):
serializer_class = IssueRelationSerializer
model = IssueRelation
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
def list(self, request, slug, project_id, issue_id):
issue_relations = (
@@ -137,9 +123,7 @@ class IssueRelationViewSet(BaseViewSet):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -191,78 +175,34 @@ class IssueRelationViewSet(BaseViewSet):
response_data = {
"blocking": queryset.filter(pk__in=blocking_issues)
- .annotate(
- relation_type=Value("blocking", output_field=CharField())
- )
+ .annotate(relation_type=Value("blocking", output_field=CharField()))
.values(*fields),
"blocked_by": queryset.filter(pk__in=blocked_by_issues)
- .annotate(
- relation_type=Value("blocked_by", output_field=CharField())
- )
+ .annotate(relation_type=Value("blocked_by", output_field=CharField()))
.values(*fields),
"duplicate": queryset.filter(pk__in=duplicate_issues)
- .annotate(
- relation_type=Value(
- "duplicate",
- output_field=CharField(),
- )
- )
+ .annotate(relation_type=Value("duplicate", output_field=CharField()))
.values(*fields)
| queryset.filter(pk__in=duplicate_issues_related)
- .annotate(
- relation_type=Value(
- "duplicate",
- output_field=CharField(),
- )
- )
+ .annotate(relation_type=Value("duplicate", output_field=CharField()))
.values(*fields),
"relates_to": queryset.filter(pk__in=relates_to_issues)
- .annotate(
- relation_type=Value(
- "relates_to",
- output_field=CharField(),
- )
- )
+ .annotate(relation_type=Value("relates_to", output_field=CharField()))
.values(*fields)
| queryset.filter(pk__in=relates_to_issues_related)
- .annotate(
- relation_type=Value(
- "relates_to",
- output_field=CharField(),
- )
- )
+ .annotate(relation_type=Value("relates_to", output_field=CharField()))
.values(*fields),
"start_after": queryset.filter(pk__in=start_after_issues)
- .annotate(
- relation_type=Value(
- "start_after",
- output_field=CharField(),
- )
- )
+ .annotate(relation_type=Value("start_after", output_field=CharField()))
.values(*fields),
"start_before": queryset.filter(pk__in=start_before_issues)
- .annotate(
- relation_type=Value(
- "start_before",
- output_field=CharField(),
- )
- )
+ .annotate(relation_type=Value("start_before", output_field=CharField()))
.values(*fields),
"finish_after": queryset.filter(pk__in=finish_after_issues)
- .annotate(
- relation_type=Value(
- "finish_after",
- output_field=CharField(),
- )
- )
+ .annotate(relation_type=Value("finish_after", output_field=CharField()))
.values(*fields),
"finish_before": queryset.filter(pk__in=finish_before_issues)
- .annotate(
- relation_type=Value(
- "finish_before",
- output_field=CharField(),
- )
- )
+ .annotate(relation_type=Value("finish_before", output_field=CharField()))
.values(*fields),
}
@@ -284,14 +224,12 @@ class IssueRelationViewSet(BaseViewSet):
IssueRelation(
issue_id=(
issue
- if relation_type
- in ["blocking", "start_after", "finish_after"]
+ if relation_type in ["blocking", "start_after", "finish_after"]
else issue_id
),
related_issue_id=(
issue_id
- if relation_type
- in ["blocking", "start_after", "finish_after"]
+ if relation_type in ["blocking", "start_after", "finish_after"]
else issue
),
relation_type=(get_actual_relation(relation_type)),
@@ -348,8 +286,7 @@ class IssueRelationViewSet(BaseViewSet):
related_issue_id=related_issue,
)
current_instance = json.dumps(
- IssueRelationSerializer(issue_relation).data,
- cls=DjangoJSONEncoder,
+ IssueRelationSerializer(issue_relation).data, cls=DjangoJSONEncoder
)
issue_relation.delete()
issue_activity.delay(
diff --git a/apiserver/plane/app/views/issue/sub_issue.py b/apiserver/plane/app/views/issue/sub_issue.py
index cf3e108de..e461917fb 100644
--- a/apiserver/plane/app/views/issue/sub_issue.py
+++ b/apiserver/plane/app/views/issue/sub_issue.py
@@ -18,28 +18,19 @@ from rest_framework import status
from .. import BaseAPIView
from plane.app.serializers import IssueSerializer
from plane.app.permissions import ProjectEntityPermission
-from plane.db.models import (
- Issue,
- IssueLink,
- FileAsset,
- CycleIssue,
-)
+from plane.db.models import Issue, IssueLink, FileAsset, CycleIssue
from plane.bgtasks.issue_activities_task import issue_activity
from plane.utils.user_timezone_converter import user_timezone_converter
from collections import defaultdict
class SubIssuesEndpoint(BaseAPIView):
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
@method_decorator(gzip_page)
def get(self, request, slug, project_id, issue_id):
sub_issues = (
- Issue.issue_objects.filter(
- parent_id=issue_id, workspace__slug=slug
- )
+ Issue.issue_objects.filter(parent_id=issue_id, workspace__slug=slug)
.select_related("workspace", "project", "state", "parent")
.prefetch_related("assignees", "labels", "issue_module__module")
.annotate(
@@ -65,9 +56,7 @@ class SubIssuesEndpoint(BaseAPIView):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -79,7 +68,7 @@ class SubIssuesEndpoint(BaseAPIView):
distinct=True,
filter=Q(
~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ & Q(label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -150,10 +139,7 @@ class SubIssuesEndpoint(BaseAPIView):
sub_issues, datetime_fields, request.user.user_timezone
)
return Response(
- {
- "sub_issues": sub_issues,
- "state_distribution": result,
- },
+ {"sub_issues": sub_issues, "state_distribution": result},
status=status.HTTP_200_OK,
)
@@ -175,9 +161,9 @@ class SubIssuesEndpoint(BaseAPIView):
_ = Issue.objects.bulk_update(sub_issues, ["parent"], batch_size=10)
- updated_sub_issues = Issue.issue_objects.filter(
- id__in=sub_issue_ids
- ).annotate(state_group=F("state__group"))
+ updated_sub_issues = Issue.issue_objects.filter(id__in=sub_issue_ids).annotate(
+ state_group=F("state__group")
+ )
# Track the issue
_ = [
@@ -200,14 +186,8 @@ class SubIssuesEndpoint(BaseAPIView):
for sub_issue in updated_sub_issues:
result[sub_issue.state_group].append(str(sub_issue.id))
- serializer = IssueSerializer(
- updated_sub_issues,
- many=True,
- )
+ serializer = IssueSerializer(updated_sub_issues, many=True)
return Response(
- {
- "sub_issues": serializer.data,
- "state_distribution": result,
- },
+ {"sub_issues": serializer.data, "state_distribution": result},
status=status.HTTP_200_OK,
)
diff --git a/apiserver/plane/app/views/issue/subscriber.py b/apiserver/plane/app/views/issue/subscriber.py
index dc727de28..58f3ba4c7 100644
--- a/apiserver/plane/app/views/issue/subscriber.py
+++ b/apiserver/plane/app/views/issue/subscriber.py
@@ -4,37 +4,22 @@ from rest_framework import status
# Module imports
from .. import BaseViewSet
-from plane.app.serializers import (
- IssueSubscriberSerializer,
- ProjectMemberLiteSerializer,
-)
-from plane.app.permissions import (
- ProjectEntityPermission,
- ProjectLitePermission,
-)
-from plane.db.models import (
- IssueSubscriber,
- ProjectMember,
-)
+from plane.app.serializers import IssueSubscriberSerializer, ProjectMemberLiteSerializer
+from plane.app.permissions import ProjectEntityPermission, ProjectLitePermission
+from plane.db.models import IssueSubscriber, ProjectMember
class IssueSubscriberViewSet(BaseViewSet):
serializer_class = IssueSubscriberSerializer
model = IssueSubscriber
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
def get_permissions(self):
if self.action in ["subscribe", "unsubscribe", "subscription_status"]:
- self.permission_classes = [
- ProjectLitePermission,
- ]
+ self.permission_classes = [ProjectLitePermission]
else:
- self.permission_classes = [
- ProjectEntityPermission,
- ]
+ self.permission_classes = [ProjectEntityPermission]
return super(IssueSubscriberViewSet, self).get_permissions()
@@ -62,9 +47,7 @@ class IssueSubscriberViewSet(BaseViewSet):
def list(self, request, slug, project_id, issue_id):
members = ProjectMember.objects.filter(
- workspace__slug=slug,
- project_id=project_id,
- is_active=True,
+ workspace__slug=slug, project_id=project_id, is_active=True
).select_related("member")
serializer = ProjectMemberLiteSerializer(members, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
@@ -77,9 +60,7 @@ class IssueSubscriberViewSet(BaseViewSet):
issue=issue_id,
)
issue_subscriber.delete()
- return Response(
- status=status.HTTP_204_NO_CONTENT,
- )
+ return Response(status=status.HTTP_204_NO_CONTENT)
def subscribe(self, request, slug, project_id, issue_id):
if IssueSubscriber.objects.filter(
@@ -94,9 +75,7 @@ class IssueSubscriberViewSet(BaseViewSet):
)
subscriber = IssueSubscriber.objects.create(
- issue_id=issue_id,
- subscriber_id=request.user.id,
- project_id=project_id,
+ issue_id=issue_id, subscriber_id=request.user.id, project_id=project_id
)
serializer = IssueSubscriberSerializer(subscriber)
return Response(serializer.data, status=status.HTTP_201_CREATED)
@@ -109,9 +88,7 @@ class IssueSubscriberViewSet(BaseViewSet):
issue=issue_id,
)
issue_subscriber.delete()
- return Response(
- status=status.HTTP_204_NO_CONTENT,
- )
+ return Response(status=status.HTTP_204_NO_CONTENT)
def subscription_status(self, request, slug, project_id, issue_id):
issue_subscriber = IssueSubscriber.objects.filter(
@@ -120,6 +97,4 @@ class IssueSubscriberViewSet(BaseViewSet):
workspace__slug=slug,
project=project_id,
).exists()
- return Response(
- {"subscribed": issue_subscriber}, status=status.HTTP_200_OK
- )
+ return Response({"subscribed": issue_subscriber}, status=status.HTTP_200_OK)
diff --git a/apiserver/plane/app/views/module/archive.py b/apiserver/plane/app/views/module/archive.py
index 997cac4cd..82c1d47eb 100644
--- a/apiserver/plane/app/views/module/archive.py
+++ b/apiserver/plane/app/views/module/archive.py
@@ -24,12 +24,8 @@ from django.db import models
# Third party imports
from rest_framework import status
from rest_framework.response import Response
-from plane.app.permissions import (
- ProjectEntityPermission,
-)
-from plane.app.serializers import (
- ModuleDetailSerializer,
-)
+from plane.app.permissions import ProjectEntityPermission
+from plane.app.serializers import ModuleDetailSerializer
from plane.db.models import Issue, Module, ModuleLink, UserFavorite, Project
from plane.utils.analytics_plot import burndown_plot
from plane.utils.user_timezone_converter import user_timezone_converter
@@ -40,10 +36,7 @@ from .. import BaseAPIView
class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
-
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
def get_queryset(self):
favorite_subquery = UserFavorite.objects.filter(
@@ -136,9 +129,7 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
)
.values("issue_module__module_id")
.annotate(
- total_estimate_points=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ total_estimate_points=Sum(Cast("estimate_point__value", FloatField()))
)
.values("total_estimate_points")[:1]
)
@@ -151,9 +142,7 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
)
.values("issue_module__module_id")
.annotate(
- backlog_estimate_point=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ backlog_estimate_point=Sum(Cast("estimate_point__value", FloatField()))
)
.values("backlog_estimate_point")[:1]
)
@@ -181,9 +170,7 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
)
.values("issue_module__module_id")
.annotate(
- started_estimate_point=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ started_estimate_point=Sum(Cast("estimate_point__value", FloatField()))
)
.values("started_estimate_point")[:1]
)
@@ -212,9 +199,7 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
.prefetch_related(
Prefetch(
"link_module",
- queryset=ModuleLink.objects.select_related(
- "module", "created_by"
- ),
+ queryset=ModuleLink.objects.select_related("module", "created_by"),
)
)
.annotate(
@@ -231,8 +216,7 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
)
.annotate(
started_issues=Coalesce(
- Subquery(started_issues[:1]),
- Value(0, output_field=IntegerField()),
+ Subquery(started_issues[:1]), Value(0, output_field=IntegerField())
)
)
.annotate(
@@ -243,51 +227,48 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
)
.annotate(
backlog_issues=Coalesce(
- Subquery(backlog_issues[:1]),
- Value(0, output_field=IntegerField()),
+ Subquery(backlog_issues[:1]), Value(0, output_field=IntegerField())
)
)
.annotate(
total_issues=Coalesce(
- Subquery(total_issues[:1]),
- Value(0, output_field=IntegerField()),
+ Subquery(total_issues[:1]), Value(0, output_field=IntegerField())
)
)
.annotate(
backlog_estimate_points=Coalesce(
Subquery(backlog_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
unstarted_estimate_points=Coalesce(
Subquery(unstarted_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
started_estimate_points=Coalesce(
Subquery(started_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
cancelled_estimate_points=Coalesce(
Subquery(cancelled_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
completed_estimate_points=Coalesce(
Subquery(completed_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
total_estimate_points=Coalesce(
- Subquery(total_estimate_point),
- Value(0, output_field=FloatField()),
- ),
+ Subquery(total_estimate_point), Value(0, output_field=FloatField())
+ )
)
.annotate(
member_ids=Coalesce(
@@ -409,9 +390,7 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
"display_name",
)
.annotate(
- total_estimates=Sum(
- Cast("estimate_point__value", FloatField())
- ),
+ total_estimates=Sum(Cast("estimate_point__value", FloatField()))
)
.annotate(
completed_estimates=Sum(
@@ -447,9 +426,7 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
.annotate(label_id=F("labels__id"))
.values("label_name", "color", "label_id")
.annotate(
- total_estimates=Sum(
- Cast("estimate_point__value", FloatField())
- ),
+ total_estimates=Sum(Cast("estimate_point__value", FloatField()))
)
.annotate(
completed_estimates=Sum(
@@ -473,20 +450,16 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
)
.order_by("label_name")
)
- data["estimate_distribution"][
- "assignees"
- ] = assignee_distribution
+ data["estimate_distribution"]["assignees"] = assignee_distribution
data["estimate_distribution"]["labels"] = label_distribution
if modules and modules.start_date and modules.target_date:
- data["estimate_distribution"]["completion_chart"] = (
- burndown_plot(
- queryset=modules,
- slug=slug,
- project_id=project_id,
- plot_type="points",
- module_id=pk,
- )
+ data["estimate_distribution"]["completion_chart"] = burndown_plot(
+ queryset=modules,
+ slug=slug,
+ project_id=project_id,
+ plot_type="points",
+ module_id=pk,
)
assignee_distribution = (
@@ -529,12 +502,8 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
)
.annotate(
total_issues=Count(
- "id",
- filter=Q(
- archived_at__isnull=True,
- is_draft=False,
- ),
- ),
+ "id", filter=Q(archived_at__isnull=True, is_draft=False)
+ )
)
.annotate(
completed_issues=Count(
@@ -572,12 +541,8 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
.values("label_name", "color", "label_id")
.annotate(
total_issues=Count(
- "id",
- filter=Q(
- archived_at__isnull=True,
- is_draft=False,
- ),
- ),
+ "id", filter=Q(archived_at__isnull=True, is_draft=False)
+ )
)
.annotate(
completed_issues=Count(
@@ -616,10 +581,7 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
module_id=pk,
)
- return Response(
- data,
- status=status.HTTP_200_OK,
- )
+ return Response(data, status=status.HTTP_200_OK)
def post(self, request, slug, project_id, module_id):
module = Module.objects.get(
@@ -627,9 +589,7 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
)
if module.status not in ["completed", "cancelled"]:
return Response(
- {
- "error": "Only completed or cancelled modules can be archived"
- },
+ {"error": "Only completed or cancelled modules can be archived"},
status=status.HTTP_400_BAD_REQUEST,
)
module.archived_at = timezone.now()
@@ -641,8 +601,7 @@ class ModuleArchiveUnarchiveEndpoint(BaseAPIView):
workspace__slug=slug,
).delete()
return Response(
- {"archived_at": str(module.archived_at)},
- status=status.HTTP_200_OK,
+ {"archived_at": str(module.archived_at)}, status=status.HTTP_200_OK
)
def delete(self, request, slug, project_id, module_id):
diff --git a/apiserver/plane/app/views/module/base.py b/apiserver/plane/app/views/module/base.py
index d53f13190..8f9839b71 100644
--- a/apiserver/plane/app/views/module/base.py
+++ b/apiserver/plane/app/views/module/base.py
@@ -164,9 +164,7 @@ class ModuleViewSet(BaseViewSet):
)
.values("issue_module__module_id")
.annotate(
- total_estimate_points=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ total_estimate_points=Sum(Cast("estimate_point__value", FloatField()))
)
.values("total_estimate_points")[:1]
)
@@ -179,9 +177,7 @@ class ModuleViewSet(BaseViewSet):
)
.values("issue_module__module_id")
.annotate(
- backlog_estimate_point=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ backlog_estimate_point=Sum(Cast("estimate_point__value", FloatField()))
)
.values("backlog_estimate_point")[:1]
)
@@ -209,9 +205,7 @@ class ModuleViewSet(BaseViewSet):
)
.values("issue_module__module_id")
.annotate(
- started_estimate_point=Sum(
- Cast("estimate_point__value", FloatField())
- )
+ started_estimate_point=Sum(Cast("estimate_point__value", FloatField()))
)
.values("started_estimate_point")[:1]
)
@@ -243,9 +237,7 @@ class ModuleViewSet(BaseViewSet):
.prefetch_related(
Prefetch(
"link_module",
- queryset=ModuleLink.objects.select_related(
- "module", "created_by"
- ),
+ queryset=ModuleLink.objects.select_related("module", "created_by"),
)
)
.annotate(
@@ -262,8 +254,7 @@ class ModuleViewSet(BaseViewSet):
)
.annotate(
started_issues=Coalesce(
- Subquery(started_issues[:1]),
- Value(0, output_field=IntegerField()),
+ Subquery(started_issues[:1]), Value(0, output_field=IntegerField())
)
)
.annotate(
@@ -274,51 +265,48 @@ class ModuleViewSet(BaseViewSet):
)
.annotate(
backlog_issues=Coalesce(
- Subquery(backlog_issues[:1]),
- Value(0, output_field=IntegerField()),
+ Subquery(backlog_issues[:1]), Value(0, output_field=IntegerField())
)
)
.annotate(
total_issues=Coalesce(
- Subquery(total_issues[:1]),
- Value(0, output_field=IntegerField()),
+ Subquery(total_issues[:1]), Value(0, output_field=IntegerField())
)
)
.annotate(
backlog_estimate_points=Coalesce(
Subquery(backlog_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
unstarted_estimate_points=Coalesce(
Subquery(unstarted_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
started_estimate_points=Coalesce(
Subquery(started_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
cancelled_estimate_points=Coalesce(
Subquery(cancelled_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
completed_estimate_points=Coalesce(
Subquery(completed_estimate_point),
Value(0, output_field=FloatField()),
- ),
+ )
)
.annotate(
total_estimate_points=Coalesce(
- Subquery(total_estimate_point),
- Value(0, output_field=FloatField()),
- ),
+ Subquery(total_estimate_point), Value(0, output_field=FloatField())
+ )
)
.annotate(
member_ids=Coalesce(
@@ -333,12 +321,7 @@ class ModuleViewSet(BaseViewSet):
.order_by("-is_favorite", "-created_at")
)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def create(self, request, slug, project_id):
project = Project.objects.get(workspace__slug=slug, pk=project_id)
serializer = ModuleWriteSerializer(
@@ -405,11 +388,7 @@ class ModuleViewSet(BaseViewSet):
def list(self, request, slug, project_id):
queryset = self.get_queryset().filter(archived_at__isnull=True)
if self.fields:
- modules = ModuleSerializer(
- queryset,
- many=True,
- fields=self.fields,
- ).data
+ modules = ModuleSerializer(queryset, many=True, fields=self.fields).data
else:
modules = queryset.values( # Required fields
"id",
@@ -470,8 +449,7 @@ class ModuleViewSet(BaseViewSet):
if not queryset.exists():
return Response(
- {"error": "Module not found"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Module not found"}, status=status.HTTP_404_NOT_FOUND
)
estimate_type = Project.objects.filter(
@@ -526,9 +504,7 @@ class ModuleViewSet(BaseViewSet):
"display_name",
)
.annotate(
- total_estimates=Sum(
- Cast("estimate_point__value", FloatField())
- ),
+ total_estimates=Sum(Cast("estimate_point__value", FloatField()))
)
.annotate(
completed_estimates=Sum(
@@ -565,9 +541,7 @@ class ModuleViewSet(BaseViewSet):
.annotate(label_id=F("labels__id"))
.values("label_name", "color", "label_id")
.annotate(
- total_estimates=Sum(
- Cast("estimate_point__value", FloatField())
- ),
+ total_estimates=Sum(Cast("estimate_point__value", FloatField()))
)
.annotate(
completed_estimates=Sum(
@@ -595,14 +569,12 @@ class ModuleViewSet(BaseViewSet):
data["estimate_distribution"]["labels"] = label_distribution
if modules and modules.start_date and modules.target_date:
- data["estimate_distribution"]["completion_chart"] = (
- burndown_plot(
- queryset=modules,
- slug=slug,
- project_id=project_id,
- plot_type="points",
- module_id=pk,
- )
+ data["estimate_distribution"]["completion_chart"] = burndown_plot(
+ queryset=modules,
+ slug=slug,
+ project_id=project_id,
+ plot_type="points",
+ module_id=pk,
)
assignee_distribution = (
@@ -629,28 +601,19 @@ class ModuleViewSet(BaseViewSet):
),
# If `avatar_asset` is None, fall back to using `avatar` field directly
When(
- assignees__avatar_asset__isnull=True,
- then="assignees__avatar",
+ assignees__avatar_asset__isnull=True, then="assignees__avatar"
),
default=Value(None),
output_field=models.CharField(),
)
)
.values(
- "first_name",
- "last_name",
- "assignee_id",
- "avatar_url",
- "display_name",
+ "first_name", "last_name", "assignee_id", "avatar_url", "display_name"
)
.annotate(
total_issues=Count(
- "id",
- filter=Q(
- archived_at__isnull=True,
- is_draft=False,
- ),
- ),
+ "id", filter=Q(archived_at__isnull=True, is_draft=False)
+ )
)
.annotate(
completed_issues=Count(
@@ -688,12 +651,8 @@ class ModuleViewSet(BaseViewSet):
.values("label_name", "color", "label_id")
.annotate(
total_issues=Count(
- "id",
- filter=Q(
- archived_at__isnull=True,
- is_draft=False,
- ),
- ),
+ "id", filter=Q(archived_at__isnull=True, is_draft=False)
+ )
)
.annotate(
completed_issues=Count(
@@ -746,10 +705,7 @@ class ModuleViewSet(BaseViewSet):
project_id=project_id,
)
- return Response(
- data,
- status=status.HTTP_200_OK,
- )
+ return Response(data, status=status.HTTP_200_OK)
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def partial_update(self, request, slug, project_id, pk):
@@ -823,14 +779,10 @@ class ModuleViewSet(BaseViewSet):
@allow_permission([ROLE.ADMIN], creator=True, model=Module)
def destroy(self, request, slug, project_id, pk):
- module = Module.objects.get(
- workspace__slug=slug, project_id=project_id, pk=pk
- )
+ module = Module.objects.get(workspace__slug=slug, project_id=project_id, pk=pk)
module_issues = list(
- ModuleIssue.objects.filter(module_id=pk).values_list(
- "issue", flat=True
- )
+ ModuleIssue.objects.filter(module_id=pk).values_list("issue", flat=True)
)
_ = [
issue_activity.delay(
@@ -848,10 +800,7 @@ class ModuleViewSet(BaseViewSet):
]
module.delete()
# Delete the module issues
- ModuleIssue.objects.filter(
- module=pk,
- project_id=project_id,
- ).delete()
+ ModuleIssue.objects.filter(module=pk, project_id=project_id).delete()
# Delete the user favorite module
UserFavorite.objects.filter(
user=request.user,
@@ -863,9 +812,7 @@ class ModuleViewSet(BaseViewSet):
class ModuleLinkViewSet(BaseViewSet):
- permission_classes = [
- ProjectEntityPermission,
- ]
+ permission_classes = [ProjectEntityPermission]
model = ModuleLink
serializer_class = ModuleLinkSerializer
@@ -895,9 +842,7 @@ class ModuleLinkViewSet(BaseViewSet):
class ModuleFavoriteViewSet(BaseViewSet):
model = UserFavorite
- permission_classes = [
- ProjectLitePermission,
- ]
+ permission_classes = [ProjectLitePermission]
def get_queryset(self):
return self.filter_queryset(
@@ -930,7 +875,6 @@ class ModuleFavoriteViewSet(BaseViewSet):
class ModuleUserPropertiesEndpoint(BaseAPIView):
-
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def patch(self, request, slug, project_id, module_id):
module_properties = ModuleUserProperties.objects.get(
diff --git a/apiserver/plane/app/views/module/issue.py b/apiserver/plane/app/views/module/issue.py
index dd829753c..06b0a2fb1 100644
--- a/apiserver/plane/app/views/module/issue.py
+++ b/apiserver/plane/app/views/module/issue.py
@@ -13,9 +13,7 @@ from rest_framework import status
from rest_framework.response import Response
from plane.app.permissions import allow_permission, ROLE
-from plane.app.serializers import (
- ModuleIssueSerializer,
-)
+from plane.app.serializers import ModuleIssueSerializer
from plane.bgtasks.issue_activities_task import issue_activity
from plane.db.models import (
Issue,
@@ -32,10 +30,7 @@ from plane.utils.grouper import (
)
from plane.utils.issue_filters import issue_filters
from plane.utils.order_queryset import order_issue_queryset
-from plane.utils.paginator import (
- GroupedOffsetPaginator,
- SubGroupedOffsetPaginator,
-)
+from plane.utils.paginator import GroupedOffsetPaginator, SubGroupedOffsetPaginator
# Module imports
from .. import BaseViewSet
@@ -47,10 +42,7 @@ class ModuleIssueViewSet(BaseViewSet):
webhook_event = "module_issue"
bulk = True
- filterset_fields = [
- "issue__labels__id",
- "issue__assignees__id",
- ]
+ filterset_fields = ["issue__labels__id", "issue__assignees__id"]
def get_queryset(self):
return (
@@ -85,9 +77,7 @@ class ModuleIssueViewSet(BaseViewSet):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -95,12 +85,7 @@ class ModuleIssueViewSet(BaseViewSet):
).distinct()
@method_decorator(gzip_page)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def list(self, request, slug, project_id, module_id):
filters = issue_filters(request.query_params, "GET")
issue_queryset = self.get_queryset().filter(**filters)
@@ -108,8 +93,7 @@ class ModuleIssueViewSet(BaseViewSet):
# Issue queryset
issue_queryset, order_by_param = order_issue_queryset(
- issue_queryset=issue_queryset,
- order_by_param=order_by_param,
+ issue_queryset=issue_queryset, order_by_param=order_by_param
)
# Group by
@@ -118,9 +102,7 @@ class ModuleIssueViewSet(BaseViewSet):
# issue queryset
issue_queryset = issue_queryset_grouper(
- queryset=issue_queryset,
- group_by=group_by,
- sub_group_by=sub_group_by,
+ queryset=issue_queryset, group_by=group_by, sub_group_by=sub_group_by
)
if group_by:
@@ -140,9 +122,7 @@ class ModuleIssueViewSet(BaseViewSet):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=SubGroupedOffsetPaginator,
group_by_fields=issue_group_values(
@@ -176,9 +156,7 @@ class ModuleIssueViewSet(BaseViewSet):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=GroupedOffsetPaginator,
group_by_fields=issue_group_values(
@@ -214,8 +192,7 @@ class ModuleIssueViewSet(BaseViewSet):
issues = request.data.get("issues", [])
if not issues:
return Response(
- {"error": "Issues are required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Issues are required"}, status=status.HTTP_400_BAD_REQUEST
)
project = Project.objects.get(pk=project_id)
_ = ModuleIssue.objects.bulk_create(
diff --git a/apiserver/plane/app/views/notification/base.py b/apiserver/plane/app/views/notification/base.py
index c4aa14969..d2aa1a02d 100644
--- a/apiserver/plane/app/views/notification/base.py
+++ b/apiserver/plane/app/views/notification/base.py
@@ -41,8 +41,7 @@ class NotificationViewSet(BaseViewSet, BasePaginator):
)
@allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST],
- level="WORKSPACE",
+ allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE"
)
def list(self, request, slug):
# Get query parameters
@@ -79,10 +78,8 @@ class NotificationViewSet(BaseViewSet, BasePaginator):
# Filters based on query parameters
snoozed_filters = {
- "true": Q(snoozed_till__lt=timezone.now())
- | Q(snoozed_till__isnull=False),
- "false": Q(snoozed_till__gte=timezone.now())
- | Q(snoozed_till__isnull=True),
+ "true": Q(snoozed_till__lt=timezone.now()) | Q(snoozed_till__isnull=False),
+ "false": Q(snoozed_till__gte=timezone.now()) | Q(snoozed_till__isnull=True),
}
notifications = notifications.filter(snoozed_filters[snoozed])
@@ -103,9 +100,7 @@ class NotificationViewSet(BaseViewSet, BasePaginator):
if mentioned:
notifications = notifications.filter(sender__icontains="mentioned")
else:
- notifications = notifications.exclude(
- sender__icontains="mentioned"
- )
+ notifications = notifications.exclude(sender__icontains="mentioned")
type = type.split(",")
# Subscribed issues
@@ -143,10 +138,7 @@ class NotificationViewSet(BaseViewSet, BasePaginator):
# Created issues
if "created" in type:
if WorkspaceMember.objects.filter(
- workspace__slug=slug,
- member=request.user,
- role__lt=15,
- is_active=True,
+ workspace__slug=slug, member=request.user, role__lt=15, is_active=True
).exists():
notifications = notifications.none()
else:
@@ -159,9 +151,7 @@ class NotificationViewSet(BaseViewSet, BasePaginator):
notifications = notifications.filter(q_filters)
# Pagination
- if request.GET.get("per_page", False) and request.GET.get(
- "cursor", False
- ):
+ if request.GET.get("per_page", False) and request.GET.get("cursor", False):
return self.paginate(
order_by=request.GET.get("order_by", "-created_at"),
request=request,
@@ -175,17 +165,14 @@ class NotificationViewSet(BaseViewSet, BasePaginator):
return Response(serializer.data, status=status.HTTP_200_OK)
@allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST],
- level="WORKSPACE",
+ allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE"
)
def partial_update(self, request, slug, pk):
notification = Notification.objects.get(
workspace__slug=slug, pk=pk, receiver=request.user
)
# Only read_at and snoozed_till can be updated
- notification_data = {
- "snoozed_till": request.data.get("snoozed_till", None),
- }
+ notification_data = {"snoozed_till": request.data.get("snoozed_till", None)}
serializer = NotificationSerializer(
notification, data=notification_data, partial=True
)
@@ -246,8 +233,7 @@ class NotificationViewSet(BaseViewSet, BasePaginator):
class UnreadNotificationEndpoint(BaseAPIView):
@allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST],
- level="WORKSPACE",
+ allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE"
)
def get(self, request, slug):
# Watching Issues Count
@@ -274,12 +260,8 @@ class UnreadNotificationEndpoint(BaseAPIView):
return Response(
{
- "total_unread_notifications_count": int(
- unread_notifications_count
- ),
- "mention_unread_notifications_count": int(
- mention_notifications_count
- ),
+ "total_unread_notifications_count": int(unread_notifications_count),
+ "mention_unread_notifications_count": int(mention_notifications_count),
},
status=status.HTTP_200_OK,
)
@@ -296,9 +278,7 @@ class MarkAllReadNotificationViewSet(BaseViewSet):
notifications = (
Notification.objects.filter(
- workspace__slug=slug,
- receiver_id=request.user.id,
- read_at__isnull=True,
+ workspace__slug=slug, receiver_id=request.user.id, read_at__isnull=True
)
.select_related("workspace", "project", "triggered_by", "receiver")
.order_by("snoozed_till", "-created_at")
@@ -307,13 +287,11 @@ class MarkAllReadNotificationViewSet(BaseViewSet):
# Filter for snoozed notifications
if snoozed:
notifications = notifications.filter(
- Q(snoozed_till__lt=timezone.now())
- | Q(snoozed_till__isnull=False)
+ Q(snoozed_till__lt=timezone.now()) | Q(snoozed_till__isnull=False)
)
else:
notifications = notifications.filter(
- Q(snoozed_till__gte=timezone.now())
- | Q(snoozed_till__isnull=True),
+ Q(snoozed_till__gte=timezone.now()) | Q(snoozed_till__isnull=True)
)
# Filter for archived or unarchive
@@ -327,35 +305,26 @@ class MarkAllReadNotificationViewSet(BaseViewSet):
issue_ids = IssueSubscriber.objects.filter(
workspace__slug=slug, subscriber_id=request.user.id
).values_list("issue_id", flat=True)
- notifications = notifications.filter(
- entity_identifier__in=issue_ids
- )
+ notifications = notifications.filter(entity_identifier__in=issue_ids)
# Assigned Issues
if type == "assigned":
issue_ids = IssueAssignee.objects.filter(
workspace__slug=slug, assignee_id=request.user.id
).values_list("issue_id", flat=True)
- notifications = notifications.filter(
- entity_identifier__in=issue_ids
- )
+ notifications = notifications.filter(entity_identifier__in=issue_ids)
# Created issues
if type == "created":
if WorkspaceMember.objects.filter(
- workspace__slug=slug,
- member=request.user,
- role__lt=15,
- is_active=True,
+ workspace__slug=slug, member=request.user, role__lt=15, is_active=True
).exists():
notifications = Notification.objects.none()
else:
issue_ids = Issue.objects.filter(
workspace__slug=slug, created_by=request.user
).values_list("pk", flat=True)
- notifications = notifications.filter(
- entity_identifier__in=issue_ids
- )
+ notifications = notifications.filter(entity_identifier__in=issue_ids)
updated_notifications = []
for notification in notifications:
@@ -376,9 +345,7 @@ class UserNotificationPreferenceEndpoint(BaseAPIView):
user_notification_preference = UserNotificationPreference.objects.get(
user=request.user
)
- serializer = UserNotificationPreferenceSerializer(
- user_notification_preference
- )
+ serializer = UserNotificationPreferenceSerializer(user_notification_preference)
return Response(serializer.data, status=status.HTTP_200_OK)
# update the object
diff --git a/apiserver/plane/app/views/page/base.py b/apiserver/plane/app/views/page/base.py
index 5e56cc703..24ceb2d3f 100644
--- a/apiserver/plane/app/views/page/base.py
+++ b/apiserver/plane/app/views/page/base.py
@@ -60,9 +60,7 @@ def unarchive_archive_page_and_descendants(page_id, archived_at):
class PageViewSet(BaseViewSet):
serializer_class = PageSerializer
model = Page
- search_fields = [
- "name",
- ]
+ search_fields = ["name"]
def get_queryset(self):
subquery = UserFavorite.objects.filter(
@@ -92,8 +90,7 @@ class PageViewSet(BaseViewSet):
.annotate(
project=Exists(
ProjectPage.objects.filter(
- page_id=OuterRef("id"),
- project_id=self.kwargs.get("project_id"),
+ page_id=OuterRef("id"), project_id=self.kwargs.get("project_id")
)
)
)
@@ -108,9 +105,7 @@ class PageViewSet(BaseViewSet):
),
project_ids=Coalesce(
ArrayAgg(
- "projects__id",
- distinct=True,
- filter=~Q(projects__id=True),
+ "projects__id", distinct=True, filter=~Q(projects__id=True)
),
Value([], output_field=ArrayField(UUIDField())),
),
@@ -126,9 +121,7 @@ class PageViewSet(BaseViewSet):
context={
"project_id": project_id,
"owned_by_id": request.user.id,
- "description_html": request.data.get(
- "description_html", ""
- ),
+ "description_html": request.data.get("description_html", ""),
},
)
@@ -145,23 +138,18 @@ class PageViewSet(BaseViewSet):
def partial_update(self, request, slug, project_id, pk):
try:
page = Page.objects.get(
- pk=pk,
- workspace__slug=slug,
- projects__id=project_id,
+ pk=pk, workspace__slug=slug, projects__id=project_id
)
if page.is_locked:
return Response(
- {"error": "Page is locked"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Page is locked"}, status=status.HTTP_400_BAD_REQUEST
)
parent = request.data.get("parent", None)
if parent:
_ = Page.objects.get(
- pk=parent,
- workspace__slug=slug,
- projects__id=project_id,
+ pk=parent, workspace__slug=slug, projects__id=project_id
)
# Only update access if the page owner is the requesting user
@@ -176,9 +164,7 @@ class PageViewSet(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST,
)
- serializer = PageDetailSerializer(
- page, data=request.data, partial=True
- )
+ serializer = PageDetailSerializer(page, data=request.data, partial=True)
page_description = page.description_html
if serializer.is_valid():
serializer.save()
@@ -187,18 +173,14 @@ class PageViewSet(BaseViewSet):
page_transaction.delay(
new_value=request.data,
old_value=json.dumps(
- {
- "description_html": page_description,
- },
+ {"description_html": page_description},
cls=DjangoJSONEncoder,
),
page_id=pk,
)
return Response(serializer.data, status=status.HTTP_200_OK)
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except Page.DoesNotExist:
return Response(
{
@@ -207,13 +189,7 @@ class PageViewSet(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST,
)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def retrieve(self, request, slug, project_id, pk=None):
page = self.get_queryset().filter(pk=pk).first()
project = Project.objects.get(pk=project_id)
@@ -241,8 +217,7 @@ class PageViewSet(BaseViewSet):
if page is None:
return Response(
- {"error": "Page not found"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Page not found"}, status=status.HTTP_404_NOT_FOUND
)
else:
issue_ids = PageLog.objects.filter(
@@ -257,10 +232,7 @@ class PageViewSet(BaseViewSet):
user_id=request.user.id,
project_id=project_id,
)
- return Response(
- data,
- status=status.HTTP_200_OK,
- )
+ return Response(data, status=status.HTTP_200_OK)
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def lock(self, request, slug, project_id, pk):
@@ -306,13 +278,7 @@ class PageViewSet(BaseViewSet):
page.save()
return Response(status=status.HTTP_204_NO_CONTENT)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def list(self, request, slug, project_id):
queryset = self.get_queryset()
project = Project.objects.get(pk=project_id)
@@ -332,17 +298,12 @@ class PageViewSet(BaseViewSet):
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def archive(self, request, slug, project_id, pk):
- page = Page.objects.get(
- pk=pk, workspace__slug=slug, projects__id=project_id
- )
+ page = Page.objects.get(pk=pk, workspace__slug=slug, projects__id=project_id)
# only the owner or admin can archive the page
if (
ProjectMember.objects.filter(
- project_id=project_id,
- member=request.user,
- is_active=True,
- role__lte=15,
+ project_id=project_id, member=request.user, is_active=True, role__lte=15
).exists()
and request.user.id != page.owned_by_id
):
@@ -360,24 +321,16 @@ class PageViewSet(BaseViewSet):
unarchive_archive_page_and_descendants(pk, datetime.now())
- return Response(
- {"archived_at": str(datetime.now())},
- status=status.HTTP_200_OK,
- )
+ return Response({"archived_at": str(datetime.now())}, status=status.HTTP_200_OK)
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def unarchive(self, request, slug, project_id, pk):
- page = Page.objects.get(
- pk=pk, workspace__slug=slug, projects__id=project_id
- )
+ page = Page.objects.get(pk=pk, workspace__slug=slug, projects__id=project_id)
# only the owner or admin can un archive the page
if (
ProjectMember.objects.filter(
- project_id=project_id,
- member=request.user,
- is_active=True,
- role__lte=15,
+ project_id=project_id, member=request.user, is_active=True, role__lte=15
).exists()
and request.user.id != page.owned_by_id
):
@@ -397,9 +350,7 @@ class PageViewSet(BaseViewSet):
@allow_permission([ROLE.ADMIN], creator=True, model=Page)
def destroy(self, request, slug, project_id, pk):
- page = Page.objects.get(
- pk=pk, workspace__slug=slug, projects__id=project_id
- )
+ page = Page.objects.get(pk=pk, workspace__slug=slug, projects__id=project_id)
if page.archived_at is None:
return Response(
@@ -438,7 +389,6 @@ class PageViewSet(BaseViewSet):
class PageFavoriteViewSet(BaseViewSet):
-
model = UserFavorite
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
@@ -465,7 +415,6 @@ class PageFavoriteViewSet(BaseViewSet):
class PageLogEndpoint(BaseAPIView):
-
serializer_class = PageLogSerializer
model = PageLog
@@ -504,7 +453,6 @@ class PageLogEndpoint(BaseAPIView):
class SubPagesEndpoint(BaseAPIView):
-
@method_decorator(gzip_page)
def get(self, request, slug, project_id, page_id):
pages = (
@@ -522,27 +470,15 @@ class SubPagesEndpoint(BaseAPIView):
class PagesDescriptionViewSet(BaseViewSet):
-
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ]
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def retrieve(self, request, slug, project_id, pk):
page = (
- Page.objects.filter(
- pk=pk, workspace__slug=slug, projects__id=project_id
- )
+ Page.objects.filter(pk=pk, workspace__slug=slug, projects__id=project_id)
.filter(Q(owned_by=self.request.user) | Q(access=0))
.first()
)
if page is None:
- return Response(
- {"error": "Page not found"},
- status=404,
- )
+ return Response({"error": "Page not found"}, status=404)
binary_data = page.description_binary
def stream_data():
@@ -554,26 +490,19 @@ class PagesDescriptionViewSet(BaseViewSet):
response = StreamingHttpResponse(
stream_data(), content_type="application/octet-stream"
)
- response["Content-Disposition"] = (
- 'attachment; filename="page_description.bin"'
- )
+ response["Content-Disposition"] = 'attachment; filename="page_description.bin"'
return response
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def partial_update(self, request, slug, project_id, pk):
page = (
- Page.objects.filter(
- pk=pk, workspace__slug=slug, projects__id=project_id
- )
+ Page.objects.filter(pk=pk, workspace__slug=slug, projects__id=project_id)
.filter(Q(owned_by=self.request.user) | Q(access=0))
.first()
)
if page is None:
- return Response(
- {"error": "Page not found"},
- status=404,
- )
+ return Response({"error": "Page not found"}, status=404)
if page.is_locked:
return Response(
@@ -595,10 +524,7 @@ class PagesDescriptionViewSet(BaseViewSet):
# Serialize the existing instance
existing_instance = json.dumps(
- {
- "description_html": page.description_html,
- },
- cls=DjangoJSONEncoder,
+ {"description_html": page.description_html}, cls=DjangoJSONEncoder
)
# Get the base64 data from the request
@@ -611,9 +537,7 @@ class PagesDescriptionViewSet(BaseViewSet):
# capture the page transaction
if request.data.get("description_html"):
page_transaction.delay(
- new_value=request.data,
- old_value=existing_instance,
- page_id=pk,
+ new_value=request.data, old_value=existing_instance, page_id=pk
)
# Store the updated binary data
page.description_binary = new_binary_data
diff --git a/apiserver/plane/app/views/page/version.py b/apiserver/plane/app/views/page/version.py
index 1152be4f7..bcf2f4f5b 100644
--- a/apiserver/plane/app/views/page/version.py
+++ b/apiserver/plane/app/views/page/version.py
@@ -5,34 +5,25 @@ from rest_framework.response import Response
# Module imports
from plane.db.models import PageVersion
from ..base import BaseAPIView
-from plane.app.serializers import (
- PageVersionSerializer,
- PageVersionDetailSerializer,
-)
+from plane.app.serializers import PageVersionSerializer, PageVersionDetailSerializer
from plane.app.permissions import allow_permission, ROLE
class PageVersionEndpoint(BaseAPIView):
-
- @allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST]
- )
+ @allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def get(self, request, slug, project_id, page_id, pk=None):
# Check if pk is provided
if pk:
# Return a single page version
page_version = PageVersion.objects.get(
- workspace__slug=slug,
- page_id=page_id,
- pk=pk,
+ workspace__slug=slug, page_id=page_id, pk=pk
)
# Serialize the page version
serializer = PageVersionDetailSerializer(page_version)
return Response(serializer.data, status=status.HTTP_200_OK)
# Return all page versions
page_versions = PageVersion.objects.filter(
- workspace__slug=slug,
- page_id=page_id,
+ workspace__slug=slug, page_id=page_id
)
# Serialize the page versions
serializer = PageVersionSerializer(page_versions, many=True)
diff --git a/apiserver/plane/app/views/project/base.py b/apiserver/plane/app/views/project/base.py
index d53b3fac7..7b027df98 100644
--- a/apiserver/plane/app/views/project/base.py
+++ b/apiserver/plane/app/views/project/base.py
@@ -6,15 +6,7 @@ import json
# Django imports
from django.db import IntegrityError
-from django.db.models import (
- Exists,
- F,
- Func,
- OuterRef,
- Prefetch,
- Q,
- Subquery,
-)
+from django.db.models import Exists, F, Func, OuterRef, Prefetch, Q, Subquery
from django.core.serializers.json import DjangoJSONEncoder
# Third Party imports
@@ -30,11 +22,7 @@ from plane.app.serializers import (
DeployBoardSerializer,
)
-from plane.app.permissions import (
- ProjectMemberPermission,
- allow_permission,
- ROLE,
-)
+from plane.app.permissions import ProjectMemberPermission, allow_permission, ROLE
from plane.db.models import (
UserFavorite,
Cycle,
@@ -73,10 +61,7 @@ class ProjectViewSet(BaseViewSet):
.get_queryset()
.filter(workspace__slug=self.kwargs.get("slug"))
.select_related(
- "workspace",
- "workspace__owner",
- "default_assignee",
- "project_lead",
+ "workspace", "workspace__owner", "default_assignee", "project_lead"
)
.annotate(
is_favorite=Exists(
@@ -100,9 +85,7 @@ class ProjectViewSet(BaseViewSet):
)
.annotate(
total_members=ProjectMember.objects.filter(
- project_id=OuterRef("id"),
- member__is_bot=False,
- is_active=True,
+ project_id=OuterRef("id"), member__is_bot=False, is_active=True
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
@@ -139,8 +122,7 @@ class ProjectViewSet(BaseViewSet):
Prefetch(
"project_projectmember",
queryset=ProjectMember.objects.filter(
- workspace__slug=self.kwargs.get("slug"),
- is_active=True,
+ workspace__slug=self.kwargs.get("slug"), is_active=True
).select_related("member"),
to_attr="members_list",
)
@@ -149,21 +131,13 @@ class ProjectViewSet(BaseViewSet):
)
@allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST],
- level="WORKSPACE",
+ allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE"
)
def list(self, request, slug):
- fields = [
- field
- for field in request.GET.get("fields", "").split(",")
- if field
- ]
+ fields = [field for field in request.GET.get("fields", "").split(",") if field]
projects = self.get_queryset().order_by("sort_order", "name")
if WorkspaceMember.objects.filter(
- member=request.user,
- workspace__slug=slug,
- is_active=True,
- role=5,
+ member=request.user, workspace__slug=slug, is_active=True, role=5
).exists():
projects = projects.filter(
project_projectmember__member=self.request.user,
@@ -171,10 +145,7 @@ class ProjectViewSet(BaseViewSet):
)
if WorkspaceMember.objects.filter(
- member=request.user,
- workspace__slug=slug,
- is_active=True,
- role=15,
+ member=request.user, workspace__slug=slug, is_active=True, role=15
).exists():
projects = projects.filter(
Q(
@@ -184,9 +155,7 @@ class ProjectViewSet(BaseViewSet):
| Q(network=2)
)
- if request.GET.get("per_page", False) and request.GET.get(
- "cursor", False
- ):
+ if request.GET.get("per_page", False) and request.GET.get("cursor", False):
return self.paginate(
order_by=request.GET.get("order_by", "-created_at"),
request=request,
@@ -202,8 +171,7 @@ class ProjectViewSet(BaseViewSet):
return Response(projects, status=status.HTTP_200_OK)
@allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST],
- level="WORKSPACE",
+ allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE"
)
def retrieve(self, request, slug, pk):
project = (
@@ -212,7 +180,7 @@ class ProjectViewSet(BaseViewSet):
.filter(pk=pk)
.annotate(
total_issues=Issue.issue_objects.filter(
- project_id=self.kwargs.get("pk"),
+ project_id=self.kwargs.get("pk")
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
@@ -220,8 +188,7 @@ class ProjectViewSet(BaseViewSet):
)
.annotate(
sub_issues=Issue.issue_objects.filter(
- project_id=self.kwargs.get("pk"),
- parent__isnull=False,
+ project_id=self.kwargs.get("pk"), parent__isnull=False
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
@@ -229,8 +196,7 @@ class ProjectViewSet(BaseViewSet):
)
.annotate(
archived_issues=Issue.objects.filter(
- project_id=self.kwargs.get("pk"),
- archived_at__isnull=False,
+ project_id=self.kwargs.get("pk"), archived_at__isnull=False
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
@@ -248,8 +214,7 @@ class ProjectViewSet(BaseViewSet):
)
.annotate(
draft_issues=Issue.objects.filter(
- project_id=self.kwargs.get("pk"),
- is_draft=True,
+ project_id=self.kwargs.get("pk"), is_draft=True
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
@@ -269,8 +234,7 @@ class ProjectViewSet(BaseViewSet):
if project is None:
return Response(
- {"error": "Project does not exist"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Project does not exist"}, status=status.HTTP_404_NOT_FOUND
)
recent_visited_task.delay(
@@ -297,14 +261,11 @@ class ProjectViewSet(BaseViewSet):
# Add the user as Administrator to the project
_ = ProjectMember.objects.create(
- project_id=serializer.data["id"],
- member=request.user,
- role=20,
+ project_id=serializer.data["id"], member=request.user, role=20
)
# Also create the issue property for the user
_ = IssueUserProperty.objects.create(
- project_id=serializer.data["id"],
- user=request.user,
+ project_id=serializer.data["id"], user=request.user
)
if serializer.data["project_lead"] is not None and str(
@@ -372,11 +333,7 @@ class ProjectViewSet(BaseViewSet):
]
)
- project = (
- self.get_queryset()
- .filter(pk=serializer.data["id"])
- .first()
- )
+ project = self.get_queryset().filter(pk=serializer.data["id"]).first()
# Create the model activity
model_activity.delay(
@@ -390,13 +347,8 @@ class ProjectViewSet(BaseViewSet):
)
serializer = ProjectListSerializer(project)
- return Response(
- serializer.data, status=status.HTTP_201_CREATED
- )
- return Response(
- serializer.errors,
- status=status.HTTP_400_BAD_REQUEST,
- )
+ 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(
@@ -405,8 +357,7 @@ class ProjectViewSet(BaseViewSet):
)
except Workspace.DoesNotExist:
return Response(
- {"error": "Workspace does not exist"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Workspace does not exist"}, status=status.HTTP_404_NOT_FOUND
)
except serializers.ValidationError:
return Response(
@@ -445,10 +396,7 @@ class ProjectViewSet(BaseViewSet):
serializer = ProjectSerializer(
project,
- data={
- **request.data,
- "intake_view": intake_view,
- },
+ data={**request.data, "intake_view": intake_view},
context={"workspace_id": workspace.id},
partial=True,
)
@@ -457,8 +405,7 @@ class ProjectViewSet(BaseViewSet):
serializer.save()
if intake_view:
intake = Intake.objects.filter(
- project=project,
- is_default=True,
+ project=project, is_default=True
).first()
if not intake:
Intake.objects.create(
@@ -477,11 +424,7 @@ class ProjectViewSet(BaseViewSet):
is_triage=True,
)
- project = (
- self.get_queryset()
- .filter(pk=serializer.data["id"])
- .first()
- )
+ project = self.get_queryset().filter(pk=serializer.data["id"]).first()
model_activity.delay(
model_name="project",
@@ -494,9 +437,7 @@ class ProjectViewSet(BaseViewSet):
)
serializer = ProjectListSerializer(project)
return Response(serializer.data, status=status.HTTP_200_OK)
- return Response(
- serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except IntegrityError as e:
if "already exists" in str(e):
@@ -506,8 +447,7 @@ class ProjectViewSet(BaseViewSet):
)
except (Project.DoesNotExist, Workspace.DoesNotExist):
return Response(
- {"error": "Project does not exist"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Project does not exist"}, status=status.HTTP_404_NOT_FOUND
)
except serializers.ValidationError:
return Response(
@@ -518,10 +458,7 @@ class ProjectViewSet(BaseViewSet):
def destroy(self, request, slug, pk):
if (
WorkspaceMember.objects.filter(
- member=request.user,
- workspace__slug=slug,
- is_active=True,
- role=20,
+ member=request.user, workspace__slug=slug, is_active=True, role=20
).exists()
or ProjectMember.objects.filter(
member=request.user,
@@ -535,16 +472,10 @@ class ProjectViewSet(BaseViewSet):
project.delete()
# Delete the project members
- DeployBoard.objects.filter(
- project_id=pk,
- workspace__slug=slug,
- ).delete()
+ DeployBoard.objects.filter(project_id=pk, workspace__slug=slug).delete()
# Delete the user favorite
- UserFavorite.objects.filter(
- project_id=pk,
- workspace__slug=slug,
- ).delete()
+ UserFavorite.objects.filter(project_id=pk, workspace__slug=slug).delete()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
@@ -555,19 +486,14 @@ class ProjectViewSet(BaseViewSet):
class ProjectArchiveUnarchiveEndpoint(BaseAPIView):
-
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
def post(self, request, slug, project_id):
project = Project.objects.get(pk=project_id, workspace__slug=slug)
project.archived_at = timezone.now()
project.save()
- UserFavorite.objects.filter(
- workspace__slug=slug,
- project=project_id,
- ).delete()
+ UserFavorite.objects.filter(workspace__slug=slug, project=project_id).delete()
return Response(
- {"archived_at": str(project.archived_at)},
- status=status.HTTP_200_OK,
+ {"archived_at": str(project.archived_at)}, status=status.HTTP_200_OK
)
@allow_permission([ROLE.ADMIN, ROLE.MEMBER])
@@ -585,8 +511,7 @@ class ProjectIdentifierEndpoint(BaseAPIView):
if name == "":
return Response(
- {"error": "Name is required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Name is required"}, status=status.HTTP_400_BAD_REQUEST
)
exists = ProjectIdentifier.objects.filter(
@@ -594,8 +519,7 @@ class ProjectIdentifierEndpoint(BaseAPIView):
).values("id", "name", "project")
return Response(
- {"exists": len(exists), "identifiers": exists},
- status=status.HTTP_200_OK,
+ {"exists": len(exists), "identifiers": exists}, status=status.HTTP_200_OK
)
@allow_permission([ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
@@ -604,27 +528,18 @@ class ProjectIdentifierEndpoint(BaseAPIView):
if name == "":
return Response(
- {"error": "Name is required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Name is required"}, status=status.HTTP_400_BAD_REQUEST
)
- if Project.objects.filter(
- identifier=name, workspace__slug=slug
- ).exists():
+ if Project.objects.filter(identifier=name, workspace__slug=slug).exists():
return Response(
- {
- "error": "Cannot delete an identifier of an existing project"
- },
+ {"error": "Cannot delete an identifier of an existing project"},
status=status.HTTP_400_BAD_REQUEST,
)
- ProjectIdentifier.objects.filter(
- name=name, workspace__slug=slug
- ).delete()
+ ProjectIdentifier.objects.filter(name=name, workspace__slug=slug).delete()
- return Response(
- status=status.HTTP_204_NO_CONTENT,
- )
+ return Response(status=status.HTTP_204_NO_CONTENT)
class ProjectUserViewsEndpoint(BaseAPIView):
@@ -632,15 +547,11 @@ class ProjectUserViewsEndpoint(BaseAPIView):
project = Project.objects.get(pk=project_id, workspace__slug=slug)
project_member = ProjectMember.objects.filter(
- member=request.user,
- project=project,
- is_active=True,
+ member=request.user, project=project, is_active=True
).first()
if project_member is None:
- return Response(
- {"error": "Forbidden"}, status=status.HTTP_403_FORBIDDEN
- )
+ return Response({"error": "Forbidden"}, status=status.HTTP_403_FORBIDDEN)
view_props = project_member.view_props
default_props = project_member.default_props
@@ -648,12 +559,8 @@ class ProjectUserViewsEndpoint(BaseAPIView):
sort_order = project_member.sort_order
project_member.view_props = request.data.get("view_props", view_props)
- project_member.default_props = request.data.get(
- "default_props", default_props
- )
- project_member.preferences = request.data.get(
- "preferences", preferences
- )
+ project_member.default_props = request.data.get("default_props", default_props)
+ project_member.preferences = request.data.get("preferences", preferences)
project_member.sort_order = request.data.get("sort_order", sort_order)
project_member.save()
@@ -701,9 +608,7 @@ class ProjectFavoritesViewSet(BaseViewSet):
class ProjectPublicCoverImagesEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
# Cache the below api for 24 hours
@cache_response(60 * 60 * 24, user=False)
@@ -746,17 +651,13 @@ class ProjectPublicCoverImagesEndpoint(BaseAPIView):
class DeployBoardViewSet(BaseViewSet):
- permission_classes = [
- ProjectMemberPermission,
- ]
+ permission_classes = [ProjectMemberPermission]
serializer_class = DeployBoardSerializer
model = DeployBoard
def list(self, request, slug, project_id):
project_deploy_board = DeployBoard.objects.filter(
- entity_name="project",
- entity_identifier=project_id,
- workspace__slug=slug,
+ entity_name="project", entity_identifier=project_id, workspace__slug=slug
).first()
serializer = DeployBoardSerializer(project_deploy_board)
@@ -779,9 +680,7 @@ class DeployBoardViewSet(BaseViewSet):
)
project_deploy_board, _ = DeployBoard.objects.get_or_create(
- entity_name="project",
- entity_identifier=project_id,
- project_id=project_id,
+ entity_name="project", entity_identifier=project_id, project_id=project_id
)
project_deploy_board.intake = intake
project_deploy_board.view_props = views
diff --git a/apiserver/plane/app/views/project/invite.py b/apiserver/plane/app/views/project/invite.py
index b48602cec..af8c6084b 100644
--- a/apiserver/plane/app/views/project/invite.py
+++ b/apiserver/plane/app/views/project/invite.py
@@ -52,24 +52,19 @@ class ProjectInvitationsViewset(BaseViewSet):
# Check if email is provided
if not emails:
return Response(
- {"error": "Emails are required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Emails are required"}, status=status.HTTP_400_BAD_REQUEST
)
for email in emails:
workspace_role = WorkspaceMember.objects.filter(
- workspace__slug=slug,
- member__email=email.get("email"),
- is_active=True,
+ workspace__slug=slug, member__email=email.get("email"), is_active=True
).role
- if workspace_role in [5, 20] and workspace_role != email.get(
- "role", 5
- ):
+ if workspace_role in [5, 20] and workspace_role != email.get("role", 5):
return Response(
{
"error": "You cannot invite a user with different role than workspace role"
- },
+ }
)
workspace = Workspace.objects.get(slug=slug)
@@ -84,10 +79,7 @@ class ProjectInvitationsViewset(BaseViewSet):
project_id=project_id,
workspace_id=workspace.id,
token=jwt.encode(
- {
- "email": email,
- "timestamp": datetime.now().timestamp(),
- },
+ {"email": email, "timestamp": datetime.now().timestamp()},
settings.SECRET_KEY,
algorithm="HS256",
),
@@ -120,10 +112,7 @@ class ProjectInvitationsViewset(BaseViewSet):
)
return Response(
- {
- "message": "Email sent successfully",
- },
- status=status.HTTP_200_OK,
+ {"message": "Email sent successfully"}, status=status.HTTP_200_OK
)
@@ -144,9 +133,7 @@ class UserProjectInvitationsViewset(BaseViewSet):
# Get the workspace user role
workspace_member = WorkspaceMember.objects.get(
- member=request.user,
- workspace__slug=slug,
- is_active=True,
+ member=request.user, workspace__slug=slug, is_active=True
)
workspace_role = workspace_member.role
@@ -154,9 +141,7 @@ class UserProjectInvitationsViewset(BaseViewSet):
# If the user was already part of workspace
_ = ProjectMember.objects.filter(
- workspace__slug=slug,
- project_id__in=project_ids,
- member=request.user,
+ workspace__slug=slug, project_id__in=project_ids, member=request.user
).update(is_active=True)
ProjectMember.objects.bulk_create(
@@ -187,21 +172,16 @@ class UserProjectInvitationsViewset(BaseViewSet):
)
return Response(
- {"message": "Projects joined successfully"},
- status=status.HTTP_201_CREATED,
+ {"message": "Projects joined successfully"}, status=status.HTTP_201_CREATED
)
class ProjectJoinEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def post(self, request, slug, project_id, pk):
project_invite = ProjectMemberInvite.objects.get(
- pk=pk,
- project_id=project_id,
- workspace__slug=slug,
+ pk=pk, project_id=project_id, workspace__slug=slug
)
email = request.data.get("email", "")
@@ -230,11 +210,7 @@ class ProjectJoinEndpoint(BaseAPIView):
_ = WorkspaceMember.objects.create(
workspace_id=project_invite.workspace_id,
member=user,
- role=(
- 15
- if project_invite.role >= 15
- else project_invite.role
- ),
+ role=(15 if project_invite.role >= 15 else project_invite.role),
)
else:
# Else make him active
diff --git a/apiserver/plane/app/views/project/member.py b/apiserver/plane/app/views/project/member.py
index ccb5e7521..f46bf6c50 100644
--- a/apiserver/plane/app/views/project/member.py
+++ b/apiserver/plane/app/views/project/member.py
@@ -36,20 +36,13 @@ class ProjectMemberViewSet(BaseViewSet):
def get_permissions(self):
if self.action == "leave":
- self.permission_classes = [
- ProjectLitePermission,
- ]
+ self.permission_classes = [ProjectLitePermission]
else:
- self.permission_classes = [
- ProjectMemberPermission,
- ]
+ self.permission_classes = [ProjectMemberPermission]
return super(ProjectMemberViewSet, self).get_permissions()
- search_fields = [
- "member__display_name",
- "member__first_name",
- ]
+ search_fields = ["member__display_name", "member__first_name"]
def get_queryset(self):
return self.filter_queryset(
@@ -91,14 +84,9 @@ class ProjectMemberViewSet(BaseViewSet):
# check the workspace role of the new user
for member in member_roles:
workspace_member_role = WorkspaceMember.objects.get(
- workspace__slug=slug,
- member=member,
- is_active=True,
+ workspace__slug=slug, member=member, is_active=True
).role
- if workspace_member_role in [20] and member_roles.get(member) in [
- 5,
- 15,
- ]:
+ if workspace_member_role in [20] and member_roles.get(member) in [5, 15]:
return Response(
{
"error": "You cannot add a user with role lower than the workspace role"
@@ -106,10 +94,7 @@ class ProjectMemberViewSet(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST,
)
- if workspace_member_role in [5] and member_roles.get(member) in [
- 15,
- 20,
- ]:
+ if workspace_member_role in [5] and member_roles.get(member) in [15, 20]:
return Response(
{
"error": "You cannot add a user with role higher than the workspace role"
@@ -143,13 +128,11 @@ class ProjectMemberViewSet(BaseViewSet):
# Loop through requested members
for member in members:
-
# Get the sort orders of the member
sort_order = [
project_member.get("sort_order")
for project_member in project_members
- if str(project_member.get("member_id"))
- == str(member.get("member_id"))
+ if str(project_member.get("member_id")) == str(member.get("member_id"))
]
# Create a new project member
bulk_project_members.append(
@@ -158,9 +141,7 @@ class ProjectMemberViewSet(BaseViewSet):
role=member.get("role", 5),
project_id=project_id,
workspace_id=project.workspace_id,
- sort_order=(
- sort_order[0] - 10000 if len(sort_order) else 65535
- ),
+ sort_order=(sort_order[0] - 10000 if len(sort_order) else 65535),
)
)
# Create a new issue property
@@ -174,9 +155,7 @@ class ProjectMemberViewSet(BaseViewSet):
# Bulk create the project members and issue properties
project_members = ProjectMember.objects.bulk_create(
- bulk_project_members,
- batch_size=10,
- ignore_conflicts=True,
+ bulk_project_members, batch_size=10, ignore_conflicts=True
)
_ = IssueUserProperty.objects.bulk_create(
@@ -219,10 +198,7 @@ class ProjectMemberViewSet(BaseViewSet):
@allow_permission([ROLE.ADMIN])
def partial_update(self, request, slug, project_id, pk):
project_member = ProjectMember.objects.get(
- pk=pk,
- workspace__slug=slug,
- project_id=project_id,
- is_active=True,
+ pk=pk, workspace__slug=slug, project_id=project_id, is_active=True
)
if request.user.id == project_member.member_id:
return Response(
@@ -238,9 +214,7 @@ class ProjectMemberViewSet(BaseViewSet):
)
workspace_role = WorkspaceMember.objects.get(
- workspace__slug=slug,
- member=project_member.member,
- is_active=True,
+ workspace__slug=slug, member=project_member.member, is_active=True
).role
if workspace_role in [5] and int(
request.data.get("role", project_member.role)
@@ -258,9 +232,7 @@ class ProjectMemberViewSet(BaseViewSet):
> requested_project_member.role
):
return Response(
- {
- "error": "You cannot update a role that is higher than your own role"
- },
+ {"error": "You cannot update a role that is higher than your own role"},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -300,9 +272,7 @@ class ProjectMemberViewSet(BaseViewSet):
# User cannot deactivate higher role
if requesting_project_member.role < project_member.role:
return Response(
- {
- "error": "You cannot remove a user having role higher than you"
- },
+ {"error": "You cannot remove a user having role higher than you"},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -323,16 +293,13 @@ class ProjectMemberViewSet(BaseViewSet):
if (
project_member.role == 20
and not ProjectMember.objects.filter(
- workspace__slug=slug,
- project_id=project_id,
- role=20,
- is_active=True,
+ workspace__slug=slug, project_id=project_id, role=20, is_active=True
).count()
> 1
):
return Response(
{
- "error": "You cannot leave the project as your the only admin of the project you will have to either delete the project or create an another admin",
+ "error": "You cannot leave the project as your the only admin of the project you will have to either delete the project or create an another admin"
},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -343,9 +310,7 @@ class ProjectMemberViewSet(BaseViewSet):
class AddTeamToProjectEndpoint(BaseAPIView):
- permission_classes = [
- ProjectBasePermission,
- ]
+ permission_classes = [ProjectBasePermission]
def post(self, request, slug, project_id):
team_members = TeamMember.objects.filter(
@@ -354,8 +319,7 @@ class AddTeamToProjectEndpoint(BaseAPIView):
if len(team_members) == 0:
return Response(
- {"error": "No such team exists"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "No such team exists"}, status=status.HTTP_400_BAD_REQUEST
)
workspace = Workspace.objects.get(slug=slug)
@@ -406,19 +370,14 @@ class ProjectMemberUserEndpoint(BaseAPIView):
class UserProjectRolesEndpoint(BaseAPIView):
- permission_classes = [
- WorkspaceUserPermission,
- ]
+ permission_classes = [WorkspaceUserPermission]
def get(self, request, slug):
project_members = ProjectMember.objects.filter(
- workspace__slug=slug,
- member_id=request.user.id,
- is_active=True,
+ workspace__slug=slug, member_id=request.user.id, is_active=True
).values("project_id", "role")
project_members = {
- str(member["project_id"]): member["role"]
- for member in project_members
+ str(member["project_id"]): member["role"] for member in project_members
}
return Response(project_members, status=status.HTTP_200_OK)
diff --git a/apiserver/plane/app/views/search/base.py b/apiserver/plane/app/views/search/base.py
index 714ccacc6..5161103f5 100644
--- a/apiserver/plane/app/views/search/base.py
+++ b/apiserver/plane/app/views/search/base.py
@@ -36,9 +36,7 @@ class GlobalSearchEndpoint(BaseAPIView):
for field in fields:
q |= Q(**{f"{field}__icontains": query})
return (
- Workspace.objects.filter(
- q, workspace_member__member=self.request.user
- )
+ Workspace.objects.filter(q, workspace_member__member=self.request.user)
.distinct()
.values("name", "id", "slug")
)
@@ -110,11 +108,7 @@ class GlobalSearchEndpoint(BaseAPIView):
cycles = cycles.filter(project_id=project_id)
return cycles.distinct().values(
- "name",
- "id",
- "project_id",
- "project__identifier",
- "workspace__slug",
+ "name", "id", "project_id", "project__identifier", "workspace__slug"
)
def filter_modules(self, query, slug, project_id, workspace_search):
@@ -135,11 +129,7 @@ class GlobalSearchEndpoint(BaseAPIView):
modules = modules.filter(project_id=project_id)
return modules.distinct().values(
- "name",
- "id",
- "project_id",
- "project__identifier",
- "workspace__slug",
+ "name", "id", "project_id", "project__identifier", "workspace__slug"
)
def filter_pages(self, query, slug, project_id, workspace_search):
@@ -159,12 +149,10 @@ class GlobalSearchEndpoint(BaseAPIView):
.annotate(
project_ids=Coalesce(
ArrayAgg(
- "projects__id",
- distinct=True,
- filter=~Q(projects__id=True),
+ "projects__id", distinct=True, filter=~Q(projects__id=True)
),
Value([], output_field=ArrayField(UUIDField())),
- ),
+ )
)
.annotate(
project_identifiers=Coalesce(
@@ -174,26 +162,21 @@ class GlobalSearchEndpoint(BaseAPIView):
filter=~Q(projects__id=True),
),
Value([], output_field=ArrayField(CharField())),
- ),
+ )
)
)
if workspace_search == "false" and project_id:
project_subquery = ProjectPage.objects.filter(
- page_id=OuterRef("id"),
- project_id=project_id,
+ page_id=OuterRef("id"), project_id=project_id
).values_list("project_id", flat=True)[:1]
- pages = pages.annotate(
- project_id=Subquery(project_subquery)
- ).filter(project_id=project_id)
+ pages = pages.annotate(project_id=Subquery(project_subquery)).filter(
+ project_id=project_id
+ )
return pages.distinct().values(
- "name",
- "id",
- "project_ids",
- "project_identifiers",
- "workspace__slug",
+ "name", "id", "project_ids", "project_identifiers", "workspace__slug"
)
def filter_views(self, query, slug, project_id, workspace_search):
@@ -214,18 +197,12 @@ class GlobalSearchEndpoint(BaseAPIView):
issue_views = issue_views.filter(project_id=project_id)
return issue_views.distinct().values(
- "name",
- "id",
- "project_id",
- "project__identifier",
- "workspace__slug",
+ "name", "id", "project_id", "project__identifier", "workspace__slug"
)
def get(self, request, slug):
query = request.query_params.get("search", False)
- workspace_search = request.query_params.get(
- "workspace_search", "false"
- )
+ workspace_search = request.query_params.get("workspace_search", "false")
project_id = request.query_params.get("project_id", False)
if not query:
diff --git a/apiserver/plane/app/views/search/issue.py b/apiserver/plane/app/views/search/issue.py
index 4ae5b5ea1..13fdc4eff 100644
--- a/apiserver/plane/app/views/search/issue.py
+++ b/apiserver/plane/app/views/search/issue.py
@@ -16,9 +16,7 @@ from plane.utils.issue_search import search_issues
class IssueSearchEndpoint(BaseAPIView):
def get(self, request, slug, project_id):
query = request.query_params.get("search", False)
- workspace_search = request.query_params.get(
- "workspace_search", "false"
- )
+ workspace_search = request.query_params.get("workspace_search", "false")
parent = request.query_params.get("parent", "false")
issue_relation = request.query_params.get("issue_relation", "false")
cycle = request.query_params.get("cycle", "false")
@@ -45,9 +43,7 @@ class IssueSearchEndpoint(BaseAPIView):
issue = Issue.issue_objects.filter(pk=issue_id).first()
if issue:
issues = issues.filter(
- ~Q(pk=issue_id),
- ~Q(pk=issue.parent_id),
- ~Q(parent_id=issue_id),
+ ~Q(pk=issue_id), ~Q(pk=issue.parent_id), ~Q(parent_id=issue_id)
)
if issue_relation == "true" and issue_id:
issue = Issue.issue_objects.filter(pk=issue_id).first()
@@ -72,8 +68,7 @@ class IssueSearchEndpoint(BaseAPIView):
if cycle == "true":
issues = issues.exclude(
- Q(issue_cycle__isnull=False)
- & Q(issue_cycle__deleted_at__isnull=True)
+ Q(issue_cycle__isnull=False) & Q(issue_cycle__deleted_at__isnull=True)
)
if module:
@@ -86,10 +81,7 @@ class IssueSearchEndpoint(BaseAPIView):
issues = issues.filter(target_date__isnull=True)
if ProjectMember.objects.filter(
- project_id=project_id,
- member=self.request.user,
- is_active=True,
- role=5,
+ project_id=project_id, member=self.request.user, is_active=True, role=5
).exists():
issues = issues.filter(created_by=self.request.user)
diff --git a/apiserver/plane/app/views/state/base.py b/apiserver/plane/app/views/state/base.py
index fd94a8dae..00f4813e6 100644
--- a/apiserver/plane/app/views/state/base.py
+++ b/apiserver/plane/app/views/state/base.py
@@ -8,10 +8,7 @@ from rest_framework import status
# Module imports
from .. import BaseViewSet
from plane.app.serializers import StateSerializer
-from plane.app.permissions import (
- ROLE,
- allow_permission
-)
+from plane.app.permissions import ROLE, allow_permission
from plane.db.models import State, Issue
from plane.utils.cache import invalidate_cache
@@ -37,9 +34,7 @@ class StateViewSet(BaseViewSet):
.distinct()
)
- @invalidate_cache(
- path="workspaces/:slug/states/", url_params=True, user=False
- )
+ @invalidate_cache(path="workspaces/:slug/states/", url_params=True, user=False)
@allow_permission([ROLE.ADMIN])
def create(self, request, slug, project_id):
serializer = StateSerializer(data=request.data)
@@ -62,9 +57,7 @@ class StateViewSet(BaseViewSet):
return Response(state_dict, status=status.HTTP_200_OK)
return Response(states, status=status.HTTP_200_OK)
- @invalidate_cache(
- path="workspaces/:slug/states/", url_params=True, user=False
- )
+ @invalidate_cache(path="workspaces/:slug/states/", url_params=True, user=False)
@allow_permission([ROLE.ADMIN])
def mark_as_default(self, request, slug, project_id, pk):
# Select all the states which are marked as default
@@ -76,16 +69,11 @@ class StateViewSet(BaseViewSet):
).update(default=True)
return Response(status=status.HTTP_204_NO_CONTENT)
- @invalidate_cache(
- path="workspaces/:slug/states/", url_params=True, user=False
- )
+ @invalidate_cache(path="workspaces/:slug/states/", url_params=True, user=False)
@allow_permission([ROLE.ADMIN])
def destroy(self, request, slug, project_id, pk):
state = State.objects.get(
- is_triage=False,
- pk=pk,
- project_id=project_id,
- workspace__slug=slug,
+ is_triage=False, pk=pk, project_id=project_id, workspace__slug=slug
)
if state.default:
@@ -99,9 +87,7 @@ class StateViewSet(BaseViewSet):
if issue_exist:
return Response(
- {
- "error": "The state is not empty, only empty states can be deleted"
- },
+ {"error": "The state is not empty, only empty states can be deleted"},
status=status.HTTP_400_BAD_REQUEST,
)
diff --git a/apiserver/plane/app/views/user/base.py b/apiserver/plane/app/views/user/base.py
index 5c036929c..4eca872f3 100644
--- a/apiserver/plane/app/views/user/base.py
+++ b/apiserver/plane/app/views/user/base.py
@@ -52,10 +52,7 @@ class UserEndpoint(BaseViewSet):
@method_decorator(vary_on_cookie)
def retrieve(self, request):
serialized_data = UserMeSerializer(request.user).data
- return Response(
- serialized_data,
- status=status.HTTP_200_OK,
- )
+ return Response(serialized_data, status=status.HTTP_200_OK)
@method_decorator(cache_control(private=True, max_age=12))
@method_decorator(vary_on_cookie)
@@ -68,9 +65,7 @@ class UserEndpoint(BaseViewSet):
is_admin = InstanceAdmin.objects.filter(
instance=instance, user=request.user
).exists()
- return Response(
- {"is_instance_admin": is_admin}, status=status.HTTP_200_OK
- )
+ return Response({"is_instance_admin": is_admin}, status=status.HTTP_200_OK)
def partial_update(self, request, *args, **kwargs):
return super().partial_update(request, *args, **kwargs)
@@ -96,10 +91,7 @@ class UserEndpoint(BaseViewSet):
).annotate(
other_admin_exists=Count(
Case(
- When(
- Q(role=20, is_active=True) & ~Q(member=request.user),
- then=1,
- ),
+ When(Q(role=20, is_active=True) & ~Q(member=request.user), then=1),
default=0,
output_field=IntegerField(),
)
@@ -124,10 +116,7 @@ class UserEndpoint(BaseViewSet):
).annotate(
other_admin_exists=Count(
Case(
- When(
- Q(role=20, is_active=True) & ~Q(member=request.user),
- then=1,
- ),
+ When(Q(role=20, is_active=True) & ~Q(member=request.user), then=1),
default=0,
output_field=IntegerField(),
)
@@ -136,9 +125,7 @@ class UserEndpoint(BaseViewSet):
)
for workspace in workspaces:
- if workspace.other_admin_exists > 0 or (
- workspace.total_members == 1
- ):
+ if workspace.other_admin_exists > 0 or (workspace.total_members == 1):
workspace.is_active = False
workspaces_to_deactivate.append(workspace)
else:
@@ -158,9 +145,7 @@ class UserEndpoint(BaseViewSet):
)
# Delete all workspace invites
- WorkspaceMemberInvite.objects.filter(
- email=user.email,
- ).delete()
+ WorkspaceMemberInvite.objects.filter(email=user.email).delete()
# Delete all sessions
Session.objects.filter(user_id=request.user.id).delete()
@@ -191,9 +176,7 @@ class UserEndpoint(BaseViewSet):
user.save()
# Send an email to the user
- user_deactivation_email.delay(
- base_host(request=request, is_app=True), user.id
- )
+ user_deactivation_email.delay(base_host(request=request, is_app=True), user.id)
# Logout the user
logout(request)
@@ -201,10 +184,7 @@ class UserEndpoint(BaseViewSet):
class UserSessionEndpoint(BaseAPIView):
-
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request):
if request.user.is_authenticated:
@@ -214,41 +194,30 @@ class UserSessionEndpoint(BaseAPIView):
data["user"] = serializer.data
return Response(data, status=status.HTTP_200_OK)
else:
- return Response(
- {"is_authenticated": False}, status=status.HTTP_200_OK
- )
+ return Response({"is_authenticated": False}, status=status.HTTP_200_OK)
class UpdateUserOnBoardedEndpoint(BaseAPIView):
-
def patch(self, request):
profile = Profile.objects.get(user_id=request.user.id)
profile.is_onboarded = request.data.get("is_onboarded", False)
profile.save()
- return Response(
- {"message": "Updated successfully"}, status=status.HTTP_200_OK
- )
+ return Response({"message": "Updated successfully"}, status=status.HTTP_200_OK)
class UpdateUserTourCompletedEndpoint(BaseAPIView):
-
def patch(self, request):
profile = Profile.objects.get(user_id=request.user.id)
- profile.is_tour_completed = request.data.get(
- "is_tour_completed", False
- )
+ profile.is_tour_completed = request.data.get("is_tour_completed", False)
profile.save()
- return Response(
- {"message": "Updated successfully"}, status=status.HTTP_200_OK
- )
+ return Response({"message": "Updated successfully"}, status=status.HTTP_200_OK)
class UserActivityEndpoint(BaseAPIView, BasePaginator):
-
def get(self, request):
- queryset = IssueActivity.objects.filter(
- actor=request.user
- ).select_related("actor", "workspace", "issue", "project")
+ queryset = IssueActivity.objects.filter(actor=request.user).select_related(
+ "actor", "workspace", "issue", "project"
+ )
return self.paginate(
order_by=request.GET.get("order_by", "-created_at"),
@@ -261,7 +230,6 @@ class UserActivityEndpoint(BaseAPIView, BasePaginator):
class AccountEndpoint(BaseAPIView):
-
def get(self, request, pk=None):
if pk:
account = Account.objects.get(pk=pk, user=request.user)
@@ -270,10 +238,7 @@ class AccountEndpoint(BaseAPIView):
account = Account.objects.filter(user=request.user)
serializer = AccountSerializer(account, many=True)
- return Response(
- serializer.data,
- status=status.HTTP_200_OK,
- )
+ return Response(serializer.data, status=status.HTTP_200_OK)
def delete(self, request, pk):
account = Account.objects.get(pk=pk, user=request.user)
@@ -291,9 +256,7 @@ class ProfileEndpoint(BaseAPIView):
def patch(self, request):
profile = Profile.objects.get(user=request.user)
- serializer = ProfileSerializer(
- profile, data=request.data, partial=True
- )
+ serializer = ProfileSerializer(profile, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
diff --git a/apiserver/plane/app/views/view/base.py b/apiserver/plane/app/views/view/base.py
index 53c962e70..ca4048b70 100644
--- a/apiserver/plane/app/views/view/base.py
+++ b/apiserver/plane/app/views/view/base.py
@@ -1,16 +1,7 @@
# Django imports
from django.contrib.postgres.aggregates import ArrayAgg
from django.contrib.postgres.fields import ArrayField
-from django.db.models import (
- Exists,
- F,
- Func,
- OuterRef,
- Q,
- UUIDField,
- Value,
- Subquery,
-)
+from django.db.models import Exists, F, Func, OuterRef, Q, UUIDField, Value, Subquery
from django.db.models.functions import Coalesce
from django.utils.decorators import method_decorator
from django.views.decorators.gzip import gzip_page
@@ -21,13 +12,8 @@ from rest_framework import status
from rest_framework.response import Response
# Module imports
-from plane.app.permissions import (
- allow_permission,
- ROLE,
-)
-from plane.app.serializers import (
- IssueViewSerializer,
-)
+from plane.app.permissions import allow_permission, ROLE
+from plane.app.serializers import IssueViewSerializer
from plane.db.models import (
Issue,
FileAsset,
@@ -46,15 +32,10 @@ from plane.utils.grouper import (
)
from plane.utils.issue_filters import issue_filters
from plane.utils.order_queryset import order_issue_queryset
-from plane.utils.paginator import (
- GroupedOffsetPaginator,
- SubGroupedOffsetPaginator,
-)
+from plane.utils.paginator import GroupedOffsetPaginator, SubGroupedOffsetPaginator
from plane.bgtasks.recent_visited_task import recent_visited_task
from .. import BaseViewSet
-from plane.db.models import (
- UserFavorite,
-)
+from plane.db.models import UserFavorite
class WorkspaceViewViewSet(BaseViewSet):
@@ -78,21 +59,13 @@ class WorkspaceViewViewSet(BaseViewSet):
)
@allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST],
- level="WORKSPACE",
+ allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE"
)
def list(self, request, slug):
queryset = self.get_queryset()
- fields = [
- field
- for field in request.GET.get("fields", "").split(",")
- if field
- ]
+ fields = [field for field in request.GET.get("fields", "").split(",") if field]
if WorkspaceMember.objects.filter(
- workspace__slug=slug,
- member=request.user,
- role=5,
- is_active=True,
+ workspace__slug=slug, member=request.user, role=5, is_active=True
).exists():
queryset = queryset.filter(owned_by=request.user)
views = IssueViewSerializer(
@@ -106,22 +79,18 @@ class WorkspaceViewViewSet(BaseViewSet):
def partial_update(self, request, slug, pk):
with transaction.atomic():
workspace_view = IssueView.objects.select_for_update().get(
- pk=pk,
- workspace__slug=slug,
+ pk=pk, workspace__slug=slug
)
if workspace_view.is_locked:
return Response(
- {"error": "view is locked"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "view is locked"}, status=status.HTTP_400_BAD_REQUEST
)
# Only update the view if owner is updating
if workspace_view.owned_by_id != request.user.id:
return Response(
- {
- "error": "Only the owner of the view can update the view"
- },
+ {"error": "Only the owner of the view can update the view"},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -132,9 +101,7 @@ class WorkspaceViewViewSet(BaseViewSet):
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(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def retrieve(self, request, slug, pk):
issue_view = self.get_queryset().filter(pk=pk).first()
@@ -146,33 +113,18 @@ class WorkspaceViewViewSet(BaseViewSet):
entity_identifier=pk,
user_id=request.user.id,
)
- return Response(
- serializer.data,
- status=status.HTTP_200_OK,
- )
+ return Response(serializer.data, status=status.HTTP_200_OK)
@allow_permission(
- allowed_roles=[],
- level="WORKSPACE",
- creator=True,
- model=IssueView,
+ allowed_roles=[], level="WORKSPACE", creator=True, model=IssueView
)
def destroy(self, request, slug, pk):
- workspace_view = IssueView.objects.get(
- pk=pk,
- workspace__slug=slug,
- )
+ workspace_view = IssueView.objects.get(pk=pk, workspace__slug=slug)
workspace_member = WorkspaceMember.objects.filter(
- workspace__slug=slug,
- member=request.user,
- role=20,
- is_active=True,
+ workspace__slug=slug, member=request.user, role=20, is_active=True
)
- if (
- workspace_member.exists()
- or workspace_view.owned_by == request.user
- ):
+ if workspace_member.exists() or workspace_view.owned_by == request.user:
workspace_view.delete()
# Delete the user favorite view
UserFavorite.objects.filter(
@@ -193,9 +145,7 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
def get_queryset(self):
return (
Issue.issue_objects.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -230,9 +180,7 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -244,7 +192,7 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
distinct=True,
filter=Q(
~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ & Q(label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -278,8 +226,7 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
@method_decorator(gzip_page)
@allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST],
- level="WORKSPACE",
+ allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE"
)
def list(self, request, slug):
filters = issue_filters(request.query_params, "GET")
@@ -318,8 +265,7 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
# Issue queryset
issue_queryset, order_by_param = order_issue_queryset(
- issue_queryset=issue_queryset,
- order_by_param=order_by_param,
+ issue_queryset=issue_queryset, order_by_param=order_by_param
)
# Group by
@@ -328,9 +274,7 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
# issue queryset
issue_queryset = issue_queryset_grouper(
- queryset=issue_queryset,
- group_by=group_by,
- sub_group_by=sub_group_by,
+ queryset=issue_queryset, group_by=group_by, sub_group_by=sub_group_by
)
if group_by:
@@ -350,16 +294,11 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=SubGroupedOffsetPaginator,
group_by_fields=issue_group_values(
- field=group_by,
- slug=slug,
- project_id=None,
- filters=filters,
+ field=group_by, slug=slug, project_id=None, filters=filters
),
sub_group_by_fields=issue_group_values(
field=sub_group_by,
@@ -386,16 +325,11 @@ class WorkspaceViewIssuesViewSet(BaseViewSet):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=GroupedOffsetPaginator,
group_by_fields=issue_group_values(
- field=group_by,
- slug=slug,
- project_id=None,
- filters=filters,
+ field=group_by, slug=slug, project_id=None, filters=filters
),
group_by_field_name=group_by,
count_filter=Q(
@@ -425,8 +359,7 @@ class IssueViewViewSet(BaseViewSet):
def perform_create(self, serializer):
serializer.save(
- project_id=self.kwargs.get("project_id"),
- owned_by=self.request.user,
+ project_id=self.kwargs.get("project_id"), owned_by=self.request.user
)
def get_queryset(self):
@@ -470,11 +403,7 @@ class IssueViewViewSet(BaseViewSet):
and not project.guest_view_all_features
):
queryset = queryset.filter(owned_by=request.user)
- fields = [
- field
- for field in request.GET.get("fields", "").split(",")
- if field
- ]
+ fields = [field for field in request.GET.get("fields", "").split(",") if field]
views = IssueViewSerializer(
queryset, many=True, fields=fields if fields else None
).data
@@ -482,9 +411,7 @@ class IssueViewViewSet(BaseViewSet):
@allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
def retrieve(self, request, slug, project_id, pk):
- issue_view = (
- self.get_queryset().filter(pk=pk, project_id=project_id).first()
- )
+ issue_view = self.get_queryset().filter(pk=pk, project_id=project_id).first()
project = Project.objects.get(id=project_id)
"""
if the role is guest and guest_view_all_features is false and owned by is not
@@ -515,10 +442,7 @@ class IssueViewViewSet(BaseViewSet):
entity_identifier=pk,
user_id=request.user.id,
)
- return Response(
- serializer.data,
- status=status.HTTP_200_OK,
- )
+ return Response(serializer.data, status=status.HTTP_200_OK)
@allow_permission(allowed_roles=[], creator=True, model=IssueView)
def partial_update(self, request, slug, project_id, pk):
@@ -529,16 +453,13 @@ class IssueViewViewSet(BaseViewSet):
if issue_view.is_locked:
return Response(
- {"error": "view is locked"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "view is locked"}, status=status.HTTP_400_BAD_REQUEST
)
# Only update the view if owner is updating
if issue_view.owned_by_id != request.user.id:
return Response(
- {
- "error": "Only the owner of the view can update the view"
- },
+ {"error": "Only the owner of the view can update the view"},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -549,18 +470,12 @@ class IssueViewViewSet(BaseViewSet):
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(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
- @allow_permission(
- allowed_roles=[ROLE.ADMIN], creator=True, model=IssueView
- )
+ @allow_permission(allowed_roles=[ROLE.ADMIN], creator=True, model=IssueView)
def destroy(self, request, slug, project_id, pk):
project_view = IssueView.objects.get(
- pk=pk,
- project_id=project_id,
- workspace__slug=slug,
+ pk=pk, project_id=project_id, workspace__slug=slug
)
if (
ProjectMember.objects.filter(
diff --git a/apiserver/plane/app/views/webhook/base.py b/apiserver/plane/app/views/webhook/base.py
index 5581b6aa3..d62838fab 100644
--- a/apiserver/plane/app/views/webhook/base.py
+++ b/apiserver/plane/app/views/webhook/base.py
@@ -14,7 +14,6 @@ from plane.app.serializers import WebhookSerializer, WebhookLogSerializer
class WebhookEndpoint(BaseAPIView):
-
@allow_permission(allowed_roles=[ROLE.ADMIN], level="WORKSPACE")
def post(self, request, slug):
workspace = Workspace.objects.get(slug=slug)
@@ -24,12 +23,8 @@ class WebhookEndpoint(BaseAPIView):
)
if serializer.is_valid():
serializer.save(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(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(
@@ -112,7 +107,6 @@ class WebhookEndpoint(BaseAPIView):
class WebhookSecretRegenerateEndpoint(BaseAPIView):
-
@allow_permission(allowed_roles=[ROLE.ADMIN], level="WORKSPACE")
def post(self, request, slug, pk):
webhook = Webhook.objects.get(workspace__slug=slug, pk=pk)
@@ -123,7 +117,6 @@ class WebhookSecretRegenerateEndpoint(BaseAPIView):
class WebhookLogsEndpoint(BaseAPIView):
-
@allow_permission(allowed_roles=[ROLE.ADMIN], level="WORKSPACE")
def get(self, request, slug, webhook_id):
webhook_logs = WebhookLog.objects.filter(
diff --git a/apiserver/plane/app/views/workspace/base.py b/apiserver/plane/app/views/workspace/base.py
index bd552368a..6ffb643a9 100644
--- a/apiserver/plane/app/views/workspace/base.py
+++ b/apiserver/plane/app/views/workspace/base.py
@@ -5,14 +5,7 @@ from datetime import date
from dateutil.relativedelta import relativedelta
from django.db import IntegrityError
-from django.db.models import (
- Count,
- F,
- Func,
- OuterRef,
- Prefetch,
- Q,
-)
+from django.db.models import Count, F, Func, OuterRef, Prefetch, Q
from django.db.models.fields import DateField
from django.db.models.functions import Cast, ExtractDay, ExtractWeek
@@ -31,10 +24,7 @@ from plane.app.permissions import (
)
# Module imports
-from plane.app.serializers import (
- WorkSpaceSerializer,
- WorkspaceThemeSerializer,
-)
+from plane.app.serializers import WorkSpaceSerializer, WorkspaceThemeSerializer
from plane.app.views.base import BaseAPIView, BaseViewSet
from plane.db.models import (
Issue,
@@ -53,25 +43,17 @@ from plane.utils.constants import RESTRICTED_WORKSPACE_SLUGS
class WorkSpaceViewSet(BaseViewSet):
model = Workspace
serializer_class = WorkSpaceSerializer
- permission_classes = [
- WorkSpaceBasePermission,
- ]
+ permission_classes = [WorkSpaceBasePermission]
- search_fields = [
- "name",
- ]
- filterset_fields = [
- "owner",
- ]
+ search_fields = ["name"]
+ filterset_fields = ["owner"]
lookup_field = "slug"
def get_queryset(self):
member_count = (
WorkspaceMember.objects.filter(
- workspace=OuterRef("id"),
- member__is_bot=False,
- is_active=True,
+ workspace=OuterRef("id"), member__is_bot=False, is_active=True
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
@@ -85,9 +67,7 @@ class WorkSpaceViewSet(BaseViewSet):
.values("count")
)
return (
- self.filter_queryset(
- super().get_queryset().select_related("owner")
- )
+ self.filter_queryset(super().get_queryset().select_related("owner"))
.order_by("name")
.filter(
workspace_member__member=self.request.user,
@@ -113,9 +93,7 @@ class WorkSpaceViewSet(BaseViewSet):
if len(name) > 80 or len(slug) > 48:
return Response(
- {
- "error": "The maximum length for name is 80 and for slug is 48"
- },
+ {"error": "The maximum length for name is 80 and for slug is 48"},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -128,9 +106,7 @@ class WorkSpaceViewSet(BaseViewSet):
role=20,
company_role=request.data.get("company_role", ""),
)
- return Response(
- serializer.data, status=status.HTTP_201_CREATED
- )
+ return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(
[serializer.errors[error][0] for error in serializer.errors],
status=status.HTTP_400_BAD_REQUEST,
@@ -143,23 +119,11 @@ class WorkSpaceViewSet(BaseViewSet):
status=status.HTTP_410_GONE,
)
- @allow_permission(
- [
- ROLE.ADMIN,
- ROLE.MEMBER,
- ROLE.GUEST,
- ],
- level="WORKSPACE",
- )
+ @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE")
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)
- @allow_permission(
- [
- ROLE.ADMIN,
- ],
- level="WORKSPACE",
- )
+ @allow_permission([ROLE.ADMIN], level="WORKSPACE")
def partial_update(self, request, *args, **kwargs):
return super().partial_update(request, *args, **kwargs)
@@ -169,26 +133,16 @@ class WorkSpaceViewSet(BaseViewSet):
class UserWorkSpacesEndpoint(BaseAPIView):
- search_fields = [
- "name",
- ]
- filterset_fields = [
- "owner",
- ]
+ search_fields = ["name"]
+ filterset_fields = ["owner"]
@method_decorator(cache_control(private=True, max_age=12))
@method_decorator(vary_on_cookie)
def get(self, request):
- fields = [
- field
- for field in request.GET.get("fields", "").split(",")
- if field
- ]
+ fields = [field for field in request.GET.get("fields", "").split(",") if field]
member_count = (
WorkspaceMember.objects.filter(
- workspace=OuterRef("id"),
- member__is_bot=False,
- is_active=True,
+ workspace=OuterRef("id"), member__is_bot=False, is_active=True
)
.order_by()
.annotate(count=Func(F("id"), function="Count"))
@@ -215,8 +169,7 @@ class UserWorkSpacesEndpoint(BaseAPIView):
.annotate(total_members=member_count)
.annotate(total_issues=issue_count)
.filter(
- workspace_member__member=request.user,
- workspace_member__is_active=True,
+ workspace_member__member=request.user, workspace_member__is_active=True
)
.distinct()
)
@@ -291,15 +244,12 @@ class UserWorkspaceDashboardEndpoint(BaseAPIView):
).count()
completed_issues_count = Issue.issue_objects.filter(
- workspace__slug=slug,
- assignees__in=[request.user],
- state__group="completed",
+ workspace__slug=slug, assignees__in=[request.user], state__group="completed"
).count()
issues_due_week = (
Issue.issue_objects.filter(
- workspace__slug=slug,
- assignees__in=[request.user],
+ workspace__slug=slug, assignees__in=[request.user]
)
.annotate(target_week=ExtractWeek("target_date"))
.filter(target_week=timezone.now().date().isocalendar()[1])
@@ -349,18 +299,12 @@ class UserWorkspaceDashboardEndpoint(BaseAPIView):
class WorkspaceThemeViewSet(BaseViewSet):
- permission_classes = [
- WorkSpaceAdminPermission,
- ]
+ permission_classes = [WorkSpaceAdminPermission]
model = WorkspaceTheme
serializer_class = WorkspaceThemeSerializer
def get_queryset(self):
- return (
- super()
- .get_queryset()
- .filter(workspace__slug=self.kwargs.get("slug"))
- )
+ return super().get_queryset().filter(workspace__slug=self.kwargs.get("slug"))
def create(self, request, slug):
workspace = Workspace.objects.get(slug=slug)
@@ -372,9 +316,7 @@ class WorkspaceThemeViewSet(BaseViewSet):
class ExportWorkspaceUserActivityEndpoint(BaseAPIView):
- permission_classes = [
- WorkspaceEntityPermission,
- ]
+ permission_classes = [WorkspaceEntityPermission]
def generate_csv_from_rows(self, rows):
"""Generate CSV buffer from rows."""
@@ -385,11 +327,9 @@ class ExportWorkspaceUserActivityEndpoint(BaseAPIView):
return csv_buffer
def post(self, request, slug, user_id):
-
if not request.data.get("date"):
return Response(
- {"error": "Date is required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Date is required"}, status=status.HTTP_400_BAD_REQUEST
)
user_activities = IssueActivity.objects.filter(
diff --git a/apiserver/plane/app/views/workspace/cycle.py b/apiserver/plane/app/views/workspace/cycle.py
index 6040827ad..ec08f47c9 100644
--- a/apiserver/plane/app/views/workspace/cycle.py
+++ b/apiserver/plane/app/views/workspace/cycle.py
@@ -1,8 +1,5 @@
# Django imports
-from django.db.models import (
- Q,
- Count,
-)
+from django.db.models import Q, Count
# Third party modules
from rest_framework import status
@@ -16,9 +13,7 @@ from plane.app.serializers.cycle import CycleSerializer
class WorkspaceCyclesEndpoint(BaseAPIView):
- permission_classes = [
- WorkspaceViewerPermission,
- ]
+ permission_classes = [WorkspaceViewerPermission]
def get(self, request, slug):
cycles = (
diff --git a/apiserver/plane/app/views/workspace/draft.py b/apiserver/plane/app/views/workspace/draft.py
index b2cb529fc..fa161cbab 100644
--- a/apiserver/plane/app/views/workspace/draft.py
+++ b/apiserver/plane/app/views/workspace/draft.py
@@ -7,13 +7,7 @@ from django.core import serializers
from django.core.serializers.json import DjangoJSONEncoder
from django.contrib.postgres.aggregates import ArrayAgg
from django.contrib.postgres.fields import ArrayField
-from django.db.models import (
- Q,
- UUIDField,
- Value,
- Subquery,
- OuterRef,
-)
+from django.db.models import Q, UUIDField, Value, Subquery, OuterRef
from django.db.models.functions import Coalesce
from django.utils.decorators import method_decorator
from django.views.decorators.gzip import gzip_page
@@ -51,9 +45,7 @@ class WorkspaceDraftIssueViewSet(BaseViewSet):
return (
DraftIssue.objects.filter(workspace__slug=self.kwargs.get("slug"))
.select_related("workspace", "project", "state", "parent")
- .prefetch_related(
- "assignees", "labels", "draft_issue_module__module"
- )
+ .prefetch_related("assignees", "labels", "draft_issue_module__module")
.annotate(
cycle_id=Subquery(
DraftIssueCycle.objects.filter(
@@ -91,9 +83,7 @@ class WorkspaceDraftIssueViewSet(BaseViewSet):
distinct=True,
filter=Q(
~Q(draft_issue_module__module_id__isnull=True)
- & Q(
- draft_issue_module__module__archived_at__isnull=True
- )
+ & Q(draft_issue_module__module__archived_at__isnull=True)
& Q(draft_issue_module__deleted_at__isnull=True)
),
),
@@ -109,9 +99,7 @@ class WorkspaceDraftIssueViewSet(BaseViewSet):
def list(self, request, slug):
filters = issue_filters(request.query_params, "GET")
issues = (
- self.get_queryset()
- .filter(created_by=request.user)
- .order_by("-created_at")
+ self.get_queryset().filter(created_by=request.user).order_by("-created_at")
)
issues = issues.filter(**filters)
@@ -119,10 +107,7 @@ class WorkspaceDraftIssueViewSet(BaseViewSet):
return self.paginate(
request=request,
queryset=(issues),
- on_results=lambda issues: DraftIssueSerializer(
- issues,
- many=True,
- ).data,
+ on_results=lambda issues: DraftIssueSerializer(issues, many=True).data,
)
@allow_permission(
@@ -179,14 +164,11 @@ class WorkspaceDraftIssueViewSet(BaseViewSet):
level="WORKSPACE",
)
def partial_update(self, request, slug, pk):
- issue = (
- self.get_queryset().filter(pk=pk, created_by=request.user).first()
- )
+ issue = self.get_queryset().filter(pk=pk, created_by=request.user).first()
if not issue:
return Response(
- {"error": "Issue not found"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Issue not found"}, status=status.HTTP_404_NOT_FOUND
)
serializer = DraftIssueCreateSerializer(
@@ -206,15 +188,10 @@ class WorkspaceDraftIssueViewSet(BaseViewSet):
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@allow_permission(
- allowed_roles=[ROLE.ADMIN],
- creator=True,
- model=Issue,
- level="WORKSPACE",
+ allowed_roles=[ROLE.ADMIN], creator=True, model=Issue, level="WORKSPACE"
)
def retrieve(self, request, slug, pk=None):
- issue = (
- self.get_queryset().filter(pk=pk, created_by=request.user).first()
- )
+ issue = self.get_queryset().filter(pk=pk, created_by=request.user).first()
if not issue:
return Response(
@@ -226,20 +203,14 @@ class WorkspaceDraftIssueViewSet(BaseViewSet):
return Response(serializer.data, status=status.HTTP_200_OK)
@allow_permission(
- allowed_roles=[ROLE.ADMIN],
- creator=True,
- model=DraftIssue,
- level="WORKSPACE",
+ allowed_roles=[ROLE.ADMIN], creator=True, model=DraftIssue, level="WORKSPACE"
)
def destroy(self, request, slug, pk=None):
draft_issue = DraftIssue.objects.get(workspace__slug=slug, pk=pk)
draft_issue.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
- @allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER],
- level="WORKSPACE",
- )
+ @allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def create_draft_to_issue(self, request, slug, draft_id):
draft_issue = self.get_queryset().filter(pk=draft_id).first()
@@ -263,9 +234,7 @@ class WorkspaceDraftIssueViewSet(BaseViewSet):
issue_activity.delay(
type="issue.activity.created",
- requested_data=json.dumps(
- self.request.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(self.request.data, cls=DjangoJSONEncoder),
actor_id=str(request.user.id),
issue_id=str(serializer.data.get("id", None)),
project_id=str(draft_issue.project_id),
diff --git a/apiserver/plane/app/views/workspace/estimate.py b/apiserver/plane/app/views/workspace/estimate.py
index 59a23d867..beef2a8ec 100644
--- a/apiserver/plane/app/views/workspace/estimate.py
+++ b/apiserver/plane/app/views/workspace/estimate.py
@@ -11,9 +11,7 @@ from plane.utils.cache import cache_response
class WorkspaceEstimatesEndpoint(BaseAPIView):
- permission_classes = [
- WorkspaceEntityPermission,
- ]
+ permission_classes = [WorkspaceEntityPermission]
@cache_response(60 * 60 * 2)
def get(self, request, slug):
diff --git a/apiserver/plane/app/views/workspace/favorite.py b/apiserver/plane/app/views/workspace/favorite.py
index 25c76779c..38fa1bdef 100644
--- a/apiserver/plane/app/views/workspace/favorite.py
+++ b/apiserver/plane/app/views/workspace/favorite.py
@@ -13,16 +13,11 @@ from plane.app.permissions import allow_permission, ROLE
class WorkspaceFavoriteEndpoint(BaseAPIView):
-
- @allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE"
- )
+ @allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def get(self, request, slug):
# the second filter is to check if the user is a member of the project
favorites = UserFavorite.objects.filter(
- user=request.user,
- workspace__slug=slug,
- parent__isnull=True,
+ user=request.user, workspace__slug=slug, parent__isnull=True
).filter(
Q(project__isnull=True) & ~Q(entity_type="page")
| (
@@ -34,9 +29,7 @@ class WorkspaceFavoriteEndpoint(BaseAPIView):
serializer = UserFavoriteSerializer(favorites, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
- @allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE"
- )
+ @allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def post(self, request, slug):
workspace = Workspace.objects.get(slug=slug)
serializer = UserFavoriteSerializer(data=request.data)
@@ -49,24 +42,18 @@ class WorkspaceFavoriteEndpoint(BaseAPIView):
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
- @allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE"
- )
+ @allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def patch(self, request, slug, favorite_id):
favorite = UserFavorite.objects.get(
user=request.user, workspace__slug=slug, pk=favorite_id
)
- serializer = UserFavoriteSerializer(
- favorite, data=request.data, partial=True
- )
+ serializer = UserFavoriteSerializer(favorite, 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)
- @allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE"
- )
+ @allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def delete(self, request, slug, favorite_id):
favorite = UserFavorite.objects.get(
user=request.user, workspace__slug=slug, pk=favorite_id
@@ -76,15 +63,10 @@ class WorkspaceFavoriteEndpoint(BaseAPIView):
class WorkspaceFavoriteGroupEndpoint(BaseAPIView):
-
- @allow_permission(
- allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE"
- )
+ @allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
def get(self, request, slug, favorite_id):
favorites = UserFavorite.objects.filter(
- user=request.user,
- workspace__slug=slug,
- parent_id=favorite_id,
+ user=request.user, workspace__slug=slug, parent_id=favorite_id
).filter(
Q(project__isnull=True)
| (
diff --git a/apiserver/plane/app/views/workspace/invite.py b/apiserver/plane/app/views/workspace/invite.py
index 79b03d8a0..486a3c93b 100644
--- a/apiserver/plane/app/views/workspace/invite.py
+++ b/apiserver/plane/app/views/workspace/invite.py
@@ -24,12 +24,7 @@ from plane.app.serializers import (
from plane.app.views.base import BaseAPIView
from plane.bgtasks.event_tracking_task import workspace_invite_event
from plane.bgtasks.workspace_invitation_task import workspace_invitation
-from plane.db.models import (
- User,
- Workspace,
- WorkspaceMember,
- WorkspaceMemberInvite,
-)
+from plane.db.models import User, Workspace, WorkspaceMember, WorkspaceMemberInvite
from plane.utils.cache import invalidate_cache, invalidate_cache_directly
from .. import BaseViewSet
@@ -41,9 +36,7 @@ class WorkspaceInvitationsViewset(BaseViewSet):
serializer_class = WorkSpaceMemberInviteSerializer
model = WorkspaceMemberInvite
- permission_classes = [
- WorkSpaceAdminPermission,
- ]
+ permission_classes = [WorkSpaceAdminPermission]
def get_queryset(self):
return self.filter_queryset(
@@ -58,15 +51,12 @@ class WorkspaceInvitationsViewset(BaseViewSet):
# Check if email is provided
if not emails:
return Response(
- {"error": "Emails are required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Emails are required"}, status=status.HTTP_400_BAD_REQUEST
)
# check for role level of the requesting user
requesting_user = WorkspaceMember.objects.get(
- workspace__slug=slug,
- member=request.user,
- is_active=True,
+ workspace__slug=slug, member=request.user, is_active=True
)
# Check if any invited user has an higher role
@@ -112,10 +102,7 @@ class WorkspaceInvitationsViewset(BaseViewSet):
email=email.get("email").strip().lower(),
workspace_id=workspace.id,
token=jwt.encode(
- {
- "email": email,
- "timestamp": datetime.now().timestamp(),
- },
+ {"email": email, "timestamp": datetime.now().timestamp()},
settings.SECRET_KEY,
algorithm="HS256",
),
@@ -148,10 +135,7 @@ class WorkspaceInvitationsViewset(BaseViewSet):
)
return Response(
- {
- "message": "Emails sent successfully",
- },
- status=status.HTTP_200_OK,
+ {"message": "Emails sent successfully"}, status=status.HTTP_200_OK
)
def destroy(self, request, slug, pk):
@@ -163,9 +147,7 @@ class WorkspaceInvitationsViewset(BaseViewSet):
class WorkspaceJoinEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
"""Invitation response endpoint the user can respond to the invitation"""
@invalidate_cache(path="/api/workspaces/", user=False)
diff --git a/apiserver/plane/app/views/workspace/label.py b/apiserver/plane/app/views/workspace/label.py
index 0ea9ea24a..c93cd44c8 100644
--- a/apiserver/plane/app/views/workspace/label.py
+++ b/apiserver/plane/app/views/workspace/label.py
@@ -9,11 +9,10 @@ from plane.db.models import Label
from plane.app.permissions import WorkspaceViewerPermission
from plane.utils.cache import cache_response
+
class WorkspaceLabelsEndpoint(BaseAPIView):
- permission_classes = [
- WorkspaceViewerPermission,
- ]
-
+ permission_classes = [WorkspaceViewerPermission]
+
@cache_response(60 * 60 * 2)
def get(self, request, slug):
labels = Label.objects.filter(
diff --git a/apiserver/plane/app/views/workspace/member.py b/apiserver/plane/app/views/workspace/member.py
index e64c4e5ed..3f5a4bd2b 100644
--- a/apiserver/plane/app/views/workspace/member.py
+++ b/apiserver/plane/app/views/workspace/member.py
@@ -1,12 +1,5 @@
# Django imports
-from django.db.models import (
- CharField,
- Count,
- Q,
- OuterRef,
- Subquery,
- IntegerField,
-)
+from django.db.models import CharField, Count, Q, OuterRef, Subquery, IntegerField
from django.db.models.functions import Coalesce
from django.db.models.functions import Cast
@@ -49,19 +42,13 @@ class WorkSpaceMemberViewSet(BaseViewSet):
serializer_class = WorkspaceMemberAdminSerializer
model = WorkspaceMember
- search_fields = [
- "member__display_name",
- "member__first_name",
- ]
+ search_fields = ["member__display_name", "member__first_name"]
def get_queryset(self):
return self.filter_queryset(
super()
.get_queryset()
- .filter(
- workspace__slug=self.kwargs.get("slug"),
- is_active=True,
- )
+ .filter(workspace__slug=self.kwargs.get("slug"), is_active=True)
.select_related("workspace", "workspace__owner")
.select_related("member")
)
@@ -71,34 +58,25 @@ class WorkSpaceMemberViewSet(BaseViewSet):
)
def list(self, request, slug):
workspace_member = WorkspaceMember.objects.get(
- member=request.user,
- workspace__slug=slug,
- is_active=True,
+ member=request.user, workspace__slug=slug, is_active=True
)
# Get all active workspace members
workspace_members = self.get_queryset()
if workspace_member.role > 5:
serializer = WorkspaceMemberAdminSerializer(
- workspace_members,
- fields=("id", "member", "role"),
- many=True,
+ workspace_members, fields=("id", "member", "role"), many=True
)
else:
serializer = WorkSpaceMemberSerializer(
- workspace_members,
- fields=("id", "member", "role"),
- many=True,
+ workspace_members, fields=("id", "member", "role"), many=True
)
return Response(serializer.data, status=status.HTTP_200_OK)
@allow_permission(allowed_roles=[ROLE.ADMIN], level="WORKSPACE")
def partial_update(self, request, slug, pk):
workspace_member = WorkspaceMember.objects.get(
- pk=pk,
- workspace__slug=slug,
- member__is_bot=False,
- is_active=True,
+ pk=pk, workspace__slug=slug, member__is_bot=False, is_active=True
)
if request.user.id == workspace_member.member_id:
return Response(
@@ -124,17 +102,12 @@ class WorkSpaceMemberViewSet(BaseViewSet):
def destroy(self, request, slug, pk):
# Check the user role who is deleting the user
workspace_member = WorkspaceMember.objects.get(
- workspace__slug=slug,
- pk=pk,
- member__is_bot=False,
- is_active=True,
+ workspace__slug=slug, pk=pk, member__is_bot=False, is_active=True
)
# check requesting user role
requesting_workspace_member = WorkspaceMember.objects.get(
- workspace__slug=slug,
- member=request.user,
- is_active=True,
+ workspace__slug=slug, member=request.user, is_active=True
)
if str(workspace_member.id) == str(requesting_workspace_member.id):
@@ -147,9 +120,7 @@ class WorkSpaceMemberViewSet(BaseViewSet):
if requesting_workspace_member.role < workspace_member.role:
return Response(
- {
- "error": "You cannot remove a user having role higher than you"
- },
+ {"error": "You cannot remove a user having role higher than you"},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -176,9 +147,7 @@ class WorkSpaceMemberViewSet(BaseViewSet):
# Deactivate the users from the projects where the user is part of
_ = ProjectMember.objects.filter(
- workspace__slug=slug,
- member_id=workspace_member.member_id,
- is_active=True,
+ workspace__slug=slug, member_id=workspace_member.member_id, is_active=True
).update(is_active=False)
workspace_member.is_active = False
@@ -192,26 +161,20 @@ class WorkSpaceMemberViewSet(BaseViewSet):
multiple=True,
)
@invalidate_cache(path="/api/users/me/settings/")
- @invalidate_cache(
- path="api/users/me/workspaces/", user=False, multiple=True
- )
+ @invalidate_cache(path="api/users/me/workspaces/", user=False, multiple=True)
@allow_permission(
allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE"
)
def leave(self, request, slug):
workspace_member = WorkspaceMember.objects.get(
- workspace__slug=slug,
- member=request.user,
- is_active=True,
+ workspace__slug=slug, member=request.user, is_active=True
)
# Check if the leaving user is the only admin of the workspace
if (
workspace_member.role == 20
and not WorkspaceMember.objects.filter(
- workspace__slug=slug,
- role=20,
- is_active=True,
+ workspace__slug=slug, role=20, is_active=True
).count()
> 1
):
@@ -245,9 +208,7 @@ class WorkSpaceMemberViewSet(BaseViewSet):
# # Deactivate the users from the projects where the user is part of
_ = ProjectMember.objects.filter(
- workspace__slug=slug,
- member_id=workspace_member.member_id,
- is_active=True,
+ workspace__slug=slug, member_id=workspace_member.member_id, is_active=True
).update(is_active=False)
# # Deactivate the user
@@ -259,9 +220,7 @@ class WorkSpaceMemberViewSet(BaseViewSet):
class WorkspaceMemberUserViewsEndpoint(BaseAPIView):
def post(self, request, slug):
workspace_member = WorkspaceMember.objects.get(
- workspace__slug=slug,
- member=request.user,
- is_active=True,
+ workspace__slug=slug, member=request.user, is_active=True
)
workspace_member.view_props = request.data.get("view_props", {})
workspace_member.save()
@@ -273,8 +232,7 @@ class WorkspaceMemberUserEndpoint(BaseAPIView):
def get(self, request, slug):
draft_issue_count = (
DraftIssue.objects.filter(
- created_by=request.user,
- workspace_id=OuterRef("workspace_id"),
+ created_by=request.user, workspace_id=OuterRef("workspace_id")
)
.values("workspace_id")
.annotate(count=Count("id"))
@@ -300,30 +258,21 @@ class WorkspaceProjectMemberEndpoint(BaseAPIView):
serializer_class = ProjectMemberRoleSerializer
model = ProjectMember
- permission_classes = [
- WorkspaceEntityPermission,
- ]
+ permission_classes = [WorkspaceEntityPermission]
def get(self, request, slug):
# Fetch all project IDs where the user is involved
project_ids = (
- ProjectMember.objects.filter(
- member=request.user,
- is_active=True,
- )
+ ProjectMember.objects.filter(member=request.user, is_active=True)
.values_list("project_id", flat=True)
.distinct()
)
# Get all the project members in which the user is involved
project_members = ProjectMember.objects.filter(
- workspace__slug=slug,
- project_id__in=project_ids,
- is_active=True,
+ workspace__slug=slug, project_id__in=project_ids, is_active=True
).select_related("project", "member", "workspace")
- project_members = ProjectMemberRoleSerializer(
- project_members, many=True
- ).data
+ project_members = ProjectMemberRoleSerializer(project_members, many=True).data
project_members_dict = dict()
@@ -340,14 +289,9 @@ class WorkspaceProjectMemberEndpoint(BaseAPIView):
class TeamMemberViewSet(BaseViewSet):
serializer_class = TeamSerializer
model = Team
- permission_classes = [
- WorkSpaceAdminPermission,
- ]
+ permission_classes = [WorkSpaceAdminPermission]
- search_fields = [
- "member__display_name",
- "member__first_name",
- ]
+ search_fields = ["member__display_name", "member__first_name"]
def get_queryset(self):
return self.filter_queryset(
@@ -371,9 +315,7 @@ class TeamMemberViewSet(BaseViewSet):
)
if len(members) != len(request.data.get("members", [])):
- users = list(
- set(request.data.get("members", [])).difference(members)
- )
+ users = list(set(request.data.get("members", [])).difference(members))
users = User.objects.filter(pk__in=users)
serializer = UserLiteSerializer(users, many=True)
@@ -387,9 +329,7 @@ class TeamMemberViewSet(BaseViewSet):
workspace = Workspace.objects.get(slug=slug)
- serializer = TeamSerializer(
- data=request.data, context={"workspace": workspace}
- )
+ serializer = TeamSerializer(data=request.data, context={"workspace": workspace})
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
diff --git a/apiserver/plane/app/views/workspace/module.py b/apiserver/plane/app/views/workspace/module.py
index 4b1e0904a..e61fc70e7 100644
--- a/apiserver/plane/app/views/workspace/module.py
+++ b/apiserver/plane/app/views/workspace/module.py
@@ -1,9 +1,5 @@
# Django imports
-from django.db.models import (
- Prefetch,
- Q,
- Count,
-)
+from django.db.models import Prefetch, Q, Count
# Third party modules
from rest_framework import status
@@ -11,17 +7,13 @@ from rest_framework.response import Response
# Module imports
from plane.app.views.base import BaseAPIView
-from plane.db.models import (
- Module,
- ModuleLink,
-)
+from plane.db.models import Module, ModuleLink
from plane.app.permissions import WorkspaceViewerPermission
from plane.app.serializers.module import ModuleSerializer
+
class WorkspaceModulesEndpoint(BaseAPIView):
- permission_classes = [
- WorkspaceViewerPermission,
- ]
+ permission_classes = [WorkspaceViewerPermission]
def get(self, request, slug):
modules = (
@@ -34,9 +26,7 @@ class WorkspaceModulesEndpoint(BaseAPIView):
.prefetch_related(
Prefetch(
"link_module",
- queryset=ModuleLink.objects.select_related(
- "module", "created_by"
- ),
+ queryset=ModuleLink.objects.select_related("module", "created_by"),
)
)
.annotate(
@@ -48,7 +38,7 @@ class WorkspaceModulesEndpoint(BaseAPIView):
issue_module__deleted_at__isnull=True,
),
distinct=True,
- ),
+ )
)
.annotate(
completed_issues=Count(
diff --git a/apiserver/plane/app/views/workspace/state.py b/apiserver/plane/app/views/workspace/state.py
index c69b56d4f..c00044cff 100644
--- a/apiserver/plane/app/views/workspace/state.py
+++ b/apiserver/plane/app/views/workspace/state.py
@@ -9,10 +9,9 @@ from plane.db.models import State
from plane.app.permissions import WorkspaceEntityPermission
from plane.utils.cache import cache_response
+
class WorkspaceStatesEndpoint(BaseAPIView):
- permission_classes = [
- WorkspaceEntityPermission,
- ]
+ permission_classes = [WorkspaceEntityPermission]
@cache_response(60 * 60 * 2)
def get(self, request, slug):
diff --git a/apiserver/plane/app/views/workspace/user.py b/apiserver/plane/app/views/workspace/user.py
index fe7b72cd1..0010b4ae7 100644
--- a/apiserver/plane/app/views/workspace/user.py
+++ b/apiserver/plane/app/views/workspace/user.py
@@ -24,10 +24,7 @@ from django.utils import timezone
from rest_framework import status
from rest_framework.response import Response
-from plane.app.permissions import (
- WorkspaceEntityPermission,
- WorkspaceViewerPermission,
-)
+from plane.app.permissions import WorkspaceEntityPermission, WorkspaceViewerPermission
# Module imports
from plane.app.serializers import (
@@ -58,10 +55,7 @@ from plane.utils.grouper import (
)
from plane.utils.issue_filters import issue_filters
from plane.utils.order_queryset import order_issue_queryset
-from plane.utils.paginator import (
- GroupedOffsetPaginator,
- SubGroupedOffsetPaginator,
-)
+from plane.utils.paginator import GroupedOffsetPaginator, SubGroupedOffsetPaginator
class UserLastProjectWithWorkspaceEndpoint(BaseAPIView):
@@ -72,10 +66,7 @@ class UserLastProjectWithWorkspaceEndpoint(BaseAPIView):
if last_workspace_id is None:
return Response(
- {
- "project_details": [],
- "workspace_details": {},
- },
+ {"project_details": [], "workspace_details": {}},
status=status.HTTP_200_OK,
)
@@ -86,9 +77,7 @@ class UserLastProjectWithWorkspaceEndpoint(BaseAPIView):
workspace_id=last_workspace_id, member=request.user
).select_related("workspace", "project", "member", "workspace__owner")
- project_member_serializer = ProjectMemberSerializer(
- project_member, many=True
- )
+ project_member_serializer = ProjectMemberSerializer(project_member, many=True)
return Response(
{
@@ -100,12 +89,9 @@ class UserLastProjectWithWorkspaceEndpoint(BaseAPIView):
class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
- permission_classes = [
- WorkspaceViewerPermission,
- ]
+ permission_classes = [WorkspaceViewerPermission]
def get(self, request, slug, user_id):
-
filters = issue_filters(request.query_params, "GET")
order_by_param = request.GET.get("order_by", "-created_at")
@@ -144,9 +130,7 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -156,8 +140,7 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
# Issue queryset
issue_queryset, order_by_param = order_issue_queryset(
- issue_queryset=issue_queryset,
- order_by_param=order_by_param,
+ issue_queryset=issue_queryset, order_by_param=order_by_param
)
# Group by
@@ -166,9 +149,7 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
# issue queryset
issue_queryset = issue_queryset_grouper(
- queryset=issue_queryset,
- group_by=group_by,
- sub_group_by=sub_group_by,
+ queryset=issue_queryset, group_by=group_by, sub_group_by=sub_group_by
)
if group_by:
@@ -186,20 +167,14 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=SubGroupedOffsetPaginator,
group_by_fields=issue_group_values(
- field=group_by,
- slug=slug,
- filters=filters,
+ field=group_by, slug=slug, filters=filters
),
sub_group_by_fields=issue_group_values(
- field=sub_group_by,
- slug=slug,
- filters=filters,
+ field=sub_group_by, slug=slug, filters=filters
),
group_by_field_name=group_by,
sub_group_by_field_name=sub_group_by,
@@ -219,15 +194,11 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=GroupedOffsetPaginator,
group_by_fields=issue_group_values(
- field=group_by,
- slug=slug,
- filters=filters,
+ field=group_by, slug=slug, filters=filters
),
group_by_field_name=group_by,
count_filter=Q(
@@ -251,14 +222,11 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView):
class WorkspaceUserPropertiesEndpoint(BaseAPIView):
- permission_classes = [
- WorkspaceViewerPermission,
- ]
+ permission_classes = [WorkspaceViewerPermission]
def patch(self, request, slug):
workspace_properties = WorkspaceUserProperties.objects.get(
- user=request.user,
- workspace__slug=slug,
+ user=request.user, workspace__slug=slug
)
workspace_properties.filters = request.data.get(
@@ -276,10 +244,7 @@ class WorkspaceUserPropertiesEndpoint(BaseAPIView):
return Response(serializer.data, status=status.HTTP_201_CREATED)
def get(self, request, slug):
- (
- workspace_properties,
- _,
- ) = WorkspaceUserProperties.objects.get_or_create(
+ (workspace_properties, _) = WorkspaceUserProperties.objects.get_or_create(
user=request.user, workspace__slug=slug
)
serializer = WorkspaceUserPropertiesSerializer(workspace_properties)
@@ -291,9 +256,7 @@ class WorkspaceUserProfileEndpoint(BaseAPIView):
user_data = User.objects.get(pk=user_id)
requesting_workspace_member = WorkspaceMember.objects.get(
- workspace__slug=slug,
- member=request.user,
- is_active=True,
+ workspace__slug=slug, member=request.user, is_active=True
)
projects = []
if requesting_workspace_member.role >= 15:
@@ -379,9 +342,7 @@ class WorkspaceUserProfileEndpoint(BaseAPIView):
class WorkspaceUserActivityEndpoint(BaseAPIView):
- permission_classes = [
- WorkspaceEntityPermission,
- ]
+ permission_classes = [WorkspaceEntityPermission]
def get(self, request, slug, user_id):
projects = request.query_params.getlist("project", [])
@@ -513,18 +474,14 @@ class WorkspaceUserProfileStatsEndpoint(BaseAPIView):
upcoming_cycles = CycleIssue.objects.filter(
workspace__slug=slug,
cycle__start_date__gt=timezone.now(),
- issue__assignees__in=[
- user_id,
- ],
+ issue__assignees__in=[user_id],
).values("cycle__name", "cycle__id", "cycle__project_id")
present_cycle = CycleIssue.objects.filter(
workspace__slug=slug,
cycle__start_date__lt=timezone.now(),
cycle__end_date__gt=timezone.now(),
- issue__assignees__in=[
- user_id,
- ],
+ issue__assignees__in=[user_id],
).values("cycle__name", "cycle__id", "cycle__project_id")
return Response(
diff --git a/apiserver/plane/asgi.py b/apiserver/plane/asgi.py
index 7333baae3..2dd703ffe 100644
--- a/apiserver/plane/asgi.py
+++ b/apiserver/plane/asgi.py
@@ -11,8 +11,4 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "plane.settings.production")
# is populated before importing code that may import ORM models.
-application = ProtocolTypeRouter(
- {
- "http": get_asgi_application(),
- }
-)
+application = ProtocolTypeRouter({"http": get_asgi_application()})
diff --git a/apiserver/plane/authentication/adapter/base.py b/apiserver/plane/authentication/adapter/base.py
index 906d55700..c7a8c43d3 100644
--- a/apiserver/plane/authentication/adapter/base.py
+++ b/apiserver/plane/authentication/adapter/base.py
@@ -11,11 +11,7 @@ from django.core.exceptions import ValidationError
from zxcvbn import zxcvbn
# Module imports
-from plane.db.models import (
- Profile,
- User,
- WorkspaceMemberInvite,
-)
+from plane.db.models import Profile, User, WorkspaceMemberInvite
from plane.license.utils.instance_value import get_configuration_value
from .error import AuthenticationException, AUTHENTICATION_ERROR_CODES
from plane.bgtasks.user_activation_email_task import user_activation_email
@@ -90,20 +86,13 @@ class Adapter:
# Get configuration value
(ENABLE_SIGNUP,) = get_configuration_value(
- [
- {
- "key": "ENABLE_SIGNUP",
- "default": os.environ.get("ENABLE_SIGNUP", "1"),
- },
- ]
+ [{"key": "ENABLE_SIGNUP", "default": os.environ.get("ENABLE_SIGNUP", "1")}]
)
# Check if sign up is disabled and invite is present or not
if (
ENABLE_SIGNUP == "0"
- and not WorkspaceMemberInvite.objects.filter(
- email=email,
- ).exists()
+ and not WorkspaceMemberInvite.objects.filter(email=email).exists()
):
# Raise exception
raise AuthenticationException(
@@ -124,9 +113,7 @@ class Adapter:
user.token_updated_at = timezone.now()
# If user is not active, send the activation email and set the user as active
if not user.is_active:
- user_activation_email.delay(
- base_host(request=self.request), user.id
- )
+ user_activation_email.delay(base_host(request=self.request), user.id)
# Set user as active
user.is_active = True
user.save()
@@ -182,11 +169,7 @@ class Adapter:
# Call callback if present
if self.callback:
- self.callback(
- user,
- is_signup,
- self.request,
- )
+ self.callback(user, is_signup, self.request)
# Create or update account if token data is present
if self.token_data:
diff --git a/apiserver/plane/authentication/adapter/error.py b/apiserver/plane/authentication/adapter/error.py
index 90e236a80..63fafffbe 100644
--- a/apiserver/plane/authentication/adapter/error.py
+++ b/apiserver/plane/authentication/adapter/error.py
@@ -67,7 +67,6 @@ AUTHENTICATION_ERROR_CODES = {
class AuthenticationException(Exception):
-
error_code = None
error_message = None
payload = {}
@@ -78,10 +77,7 @@ class AuthenticationException(Exception):
self.payload = payload
def get_error_dict(self):
- error = {
- "error_code": self.error_code,
- "error_message": self.error_message,
- }
+ error = {"error_code": self.error_code, "error_message": self.error_message}
for key in self.payload:
error[key] = self.payload[key]
diff --git a/apiserver/plane/authentication/adapter/exception.py b/apiserver/plane/authentication/adapter/exception.py
index a6f7637a9..e906c5a50 100644
--- a/apiserver/plane/authentication/adapter/exception.py
+++ b/apiserver/plane/authentication/adapter/exception.py
@@ -4,7 +4,10 @@ from rest_framework.exceptions import NotAuthenticated
from rest_framework.exceptions import Throttled
# Module imports
-from plane.authentication.adapter.error import AuthenticationException, AUTHENTICATION_ERROR_CODES
+from plane.authentication.adapter.error import (
+ AuthenticationException,
+ AUTHENTICATION_ERROR_CODES,
+)
def auth_exception_handler(exc, context):
@@ -22,6 +25,6 @@ def auth_exception_handler(exc, context):
)
response.data = exc.get_error_dict()
response.status_code = 429
-
+
# Return the response that is generated by the default exception handler.
return response
diff --git a/apiserver/plane/authentication/adapter/oauth.py b/apiserver/plane/authentication/adapter/oauth.py
index c4e78573c..e89383837 100644
--- a/apiserver/plane/authentication/adapter/oauth.py
+++ b/apiserver/plane/authentication/adapter/oauth.py
@@ -68,31 +68,25 @@ class OauthAdapter(Adapter):
def get_user_token(self, data, headers=None):
try:
headers = headers or {}
- response = requests.post(
- self.get_token_url(), data=data, headers=headers
- )
+ response = requests.post(self.get_token_url(), data=data, headers=headers)
response.raise_for_status()
return response.json()
except requests.RequestException:
code = self.authentication_error_code()
raise AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[code],
- error_message=str(code),
+ error_code=AUTHENTICATION_ERROR_CODES[code], error_message=str(code)
)
def get_user_response(self):
try:
- headers = {
- "Authorization": f"Bearer {self.token_data.get('access_token')}"
- }
+ headers = {"Authorization": f"Bearer {self.token_data.get('access_token')}"}
response = requests.get(self.get_user_info_url(), headers=headers)
response.raise_for_status()
return response.json()
except requests.RequestException:
code = self.authentication_error_code()
raise AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[code],
- error_message=str(code),
+ error_code=AUTHENTICATION_ERROR_CODES[code], error_message=str(code)
)
def set_user_data(self, data):
@@ -104,16 +98,12 @@ class OauthAdapter(Adapter):
account = Account.objects.filter(
user=user,
provider=self.provider,
- provider_account_id=self.user_data.get("user").get(
- "provider_id"
- ),
+ provider_account_id=self.user_data.get("user").get("provider_id"),
).first()
# Update the account if it exists
if account:
account.access_token = self.token_data.get("access_token")
- account.refresh_token = self.token_data.get(
- "refresh_token", None
- )
+ account.refresh_token = self.token_data.get("refresh_token", None)
account.access_token_expired_at = self.token_data.get(
"access_token_expired_at"
)
diff --git a/apiserver/plane/authentication/middleware/session.py b/apiserver/plane/authentication/middleware/session.py
index 2bb62b881..822c88316 100644
--- a/apiserver/plane/authentication/middleware/session.py
+++ b/apiserver/plane/authentication/middleware/session.py
@@ -17,9 +17,7 @@ class SessionMiddleware(MiddlewareMixin):
def process_request(self, request):
if "instances" in request.path:
- session_key = request.COOKIES.get(
- settings.ADMIN_SESSION_COOKIE_NAME
- )
+ session_key = request.COOKIES.get(settings.ADMIN_SESSION_COOKIE_NAME)
else:
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
request.session = self.SessionStore(session_key)
diff --git a/apiserver/plane/authentication/provider/credentials/email.py b/apiserver/plane/authentication/provider/credentials/email.py
index 4c7764128..4b8ae0595 100644
--- a/apiserver/plane/authentication/provider/credentials/email.py
+++ b/apiserver/plane/authentication/provider/credentials/email.py
@@ -12,20 +12,10 @@ from plane.license.utils.instance_value import get_configuration_value
class EmailProvider(CredentialAdapter):
-
provider = "email"
- def __init__(
- self,
- request,
- key=None,
- code=None,
- is_signup=False,
- callback=None,
- ):
- super().__init__(
- request=request, provider=self.provider, callback=callback
- )
+ def __init__(self, request, key=None, code=None, is_signup=False, callback=None):
+ super().__init__(request=request, provider=self.provider, callback=callback)
self.key = key
self.code = code
self.is_signup = is_signup
@@ -35,7 +25,7 @@ class EmailProvider(CredentialAdapter):
{
"key": "ENABLE_EMAIL_PASSWORD",
"default": os.environ.get("ENABLE_EMAIL_PASSWORD"),
- },
+ }
]
)
@@ -53,9 +43,7 @@ class EmailProvider(CredentialAdapter):
if User.objects.filter(email=self.key).exists():
raise AuthenticationException(
error_message="USER_ALREADY_EXIST",
- error_code=AUTHENTICATION_ERROR_CODES[
- "USER_ALREADY_EXIST"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["USER_ALREADY_EXIST"],
)
super().set_user_data(
@@ -72,20 +60,14 @@ class EmailProvider(CredentialAdapter):
)
return
else:
- user = User.objects.filter(
- email=self.key,
- ).first()
+ user = User.objects.filter(email=self.key).first()
# User does not exists
if not user:
raise AuthenticationException(
error_message="USER_DOES_NOT_EXIST",
- error_code=AUTHENTICATION_ERROR_CODES[
- "USER_DOES_NOT_EXIST"
- ],
- payload={
- "email": self.key,
- },
+ error_code=AUTHENTICATION_ERROR_CODES["USER_DOES_NOT_EXIST"],
+ payload={"email": self.key},
)
# Check user password
diff --git a/apiserver/plane/authentication/provider/credentials/magic_code.py b/apiserver/plane/authentication/provider/credentials/magic_code.py
index 418dd2a06..4fe8924f3 100644
--- a/apiserver/plane/authentication/provider/credentials/magic_code.py
+++ b/apiserver/plane/authentication/provider/credentials/magic_code.py
@@ -17,26 +17,12 @@ from plane.db.models import User
class MagicCodeProvider(CredentialAdapter):
-
provider = "magic-code"
- def __init__(
- self,
- request,
- key,
- code=None,
- callback=None,
- ):
-
- (
- EMAIL_HOST,
- ENABLE_MAGIC_LINK_LOGIN,
- ) = get_configuration_value(
+ def __init__(self, request, key, code=None, callback=None):
+ (EMAIL_HOST, ENABLE_MAGIC_LINK_LOGIN) = get_configuration_value(
[
- {
- "key": "EMAIL_HOST",
- "default": os.environ.get("EMAIL_HOST"),
- },
+ {"key": "EMAIL_HOST", "default": os.environ.get("EMAIL_HOST")},
{
"key": "ENABLE_MAGIC_LINK_LOGIN",
"default": os.environ.get("ENABLE_MAGIC_LINK_LOGIN", "1"),
@@ -53,16 +39,12 @@ class MagicCodeProvider(CredentialAdapter):
if ENABLE_MAGIC_LINK_LOGIN == "0":
raise AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "MAGIC_LINK_LOGIN_DISABLED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["MAGIC_LINK_LOGIN_DISABLED"],
error_message="MAGIC_LINK_LOGIN_DISABLED",
payload={"email": str(key)},
)
- super().__init__(
- request=request, provider=self.provider, callback=callback
- )
+ super().__init__(request=request, provider=self.provider, callback=callback)
self.key = key
self.code = code
@@ -164,17 +146,13 @@ class MagicCodeProvider(CredentialAdapter):
email = str(self.key).replace("magic_", "", 1)
if User.objects.filter(email=email).exists():
raise AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "EXPIRED_MAGIC_CODE_SIGN_IN"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["EXPIRED_MAGIC_CODE_SIGN_IN"],
error_message="EXPIRED_MAGIC_CODE_SIGN_IN",
payload={"email": str(email)},
)
else:
raise AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "EXPIRED_MAGIC_CODE_SIGN_UP"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["EXPIRED_MAGIC_CODE_SIGN_UP"],
error_message="EXPIRED_MAGIC_CODE_SIGN_UP",
payload={"email": str(email)},
)
diff --git a/apiserver/plane/authentication/provider/oauth/github.py b/apiserver/plane/authentication/provider/oauth/github.py
index edd99b1ba..1808aa515 100644
--- a/apiserver/plane/authentication/provider/oauth/github.py
+++ b/apiserver/plane/authentication/provider/oauth/github.py
@@ -16,14 +16,12 @@ from plane.authentication.adapter.error import (
class GitHubOAuthProvider(OauthAdapter):
-
token_url = "https://github.com/login/oauth/access_token"
userinfo_url = "https://api.github.com/user"
provider = "github"
scope = "read:user user:email"
def __init__(self, request, code=None, state=None, callback=None):
-
GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET = get_configuration_value(
[
{
@@ -53,9 +51,7 @@ class GitHubOAuthProvider(OauthAdapter):
"scope": self.scope,
"state": state,
}
- auth_url = (
- f"https://github.com/login/oauth/authorize?{urlencode(url_params)}"
- )
+ auth_url = f"https://github.com/login/oauth/authorize?{urlencode(url_params)}"
super().__init__(
request,
self.provider,
@@ -86,16 +82,14 @@ class GitHubOAuthProvider(OauthAdapter):
"refresh_token": token_response.get("refresh_token", None),
"access_token_expired_at": (
datetime.fromtimestamp(
- token_response.get("expires_in"),
- tz=pytz.utc,
+ token_response.get("expires_in"), tz=pytz.utc
)
if token_response.get("expires_in")
else None
),
"refresh_token_expired_at": (
datetime.fromtimestamp(
- token_response.get("refresh_token_expired_at"),
- tz=pytz.utc,
+ token_response.get("refresh_token_expired_at"), tz=pytz.utc
)
if token_response.get("refresh_token_expired_at")
else None
@@ -110,19 +104,12 @@ class GitHubOAuthProvider(OauthAdapter):
emails_url = "https://api.github.com/user/emails"
emails_response = requests.get(emails_url, headers=headers).json()
email = next(
- (
- email["email"]
- for email in emails_response
- if email["primary"]
- ),
- None,
+ (email["email"] for email in emails_response if email["primary"]), None
)
return email
except requests.RequestException:
raise AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GITHUB_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GITHUB_OAUTH_PROVIDER_ERROR"],
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
)
diff --git a/apiserver/plane/authentication/provider/oauth/gitlab.py b/apiserver/plane/authentication/provider/oauth/gitlab.py
index 3795cc37f..df6fb7c44 100644
--- a/apiserver/plane/authentication/provider/oauth/gitlab.py
+++ b/apiserver/plane/authentication/provider/oauth/gitlab.py
@@ -15,31 +15,25 @@ from plane.authentication.adapter.error import (
class GitLabOAuthProvider(OauthAdapter):
-
provider = "gitlab"
scope = "read_user"
def __init__(self, request, code=None, state=None, callback=None):
-
- GITLAB_CLIENT_ID, GITLAB_CLIENT_SECRET, GITLAB_HOST = (
- get_configuration_value(
- [
- {
- "key": "GITLAB_CLIENT_ID",
- "default": os.environ.get("GITLAB_CLIENT_ID"),
- },
- {
- "key": "GITLAB_CLIENT_SECRET",
- "default": os.environ.get("GITLAB_CLIENT_SECRET"),
- },
- {
- "key": "GITLAB_HOST",
- "default": os.environ.get(
- "GITLAB_HOST", "https://gitlab.com"
- ),
- },
- ]
- )
+ GITLAB_CLIENT_ID, GITLAB_CLIENT_SECRET, GITLAB_HOST = get_configuration_value(
+ [
+ {
+ "key": "GITLAB_CLIENT_ID",
+ "default": os.environ.get("GITLAB_CLIENT_ID"),
+ },
+ {
+ "key": "GITLAB_CLIENT_SECRET",
+ "default": os.environ.get("GITLAB_CLIENT_SECRET"),
+ },
+ {
+ "key": "GITLAB_HOST",
+ "default": os.environ.get("GITLAB_HOST", "https://gitlab.com"),
+ },
+ ]
)
self.host = GITLAB_HOST
@@ -104,8 +98,7 @@ class GitLabOAuthProvider(OauthAdapter):
),
"refresh_token_expired_at": (
datetime.fromtimestamp(
- token_response.get("refresh_token_expired_at"),
- tz=pytz.utc,
+ token_response.get("refresh_token_expired_at"), tz=pytz.utc
)
if token_response.get("refresh_token_expired_at")
else None
diff --git a/apiserver/plane/authentication/provider/oauth/google.py b/apiserver/plane/authentication/provider/oauth/google.py
index 9c17a75af..d3f683619 100644
--- a/apiserver/plane/authentication/provider/oauth/google.py
+++ b/apiserver/plane/authentication/provider/oauth/google.py
@@ -53,7 +53,9 @@ class GoogleOAuthProvider(OauthAdapter):
"prompt": "consent",
"state": state,
}
- auth_url = f"https://accounts.google.com/o/oauth2/v2/auth?{urlencode(url_params)}"
+ auth_url = (
+ f"https://accounts.google.com/o/oauth2/v2/auth?{urlencode(url_params)}"
+ )
super().__init__(
request,
@@ -84,16 +86,14 @@ class GoogleOAuthProvider(OauthAdapter):
"refresh_token": token_response.get("refresh_token", None),
"access_token_expired_at": (
datetime.fromtimestamp(
- token_response.get("expires_in"),
- tz=pytz.utc,
+ token_response.get("expires_in"), tz=pytz.utc
)
if token_response.get("expires_in")
else None
),
"refresh_token_expired_at": (
datetime.fromtimestamp(
- token_response.get("refresh_token_expired_at"),
- tz=pytz.utc,
+ token_response.get("refresh_token_expired_at"), tz=pytz.utc
)
if token_response.get("refresh_token_expired_at")
else None
diff --git a/apiserver/plane/authentication/session.py b/apiserver/plane/authentication/session.py
index 7bb0b4a00..862a63c13 100644
--- a/apiserver/plane/authentication/session.py
+++ b/apiserver/plane/authentication/session.py
@@ -2,7 +2,6 @@ from rest_framework.authentication import SessionAuthentication
class BaseSessionAuthentication(SessionAuthentication):
-
# Disable csrf for the rest apis
def enforce_csrf(self, request):
return
diff --git a/apiserver/plane/authentication/urls.py b/apiserver/plane/authentication/urls.py
index a375d94cb..b52cf2a21 100644
--- a/apiserver/plane/authentication/urls.py
+++ b/apiserver/plane/authentication/urls.py
@@ -40,64 +40,20 @@ from .views import (
urlpatterns = [
# credentials
- path(
- "sign-in/",
- SignInAuthEndpoint.as_view(),
- name="sign-in",
- ),
- path(
- "sign-up/",
- SignUpAuthEndpoint.as_view(),
- name="sign-up",
- ),
- path(
- "spaces/sign-in/",
- SignInAuthSpaceEndpoint.as_view(),
- name="sign-in",
- ),
- path(
- "spaces/sign-up/",
- SignUpAuthSpaceEndpoint.as_view(),
- name="sign-in",
- ),
+ path("sign-in/", SignInAuthEndpoint.as_view(), name="sign-in"),
+ path("sign-up/", SignUpAuthEndpoint.as_view(), name="sign-up"),
+ path("spaces/sign-in/", SignInAuthSpaceEndpoint.as_view(), name="sign-in"),
+ path("spaces/sign-up/", SignUpAuthSpaceEndpoint.as_view(), name="sign-in"),
# signout
- path(
- "sign-out/",
- SignOutAuthEndpoint.as_view(),
- name="sign-out",
- ),
- path(
- "spaces/sign-out/",
- SignOutAuthSpaceEndpoint.as_view(),
- name="sign-out",
- ),
+ path("sign-out/", SignOutAuthEndpoint.as_view(), name="sign-out"),
+ path("spaces/sign-out/", SignOutAuthSpaceEndpoint.as_view(), name="sign-out"),
# csrf token
- path(
- "get-csrf-token/",
- CSRFTokenEndpoint.as_view(),
- name="get_csrf_token",
- ),
+ path("get-csrf-token/", CSRFTokenEndpoint.as_view(), name="get_csrf_token"),
# Magic sign in
- path(
- "magic-generate/",
- MagicGenerateEndpoint.as_view(),
- name="magic-generate",
- ),
- path(
- "magic-sign-in/",
- MagicSignInEndpoint.as_view(),
- name="magic-sign-in",
- ),
- path(
- "magic-sign-up/",
- MagicSignUpEndpoint.as_view(),
- name="magic-sign-up",
- ),
- path(
- "get-csrf-token/",
- CSRFTokenEndpoint.as_view(),
- name="get_csrf_token",
- ),
+ path("magic-generate/", MagicGenerateEndpoint.as_view(), name="magic-generate"),
+ path("magic-sign-in/", MagicSignInEndpoint.as_view(), name="magic-sign-in"),
+ path("magic-sign-up/", MagicSignUpEndpoint.as_view(), name="magic-sign-up"),
+ path("get-csrf-token/", CSRFTokenEndpoint.as_view(), name="get_csrf_token"),
path(
"spaces/magic-generate/",
MagicGenerateSpaceEndpoint.as_view(),
@@ -114,16 +70,8 @@ urlpatterns = [
name="magic-sign-up",
),
## Google Oauth
- path(
- "google/",
- GoogleOauthInitiateEndpoint.as_view(),
- name="google-initiate",
- ),
- path(
- "google/callback/",
- GoogleCallbackEndpoint.as_view(),
- name="google-callback",
- ),
+ path("google/", GoogleOauthInitiateEndpoint.as_view(), name="google-initiate"),
+ path("google/callback/", GoogleCallbackEndpoint.as_view(), name="google-callback"),
path(
"spaces/google/",
GoogleOauthInitiateSpaceEndpoint.as_view(),
@@ -135,16 +83,8 @@ urlpatterns = [
name="google-callback",
),
## Github Oauth
- path(
- "github/",
- GitHubOauthInitiateEndpoint.as_view(),
- name="github-initiate",
- ),
- path(
- "github/callback/",
- GitHubCallbackEndpoint.as_view(),
- name="github-callback",
- ),
+ path("github/", GitHubOauthInitiateEndpoint.as_view(), name="github-initiate"),
+ path("github/callback/", GitHubCallbackEndpoint.as_view(), name="github-callback"),
path(
"spaces/github/",
GitHubOauthInitiateSpaceEndpoint.as_view(),
@@ -156,16 +96,8 @@ urlpatterns = [
name="github-callback",
),
## Gitlab Oauth
- path(
- "gitlab/",
- GitLabOauthInitiateEndpoint.as_view(),
- name="gitlab-initiate",
- ),
- path(
- "gitlab/callback/",
- GitLabCallbackEndpoint.as_view(),
- name="gitlab-callback",
- ),
+ path("gitlab/", GitLabOauthInitiateEndpoint.as_view(), name="gitlab-initiate"),
+ path("gitlab/callback/", GitLabCallbackEndpoint.as_view(), name="gitlab-callback"),
path(
"spaces/gitlab/",
GitLabOauthInitiateSpaceEndpoint.as_view(),
@@ -177,22 +109,10 @@ urlpatterns = [
name="gitlab-callback",
),
# Email Check
- path(
- "email-check/",
- EmailCheckEndpoint.as_view(),
- name="email-check",
- ),
- path(
- "spaces/email-check/",
- EmailCheckSpaceEndpoint.as_view(),
- name="email-check",
- ),
+ path("email-check/", EmailCheckEndpoint.as_view(), name="email-check"),
+ path("spaces/email-check/", EmailCheckSpaceEndpoint.as_view(), name="email-check"),
# Password
- path(
- "forgot-password/",
- ForgotPasswordEndpoint.as_view(),
- name="forgot-password",
- ),
+ path("forgot-password/", ForgotPasswordEndpoint.as_view(), name="forgot-password"),
path(
"reset-password///",
ResetPasswordEndpoint.as_view(),
@@ -208,14 +128,6 @@ urlpatterns = [
ResetPasswordSpaceEndpoint.as_view(),
name="forgot-password",
),
- path(
- "change-password/",
- ChangePasswordEndpoint.as_view(),
- name="forgot-password",
- ),
- path(
- "set-password/",
- SetUserPasswordEndpoint.as_view(),
- name="set-password",
- ),
+ path("change-password/", ChangePasswordEndpoint.as_view(), name="forgot-password"),
+ path("set-password/", SetUserPasswordEndpoint.as_view(), name="set-password"),
]
diff --git a/apiserver/plane/authentication/utils/login.py b/apiserver/plane/authentication/utils/login.py
index f5d453d02..ba7f9d1e1 100644
--- a/apiserver/plane/authentication/utils/login.py
+++ b/apiserver/plane/authentication/utils/login.py
@@ -17,10 +17,7 @@ def user_login(request, user, is_app=False, is_admin=False, is_space=False):
"user_agent": request.META.get("HTTP_USER_AGENT", ""),
"ip_address": request.META.get("REMOTE_ADDR", ""),
"domain": base_host(
- request=request,
- is_app=is_app,
- is_admin=is_admin,
- is_space=is_space,
+ request=request, is_app=is_app, is_admin=is_admin, is_space=is_space
),
}
request.session["device_info"] = device_info
diff --git a/apiserver/plane/authentication/utils/redirection_path.py b/apiserver/plane/authentication/utils/redirection_path.py
index 62cc1f019..459ad7434 100644
--- a/apiserver/plane/authentication/utils/redirection_path.py
+++ b/apiserver/plane/authentication/utils/redirection_path.py
@@ -27,8 +27,7 @@ def get_redirection_path(user):
fallback_workspace = (
Workspace.objects.filter(
- workspace_member__member_id=user.id,
- workspace_member__is_active=True,
+ workspace_member__member_id=user.id, workspace_member__is_active=True
)
.order_by("created_at")
.first()
diff --git a/apiserver/plane/authentication/utils/user_auth_workflow.py b/apiserver/plane/authentication/utils/user_auth_workflow.py
index e7cb4942e..13de4c287 100644
--- a/apiserver/plane/authentication/utils/user_auth_workflow.py
+++ b/apiserver/plane/authentication/utils/user_auth_workflow.py
@@ -1,9 +1,5 @@
from .workspace_project_join import process_workspace_project_invitations
-def post_user_auth_workflow(
- user,
- is_signup,
- request,
-):
+def post_user_auth_workflow(user, is_signup, request):
process_workspace_project_invitations(user=user)
diff --git a/apiserver/plane/authentication/views/__init__.py b/apiserver/plane/authentication/views/__init__.py
index af58a9cbd..24ae1f673 100644
--- a/apiserver/plane/authentication/views/__init__.py
+++ b/apiserver/plane/authentication/views/__init__.py
@@ -1,52 +1,23 @@
-from .common import (
- ChangePasswordEndpoint,
- CSRFTokenEndpoint,
- SetUserPasswordEndpoint,
-)
+from .common import ChangePasswordEndpoint, CSRFTokenEndpoint, SetUserPasswordEndpoint
from .app.check import EmailCheckEndpoint
-from .app.email import (
- SignInAuthEndpoint,
- SignUpAuthEndpoint,
-)
-from .app.github import (
- GitHubCallbackEndpoint,
- GitHubOauthInitiateEndpoint,
-)
-from .app.gitlab import (
- GitLabCallbackEndpoint,
- GitLabOauthInitiateEndpoint,
-)
-from .app.google import (
- GoogleCallbackEndpoint,
- GoogleOauthInitiateEndpoint,
-)
-from .app.magic import (
- MagicGenerateEndpoint,
- MagicSignInEndpoint,
- MagicSignUpEndpoint,
-)
+from .app.email import SignInAuthEndpoint, SignUpAuthEndpoint
+from .app.github import GitHubCallbackEndpoint, GitHubOauthInitiateEndpoint
+from .app.gitlab import GitLabCallbackEndpoint, GitLabOauthInitiateEndpoint
+from .app.google import GoogleCallbackEndpoint, GoogleOauthInitiateEndpoint
+from .app.magic import MagicGenerateEndpoint, MagicSignInEndpoint, MagicSignUpEndpoint
from .app.signout import SignOutAuthEndpoint
from .space.email import SignInAuthSpaceEndpoint, SignUpAuthSpaceEndpoint
-from .space.github import (
- GitHubCallbackSpaceEndpoint,
- GitHubOauthInitiateSpaceEndpoint,
-)
+from .space.github import GitHubCallbackSpaceEndpoint, GitHubOauthInitiateSpaceEndpoint
-from .space.gitlab import (
- GitLabCallbackSpaceEndpoint,
- GitLabOauthInitiateSpaceEndpoint,
-)
+from .space.gitlab import GitLabCallbackSpaceEndpoint, GitLabOauthInitiateSpaceEndpoint
-from .space.google import (
- GoogleCallbackSpaceEndpoint,
- GoogleOauthInitiateSpaceEndpoint,
-)
+from .space.google import GoogleCallbackSpaceEndpoint, GoogleOauthInitiateSpaceEndpoint
from .space.magic import (
MagicGenerateSpaceEndpoint,
@@ -62,7 +33,4 @@ from .space.password_management import (
ForgotPasswordSpaceEndpoint,
ResetPasswordSpaceEndpoint,
)
-from .app.password_management import (
- ForgotPasswordEndpoint,
- ResetPasswordEndpoint,
-)
+from .app.password_management import ForgotPasswordEndpoint, ResetPasswordEndpoint
diff --git a/apiserver/plane/authentication/views/app/check.py b/apiserver/plane/authentication/views/app/check.py
index 6af8859fc..c7e4b8a5e 100644
--- a/apiserver/plane/authentication/views/app/check.py
+++ b/apiserver/plane/authentication/views/app/check.py
@@ -19,42 +19,27 @@ from plane.authentication.adapter.error import (
AUTHENTICATION_ERROR_CODES,
)
from plane.authentication.rate_limit import AuthenticationThrottle
-from plane.license.utils.instance_value import (
- get_configuration_value,
-)
+from plane.license.utils.instance_value import get_configuration_value
class EmailCheckEndpoint(APIView):
+ permission_classes = [AllowAny]
- permission_classes = [
- AllowAny,
- ]
-
- throttle_classes = [
- AuthenticationThrottle,
- ]
+ throttle_classes = [AuthenticationThrottle]
def post(self, request):
# Check instance configuration
instance = Instance.objects.first()
if instance is None or not instance.is_setup_done:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
(EMAIL_HOST, ENABLE_MAGIC_LINK_LOGIN) = get_configuration_value(
[
- {
- "key": "EMAIL_HOST",
- "default": os.environ.get("EMAIL_HOST", ""),
- },
+ {"key": "EMAIL_HOST", "default": os.environ.get("EMAIL_HOST", "")},
{
"key": "ENABLE_MAGIC_LINK_LOGIN",
"default": os.environ.get("ENABLE_MAGIC_LINK_LOGIN", "1"),
@@ -73,10 +58,7 @@ class EmailCheckEndpoint(APIView):
error_code=AUTHENTICATION_ERROR_CODES["EMAIL_REQUIRED"],
error_message="EMAIL_REQUIRED",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
# Validate email
try:
@@ -86,10 +68,7 @@ class EmailCheckEndpoint(APIView):
error_code=AUTHENTICATION_ERROR_CODES["INVALID_EMAIL"],
error_message="INVALID_EMAIL",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
# Check if a user already exists with the given email
existing_user = User.objects.filter(email=email).first()
diff --git a/apiserver/plane/authentication/views/app/email.py b/apiserver/plane/authentication/views/app/email.py
index 08a3e8b01..805b273a1 100644
--- a/apiserver/plane/authentication/views/app/email.py
+++ b/apiserver/plane/authentication/views/app/email.py
@@ -13,9 +13,7 @@ from plane.authentication.utils.login import user_login
from plane.license.models import Instance
from plane.authentication.utils.host import base_host
from plane.authentication.utils.redirection_path import get_redirection_path
-from plane.authentication.utils.user_auth_workflow import (
- post_user_auth_workflow,
-)
+from plane.authentication.utils.user_auth_workflow import post_user_auth_workflow
from plane.db.models import User
from plane.authentication.adapter.error import (
AuthenticationException,
@@ -24,7 +22,6 @@ from plane.authentication.adapter.error import (
class SignInAuthEndpoint(View):
-
def post(self, request):
next_path = request.POST.get("next_path")
# Check instance configuration
@@ -32,9 +29,7 @@ class SignInAuthEndpoint(View):
if instance is None or not instance.is_setup_done:
# Redirection params
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
params = exc.get_error_dict()
@@ -42,8 +37,7 @@ class SignInAuthEndpoint(View):
params["next_path"] = str(next_path)
# Base URL join
url = urljoin(
- base_host(request=request, is_app=True),
- "sign-in?" + urlencode(params),
+ base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
)
return HttpResponseRedirect(url)
@@ -66,8 +60,7 @@ class SignInAuthEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "sign-in?" + urlencode(params),
+ base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
)
return HttpResponseRedirect(url)
@@ -85,8 +78,7 @@ class SignInAuthEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "sign-in?" + urlencode(params),
+ base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
)
return HttpResponseRedirect(url)
@@ -102,8 +94,7 @@ class SignInAuthEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "sign-in?" + urlencode(params),
+ base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
)
return HttpResponseRedirect(url)
@@ -132,14 +123,12 @@ class SignInAuthEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "sign-in?" + urlencode(params),
+ base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
)
return HttpResponseRedirect(url)
class SignUpAuthEndpoint(View):
-
def post(self, request):
next_path = request.POST.get("next_path")
# Check instance configuration
@@ -147,17 +136,14 @@ class SignUpAuthEndpoint(View):
if instance is None or not instance.is_setup_done:
# Redirection params
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
params = exc.get_error_dict()
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
@@ -177,8 +163,7 @@ class SignUpAuthEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
# Validate the email
@@ -196,8 +181,7 @@ class SignUpAuthEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
@@ -215,8 +199,7 @@ class SignUpAuthEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
@@ -244,7 +227,6 @@ class SignUpAuthEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
diff --git a/apiserver/plane/authentication/views/app/github.py b/apiserver/plane/authentication/views/app/github.py
index f93beefa3..f1a15474c 100644
--- a/apiserver/plane/authentication/views/app/github.py
+++ b/apiserver/plane/authentication/views/app/github.py
@@ -9,9 +9,7 @@ from django.views import View
from plane.authentication.provider.oauth.github import GitHubOAuthProvider
from plane.authentication.utils.login import user_login
from plane.authentication.utils.redirection_path import get_redirection_path
-from plane.authentication.utils.user_auth_workflow import (
- post_user_auth_workflow,
-)
+from plane.authentication.utils.user_auth_workflow import post_user_auth_workflow
from plane.license.models import Instance
from plane.authentication.utils.host import base_host
from plane.authentication.adapter.error import (
@@ -21,7 +19,6 @@ from plane.authentication.adapter.error import (
class GitHubOauthInitiateEndpoint(View):
-
def get(self, request):
# Get host and next path
request.session["host"] = base_host(request=request, is_app=True)
@@ -33,17 +30,14 @@ class GitHubOauthInitiateEndpoint(View):
instance = Instance.objects.first()
if instance is None or not instance.is_setup_done:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
params = exc.get_error_dict()
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
try:
@@ -57,14 +51,12 @@ class GitHubOauthInitiateEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
class GitHubCallbackEndpoint(View):
-
def get(self, request):
code = request.GET.get("code")
state = request.GET.get("state")
@@ -73,41 +65,29 @@ class GitHubCallbackEndpoint(View):
if state != request.session.get("state", ""):
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GITHUB_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GITHUB_OAUTH_PROVIDER_ERROR"],
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
)
params = exc.get_error_dict()
if next_path:
params["next_path"] = str(next_path)
- url = urljoin(
- base_host,
- "?" + urlencode(params),
- )
+ url = urljoin(base_host, "?" + urlencode(params))
return HttpResponseRedirect(url)
if not code:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GITHUB_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GITHUB_OAUTH_PROVIDER_ERROR"],
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
)
params = exc.get_error_dict()
if next_path:
params["next_path"] = str(next_path)
- url = urljoin(
- base_host,
- "?" + urlencode(params),
- )
+ url = urljoin(base_host, "?" + urlencode(params))
return HttpResponseRedirect(url)
try:
provider = GitHubOAuthProvider(
- request=request,
- code=code,
- callback=post_user_auth_workflow,
+ request=request, code=code, callback=post_user_auth_workflow
)
user = provider.authenticate()
# Login the user and record his device info
@@ -124,8 +104,5 @@ class GitHubCallbackEndpoint(View):
params = e.get_error_dict()
if next_path:
params["next_path"] = str(next_path)
- url = urljoin(
- base_host,
- "?" + urlencode(params),
- )
+ url = urljoin(base_host, "?" + urlencode(params))
return HttpResponseRedirect(url)
diff --git a/apiserver/plane/authentication/views/app/gitlab.py b/apiserver/plane/authentication/views/app/gitlab.py
index 02a44aeb4..bc0c9c8d7 100644
--- a/apiserver/plane/authentication/views/app/gitlab.py
+++ b/apiserver/plane/authentication/views/app/gitlab.py
@@ -9,9 +9,7 @@ from django.views import View
from plane.authentication.provider.oauth.gitlab import GitLabOAuthProvider
from plane.authentication.utils.login import user_login
from plane.authentication.utils.redirection_path import get_redirection_path
-from plane.authentication.utils.user_auth_workflow import (
- post_user_auth_workflow,
-)
+from plane.authentication.utils.user_auth_workflow import post_user_auth_workflow
from plane.license.models import Instance
from plane.authentication.utils.host import base_host
from plane.authentication.adapter.error import (
@@ -21,7 +19,6 @@ from plane.authentication.adapter.error import (
class GitLabOauthInitiateEndpoint(View):
-
def get(self, request):
# Get host and next path
request.session["host"] = base_host(request=request, is_app=True)
@@ -33,17 +30,14 @@ class GitLabOauthInitiateEndpoint(View):
instance = Instance.objects.first()
if instance is None or not instance.is_setup_done:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
params = exc.get_error_dict()
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
try:
@@ -57,14 +51,12 @@ class GitLabOauthInitiateEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
class GitLabCallbackEndpoint(View):
-
def get(self, request):
code = request.GET.get("code")
state = request.GET.get("state")
@@ -73,41 +65,29 @@ class GitLabCallbackEndpoint(View):
if state != request.session.get("state", ""):
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GITLAB_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GITLAB_OAUTH_PROVIDER_ERROR"],
error_message="GITLAB_OAUTH_PROVIDER_ERROR",
)
params = exc.get_error_dict()
if next_path:
params["next_path"] = str(next_path)
- url = urljoin(
- base_host,
- "?" + urlencode(params),
- )
+ url = urljoin(base_host, "?" + urlencode(params))
return HttpResponseRedirect(url)
if not code:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GITLAB_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GITLAB_OAUTH_PROVIDER_ERROR"],
error_message="GITLAB_OAUTH_PROVIDER_ERROR",
)
params = exc.get_error_dict()
if next_path:
params["next_path"] = str(next_path)
- url = urljoin(
- base_host,
- "?" + urlencode(params),
- )
+ url = urljoin(base_host, "?" + urlencode(params))
return HttpResponseRedirect(url)
try:
provider = GitLabOAuthProvider(
- request=request,
- code=code,
- callback=post_user_auth_workflow,
+ request=request, code=code, callback=post_user_auth_workflow
)
user = provider.authenticate()
# Login the user and record his device info
@@ -124,8 +104,5 @@ class GitLabCallbackEndpoint(View):
params = e.get_error_dict()
if next_path:
params["next_path"] = str(next_path)
- url = urljoin(
- base_host,
- "?" + urlencode(params),
- )
+ url = urljoin(base_host, "?" + urlencode(params))
return HttpResponseRedirect(url)
diff --git a/apiserver/plane/authentication/views/app/google.py b/apiserver/plane/authentication/views/app/google.py
index 05f4511e2..46c0d1980 100644
--- a/apiserver/plane/authentication/views/app/google.py
+++ b/apiserver/plane/authentication/views/app/google.py
@@ -11,9 +11,7 @@ from django.views import View
from plane.authentication.provider.oauth.google import GoogleOAuthProvider
from plane.authentication.utils.login import user_login
from plane.authentication.utils.redirection_path import get_redirection_path
-from plane.authentication.utils.user_auth_workflow import (
- post_user_auth_workflow,
-)
+from plane.authentication.utils.user_auth_workflow import post_user_auth_workflow
from plane.license.models import Instance
from plane.authentication.utils.host import base_host
from plane.authentication.adapter.error import (
@@ -33,17 +31,14 @@ class GoogleOauthInitiateEndpoint(View):
instance = Instance.objects.first()
if instance is None or not instance.is_setup_done:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
params = exc.get_error_dict()
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
@@ -58,8 +53,7 @@ class GoogleOauthInitiateEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
@@ -73,39 +67,27 @@ class GoogleCallbackEndpoint(View):
if state != request.session.get("state", ""):
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GOOGLE_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GOOGLE_OAUTH_PROVIDER_ERROR"],
error_message="GOOGLE_OAUTH_PROVIDER_ERROR",
)
params = exc.get_error_dict()
if next_path:
params["next_path"] = str(next_path)
- url = urljoin(
- base_host,
- "?" + urlencode(params),
- )
+ url = urljoin(base_host, "?" + urlencode(params))
return HttpResponseRedirect(url)
if not code:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GOOGLE_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GOOGLE_OAUTH_PROVIDER_ERROR"],
error_message="GOOGLE_OAUTH_PROVIDER_ERROR",
)
params = exc.get_error_dict()
if next_path:
params["next_path"] = next_path
- url = urljoin(
- base_host,
- "?" + urlencode(params),
- )
+ url = urljoin(base_host, "?" + urlencode(params))
return HttpResponseRedirect(url)
try:
provider = GoogleOAuthProvider(
- request=request,
- code=code,
- callback=post_user_auth_workflow,
+ request=request, code=code, callback=post_user_auth_workflow
)
user = provider.authenticate()
# Login the user and record his device info
@@ -119,8 +101,5 @@ class GoogleCallbackEndpoint(View):
params = e.get_error_dict()
if next_path:
params["next_path"] = str(next_path)
- url = urljoin(
- base_host,
- "?" + urlencode(params),
- )
+ url = urljoin(base_host, "?" + urlencode(params))
return HttpResponseRedirect(url)
diff --git a/apiserver/plane/authentication/views/app/magic.py b/apiserver/plane/authentication/views/app/magic.py
index 980eb4e7c..e02784333 100644
--- a/apiserver/plane/authentication/views/app/magic.py
+++ b/apiserver/plane/authentication/views/app/magic.py
@@ -13,14 +13,10 @@ from rest_framework.response import Response
from rest_framework.views import APIView
# Module imports
-from plane.authentication.provider.credentials.magic_code import (
- MagicCodeProvider,
-)
+from plane.authentication.provider.credentials.magic_code import MagicCodeProvider
from plane.authentication.utils.login import user_login
from plane.authentication.utils.redirection_path import get_redirection_path
-from plane.authentication.utils.user_auth_workflow import (
- post_user_auth_workflow,
-)
+from plane.authentication.utils.user_auth_workflow import post_user_auth_workflow
from plane.bgtasks.magic_link_code_task import magic_link
from plane.license.models import Instance
from plane.authentication.utils.host import base_host
@@ -33,28 +29,19 @@ from plane.authentication.rate_limit import AuthenticationThrottle
class MagicGenerateEndpoint(APIView):
+ permission_classes = [AllowAny]
- permission_classes = [
- AllowAny,
- ]
-
- throttle_classes = [
- AuthenticationThrottle,
- ]
+ throttle_classes = [AuthenticationThrottle]
def post(self, request):
# Check if instance is configured
instance = Instance.objects.first()
if instance is None or not instance.is_setup_done:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
- return Response(
- exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
origin = request.META.get("HTTP_ORIGIN", "/")
email = request.data.get("email", False)
@@ -69,16 +56,11 @@ class MagicGenerateEndpoint(APIView):
return Response({"key": str(key)}, status=status.HTTP_200_OK)
except AuthenticationException as e:
params = e.get_error_dict()
- return Response(
- params,
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(params, status=status.HTTP_400_BAD_REQUEST)
class MagicSignInEndpoint(View):
-
def post(self, request):
-
# set the referer as session to redirect after login
code = request.POST.get("code", "").strip()
email = request.POST.get("email", "").strip().lower()
@@ -95,8 +77,7 @@ class MagicSignInEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "sign-in?" + urlencode(params),
+ base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
)
return HttpResponseRedirect(url)
@@ -112,8 +93,7 @@ class MagicSignInEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "sign-in?" + urlencode(params),
+ base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
)
return HttpResponseRedirect(url)
@@ -146,16 +126,13 @@ class MagicSignInEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "sign-in?" + urlencode(params),
+ base_host(request=request, is_app=True), "sign-in?" + urlencode(params)
)
return HttpResponseRedirect(url)
class MagicSignUpEndpoint(View):
-
def post(self, request):
-
# set the referer as session to redirect after login
code = request.POST.get("code", "").strip()
email = request.POST.get("email", "").strip().lower()
@@ -172,8 +149,7 @@ class MagicSignUpEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
# Existing user
@@ -187,8 +163,7 @@ class MagicSignUpEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
@@ -216,7 +191,6 @@ class MagicSignUpEndpoint(View):
if next_path:
params["next_path"] = str(next_path)
url = urljoin(
- base_host(request=request, is_app=True),
- "?" + urlencode(params),
+ base_host(request=request, is_app=True), "?" + urlencode(params)
)
return HttpResponseRedirect(url)
diff --git a/apiserver/plane/authentication/views/app/password_management.py b/apiserver/plane/authentication/views/app/password_management.py
index 43054867e..cad498e63 100644
--- a/apiserver/plane/authentication/views/app/password_management.py
+++ b/apiserver/plane/authentication/views/app/password_management.py
@@ -14,11 +14,7 @@ from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.http import HttpResponseRedirect
-from django.utils.encoding import (
- DjangoUnicodeDecodeError,
- smart_bytes,
- smart_str,
-)
+from django.utils.encoding import DjangoUnicodeDecodeError, smart_bytes, smart_str
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
from django.views import View
@@ -34,6 +30,7 @@ from plane.authentication.adapter.error import (
)
from plane.authentication.rate_limit import AuthenticationThrottle
+
def generate_password_token(user):
uidb64 = urlsafe_base64_encode(smart_bytes(user.id))
token = PasswordResetTokenGenerator().make_token(user)
@@ -42,13 +39,9 @@ def generate_password_token(user):
class ForgotPasswordEndpoint(APIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
- throttle_classes = [
- AuthenticationThrottle,
- ]
+ throttle_classes = [AuthenticationThrottle]
def post(self, request):
email = request.data.get("email")
@@ -57,23 +50,13 @@ class ForgotPasswordEndpoint(APIView):
instance = Instance.objects.first()
if instance is None or not instance.is_setup_done:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
(EMAIL_HOST,) = get_configuration_value(
- [
- {
- "key": "EMAIL_HOST",
- "default": os.environ.get("EMAIL_HOST"),
- },
- ]
+ [{"key": "EMAIL_HOST", "default": os.environ.get("EMAIL_HOST")}]
)
if not (EMAIL_HOST):
@@ -81,10 +64,7 @@ class ForgotPasswordEndpoint(APIView):
error_message="SMTP_NOT_CONFIGURED",
error_code=AUTHENTICATION_ERROR_CODES["SMTP_NOT_CONFIGURED"],
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
try:
validate_email(email)
@@ -93,10 +73,7 @@ class ForgotPasswordEndpoint(APIView):
error_code=AUTHENTICATION_ERROR_CODES["INVALID_EMAIL"],
error_message="INVALID_EMAIL",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
# Get the user
user = User.objects.filter(email=email).first()
@@ -116,14 +93,10 @@ class ForgotPasswordEndpoint(APIView):
error_code=AUTHENTICATION_ERROR_CODES["USER_DOES_NOT_EXIST"],
error_message="USER_DOES_NOT_EXIST",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
class ResetPasswordEndpoint(View):
-
def post(self, request, uidb64, token):
try:
# Decode the id from the uidb64
@@ -133,9 +106,7 @@ class ResetPasswordEndpoint(View):
# check if the token is valid for the user
if not PasswordResetTokenGenerator().check_token(user, token):
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INVALID_PASSWORD_TOKEN"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INVALID_PASSWORD_TOKEN"],
error_message="INVALID_PASSWORD_TOKEN",
)
params = exc.get_error_dict()
@@ -154,8 +125,7 @@ class ResetPasswordEndpoint(View):
)
url = urljoin(
base_host(request=request, is_app=True),
- "accounts/reset-password?"
- + urlencode(exc.get_error_dict()),
+ "accounts/reset-password?" + urlencode(exc.get_error_dict()),
)
return HttpResponseRedirect(url)
@@ -168,8 +138,7 @@ class ResetPasswordEndpoint(View):
)
url = urljoin(
base_host(request=request, is_app=True),
- "accounts/reset-password?"
- + urlencode(exc.get_error_dict()),
+ "accounts/reset-password?" + urlencode(exc.get_error_dict()),
)
return HttpResponseRedirect(url)
@@ -185,9 +154,7 @@ class ResetPasswordEndpoint(View):
return HttpResponseRedirect(url)
except DjangoUnicodeDecodeError:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "EXPIRED_PASSWORD_TOKEN"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["EXPIRED_PASSWORD_TOKEN"],
error_message="EXPIRED_PASSWORD_TOKEN",
)
url = urljoin(
diff --git a/apiserver/plane/authentication/views/app/signout.py b/apiserver/plane/authentication/views/app/signout.py
index 260a89a8d..b8019dac1 100644
--- a/apiserver/plane/authentication/views/app/signout.py
+++ b/apiserver/plane/authentication/views/app/signout.py
@@ -10,7 +10,6 @@ from plane.db.models import User
class SignOutAuthEndpoint(View):
-
def post(self, request):
# Get user
try:
@@ -20,10 +19,6 @@ class SignOutAuthEndpoint(View):
user.save()
# Log the user out
logout(request)
- return HttpResponseRedirect(
- base_host(request=request, is_app=True)
- )
+ return HttpResponseRedirect(base_host(request=request, is_app=True))
except Exception:
- return HttpResponseRedirect(
- base_host(request=request, is_app=True)
- )
+ return HttpResponseRedirect(base_host(request=request, is_app=True))
diff --git a/apiserver/plane/authentication/views/common.py b/apiserver/plane/authentication/views/common.py
index 3e95d6ed8..cdcf6bc96 100644
--- a/apiserver/plane/authentication/views/common.py
+++ b/apiserver/plane/authentication/views/common.py
@@ -9,9 +9,7 @@ from rest_framework.views import APIView
from zxcvbn import zxcvbn
## Module imports
-from plane.app.serializers import (
- UserSerializer,
-)
+from plane.app.serializers import UserSerializer
from plane.authentication.utils.login import user_login
from plane.db.models import User
from plane.authentication.adapter.error import (
@@ -22,24 +20,24 @@ from django.middleware.csrf import get_token
from plane.utils.cache import invalidate_cache
from plane.authentication.utils.host import base_host
-class CSRFTokenEndpoint(APIView):
- permission_classes = [
- AllowAny,
- ]
+class CSRFTokenEndpoint(APIView):
+ permission_classes = [AllowAny]
def get(self, request):
# Generate a CSRF token
csrf_token = get_token(request)
# Return the CSRF token in a JSON response
- return Response(
- {"csrf_token": str(csrf_token)}, status=status.HTTP_200_OK
- )
+ return Response({"csrf_token": str(csrf_token)}, status=status.HTTP_200_OK)
def csrf_failure(request, reason=""):
"""Custom CSRF failure view"""
- return render(request, "csrf_failure.html", {"reason": reason, "root_url": base_host(request=request)})
+ return render(
+ request,
+ "csrf_failure.html",
+ {"reason": reason, "root_url": base_host(request=request)},
+ )
class ChangePasswordEndpoint(APIView):
@@ -55,23 +53,15 @@ class ChangePasswordEndpoint(APIView):
error_message="MISSING_PASSWORD",
payload={"error": "Old or new password is missing"},
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
if not user.check_password(old_password):
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INCORRECT_OLD_PASSWORD"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INCORRECT_OLD_PASSWORD"],
error_message="INCORRECT_OLD_PASSWORD",
payload={"error": "Old password is not correct"},
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
# check the password score
results = zxcvbn(new_password)
@@ -80,10 +70,7 @@ class ChangePasswordEndpoint(APIView):
error_code=AUTHENTICATION_ERROR_CODES["INVALID_NEW_PASSWORD"],
error_message="INVALID_NEW_PASSWORD",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
# set_password also hashes the password that the user will get
user.set_password(new_password)
@@ -91,13 +78,11 @@ class ChangePasswordEndpoint(APIView):
user.save()
user_login(user=user, request=request, is_app=True)
return Response(
- {"message": "Password updated successfully"},
- status=status.HTTP_200_OK,
+ {"message": "Password updated successfully"}, status=status.HTTP_200_OK
)
class SetUserPasswordEndpoint(APIView):
-
@invalidate_cache("/api/users/me/")
def post(self, request):
user = User.objects.get(pk=request.user.id)
@@ -112,10 +97,7 @@ class SetUserPasswordEndpoint(APIView):
"error": "Your password is already set please change your password from profile"
},
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
# Check password validation
if not password:
@@ -123,10 +105,7 @@ class SetUserPasswordEndpoint(APIView):
error_code=AUTHENTICATION_ERROR_CODES["INVALID_PASSWORD"],
error_message="INVALID_PASSWORD",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
results = zxcvbn(password)
if results["score"] < 3:
@@ -134,10 +113,7 @@ class SetUserPasswordEndpoint(APIView):
error_code=AUTHENTICATION_ERROR_CODES["INVALID_PASSWORD"],
error_message="INVALID_PASSWORD",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
# Set the user password
user.set_password(password)
diff --git a/apiserver/plane/authentication/views/space/check.py b/apiserver/plane/authentication/views/space/check.py
index 560ae0e31..9b4d8aa56 100644
--- a/apiserver/plane/authentication/views/space/check.py
+++ b/apiserver/plane/authentication/views/space/check.py
@@ -23,36 +23,23 @@ from plane.license.utils.instance_value import get_configuration_value
class EmailCheckSpaceEndpoint(APIView):
+ permission_classes = [AllowAny]
- permission_classes = [
- AllowAny,
- ]
-
- throttle_classes = [
- AuthenticationThrottle,
- ]
+ throttle_classes = [AuthenticationThrottle]
def post(self, request):
# Check instance configuration
instance = Instance.objects.first()
if instance is None or not instance.is_setup_done:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
(EMAIL_HOST, ENABLE_MAGIC_LINK_LOGIN) = get_configuration_value(
[
- {
- "key": "EMAIL_HOST",
- "default": os.environ.get("EMAIL_HOST", ""),
- },
+ {"key": "EMAIL_HOST", "default": os.environ.get("EMAIL_HOST", "")},
{
"key": "ENABLE_MAGIC_LINK_LOGIN",
"default": os.environ.get("ENABLE_MAGIC_LINK_LOGIN", "1"),
@@ -71,10 +58,7 @@ class EmailCheckSpaceEndpoint(APIView):
error_code=AUTHENTICATION_ERROR_CODES["EMAIL_REQUIRED"],
error_message="EMAIL_REQUIRED",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
# Validate email
try:
@@ -84,10 +68,7 @@ class EmailCheckSpaceEndpoint(APIView):
error_code=AUTHENTICATION_ERROR_CODES["INVALID_EMAIL"],
error_message="INVALID_EMAIL",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
# Check if a user already exists with the given email
existing_user = User.objects.filter(email=email).first()
diff --git a/apiserver/plane/authentication/views/space/email.py b/apiserver/plane/authentication/views/space/email.py
index 4329ed26d..278cdf80b 100644
--- a/apiserver/plane/authentication/views/space/email.py
+++ b/apiserver/plane/authentication/views/space/email.py
@@ -20,7 +20,6 @@ from plane.authentication.adapter.error import (
class SignInAuthSpaceEndpoint(View):
-
def post(self, request):
next_path = request.POST.get("next_path")
# Check instance configuration
@@ -28,9 +27,7 @@ class SignInAuthSpaceEndpoint(View):
if instance is None or not instance.is_setup_done:
# Redirection params
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
params = exc.get_error_dict()
@@ -108,7 +105,6 @@ class SignInAuthSpaceEndpoint(View):
class SignUpAuthSpaceEndpoint(View):
-
def post(self, request):
next_path = request.POST.get("next_path")
# Check instance configuration
@@ -116,9 +112,7 @@ class SignUpAuthSpaceEndpoint(View):
if instance is None or not instance.is_setup_done:
# Redirection params
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
params = exc.get_error_dict()
diff --git a/apiserver/plane/authentication/views/space/github.py b/apiserver/plane/authentication/views/space/github.py
index 711f7eaa7..1d9d1d4ee 100644
--- a/apiserver/plane/authentication/views/space/github.py
+++ b/apiserver/plane/authentication/views/space/github.py
@@ -18,7 +18,6 @@ from plane.authentication.adapter.error import (
class GitHubOauthInitiateSpaceEndpoint(View):
-
def get(self, request):
# Get host and next path
request.session["host"] = base_host(request=request, is_space=True)
@@ -30,9 +29,7 @@ class GitHubOauthInitiateSpaceEndpoint(View):
instance = Instance.objects.first()
if instance is None or not instance.is_setup_done:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
params = exc.get_error_dict()
@@ -56,7 +53,6 @@ class GitHubOauthInitiateSpaceEndpoint(View):
class GitHubCallbackSpaceEndpoint(View):
-
def get(self, request):
code = request.GET.get("code")
state = request.GET.get("state")
@@ -65,9 +61,7 @@ class GitHubCallbackSpaceEndpoint(View):
if state != request.session.get("state", ""):
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GITHUB_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GITHUB_OAUTH_PROVIDER_ERROR"],
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
)
params = exc.get_error_dict()
@@ -78,9 +72,7 @@ class GitHubCallbackSpaceEndpoint(View):
if not code:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GITHUB_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GITHUB_OAUTH_PROVIDER_ERROR"],
error_message="GITHUB_OAUTH_PROVIDER_ERROR",
)
params = exc.get_error_dict()
@@ -90,10 +82,7 @@ class GitHubCallbackSpaceEndpoint(View):
return HttpResponseRedirect(url)
try:
- provider = GitHubOAuthProvider(
- request=request,
- code=code,
- )
+ provider = GitHubOAuthProvider(request=request, code=code)
user = provider.authenticate()
# Login the user and record his device info
user_login(request=request, user=user, is_space=True)
diff --git a/apiserver/plane/authentication/views/space/gitlab.py b/apiserver/plane/authentication/views/space/gitlab.py
index 7ebd9d187..9fb314442 100644
--- a/apiserver/plane/authentication/views/space/gitlab.py
+++ b/apiserver/plane/authentication/views/space/gitlab.py
@@ -18,7 +18,6 @@ from plane.authentication.adapter.error import (
class GitLabOauthInitiateSpaceEndpoint(View):
-
def get(self, request):
# Get host and next path
request.session["host"] = base_host(request=request, is_space=True)
@@ -30,9 +29,7 @@ class GitLabOauthInitiateSpaceEndpoint(View):
instance = Instance.objects.first()
if instance is None or not instance.is_setup_done:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
params = exc.get_error_dict()
@@ -56,7 +53,6 @@ class GitLabOauthInitiateSpaceEndpoint(View):
class GitLabCallbackSpaceEndpoint(View):
-
def get(self, request):
code = request.GET.get("code")
state = request.GET.get("state")
@@ -65,9 +61,7 @@ class GitLabCallbackSpaceEndpoint(View):
if state != request.session.get("state", ""):
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GITLAB_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GITLAB_OAUTH_PROVIDER_ERROR"],
error_message="GITLAB_OAUTH_PROVIDER_ERROR",
)
params = exc.get_error_dict()
@@ -78,9 +72,7 @@ class GitLabCallbackSpaceEndpoint(View):
if not code:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GITLAB_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GITLAB_OAUTH_PROVIDER_ERROR"],
error_message="GITLAB_OAUTH_PROVIDER_ERROR",
)
params = exc.get_error_dict()
@@ -90,10 +82,7 @@ class GitLabCallbackSpaceEndpoint(View):
return HttpResponseRedirect(url)
try:
- provider = GitLabOAuthProvider(
- request=request,
- code=code,
- )
+ provider = GitLabOAuthProvider(request=request, code=code)
user = provider.authenticate()
# Login the user and record his device info
user_login(request=request, user=user, is_space=True)
diff --git a/apiserver/plane/authentication/views/space/google.py b/apiserver/plane/authentication/views/space/google.py
index 38a2b910a..479a18883 100644
--- a/apiserver/plane/authentication/views/space/google.py
+++ b/apiserver/plane/authentication/views/space/google.py
@@ -28,9 +28,7 @@ class GoogleOauthInitiateSpaceEndpoint(View):
instance = Instance.objects.first()
if instance is None or not instance.is_setup_done:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
params = exc.get_error_dict()
@@ -62,9 +60,7 @@ class GoogleCallbackSpaceEndpoint(View):
if state != request.session.get("state", ""):
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GOOGLE_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GOOGLE_OAUTH_PROVIDER_ERROR"],
error_message="GOOGLE_OAUTH_PROVIDER_ERROR",
)
params = exc.get_error_dict()
@@ -74,9 +70,7 @@ class GoogleCallbackSpaceEndpoint(View):
return HttpResponseRedirect(url)
if not code:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "GOOGLE_OAUTH_PROVIDER_ERROR"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["GOOGLE_OAUTH_PROVIDER_ERROR"],
error_message="GOOGLE_OAUTH_PROVIDER_ERROR",
)
params = exc.get_error_dict()
@@ -85,10 +79,7 @@ class GoogleCallbackSpaceEndpoint(View):
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
return HttpResponseRedirect(url)
try:
- provider = GoogleOAuthProvider(
- request=request,
- code=code,
- )
+ provider = GoogleOAuthProvider(request=request, code=code)
user = provider.authenticate()
# Login the user and record his device info
user_login(request=request, user=user, is_space=True)
diff --git a/apiserver/plane/authentication/views/space/magic.py b/apiserver/plane/authentication/views/space/magic.py
index 838039f96..e763aaa07 100644
--- a/apiserver/plane/authentication/views/space/magic.py
+++ b/apiserver/plane/authentication/views/space/magic.py
@@ -13,9 +13,7 @@ from rest_framework.response import Response
from rest_framework.views import APIView
# Module imports
-from plane.authentication.provider.credentials.magic_code import (
- MagicCodeProvider,
-)
+from plane.authentication.provider.credentials.magic_code import MagicCodeProvider
from plane.authentication.utils.login import user_login
from plane.bgtasks.magic_link_code_task import magic_link
from plane.license.models import Instance
@@ -28,24 +26,17 @@ from plane.authentication.adapter.error import (
class MagicGenerateSpaceEndpoint(APIView):
-
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def post(self, request):
# Check if instance is configured
instance = Instance.objects.first()
if instance is None or not instance.is_setup_done:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
- return Response(
- exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
origin = base_host(request=request, is_space=True)
email = request.data.get("email", False)
@@ -59,16 +50,11 @@ class MagicGenerateSpaceEndpoint(APIView):
magic_link.delay(email, key, token, origin)
return Response({"key": str(key)}, status=status.HTTP_200_OK)
except AuthenticationException as e:
- return Response(
- e.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(e.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
class MagicSignInSpaceEndpoint(View):
-
def post(self, request):
-
# set the referer as session to redirect after login
code = request.POST.get("code", "").strip()
email = request.POST.get("email", "").strip().lower()
@@ -122,9 +108,7 @@ class MagicSignInSpaceEndpoint(View):
class MagicSignUpSpaceEndpoint(View):
-
def post(self, request):
-
# set the referer as session to redirect after login
code = request.POST.get("code", "").strip()
email = request.POST.get("email", "").strip().lower()
diff --git a/apiserver/plane/authentication/views/space/password_management.py b/apiserver/plane/authentication/views/space/password_management.py
index 3e0379b96..710d0db2f 100644
--- a/apiserver/plane/authentication/views/space/password_management.py
+++ b/apiserver/plane/authentication/views/space/password_management.py
@@ -14,11 +14,7 @@ from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.http import HttpResponseRedirect
-from django.utils.encoding import (
- DjangoUnicodeDecodeError,
- smart_bytes,
- smart_str,
-)
+from django.utils.encoding import DjangoUnicodeDecodeError, smart_bytes, smart_str
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
from django.views import View
@@ -43,13 +39,9 @@ def generate_password_token(user):
class ForgotPasswordSpaceEndpoint(APIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
- throttle_classes = [
- AuthenticationThrottle,
- ]
+ throttle_classes = [AuthenticationThrottle]
def post(self, request):
email = request.data.get("email")
@@ -58,33 +50,23 @@ class ForgotPasswordSpaceEndpoint(APIView):
instance = Instance.objects.first()
if instance is None or not instance.is_setup_done:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
- (EMAIL_HOST, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD) = (
- get_configuration_value(
- [
- {
- "key": "EMAIL_HOST",
- "default": os.environ.get("EMAIL_HOST"),
- },
- {
- "key": "EMAIL_HOST_USER",
- "default": os.environ.get("EMAIL_HOST_USER"),
- },
- {
- "key": "EMAIL_HOST_PASSWORD",
- "default": os.environ.get("EMAIL_HOST_PASSWORD"),
- },
- ]
- )
+ (EMAIL_HOST, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD) = get_configuration_value(
+ [
+ {"key": "EMAIL_HOST", "default": os.environ.get("EMAIL_HOST")},
+ {
+ "key": "EMAIL_HOST_USER",
+ "default": os.environ.get("EMAIL_HOST_USER"),
+ },
+ {
+ "key": "EMAIL_HOST_PASSWORD",
+ "default": os.environ.get("EMAIL_HOST_PASSWORD"),
+ },
+ ]
)
if not (EMAIL_HOST):
@@ -92,10 +74,7 @@ class ForgotPasswordSpaceEndpoint(APIView):
error_message="SMTP_NOT_CONFIGURED",
error_code=AUTHENTICATION_ERROR_CODES["SMTP_NOT_CONFIGURED"],
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
try:
validate_email(email)
@@ -104,10 +83,7 @@ class ForgotPasswordSpaceEndpoint(APIView):
error_code=AUTHENTICATION_ERROR_CODES["INVALID_EMAIL"],
error_message="INVALID_EMAIL",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
# Get the user
user = User.objects.filter(email=email).first()
@@ -127,14 +103,10 @@ class ForgotPasswordSpaceEndpoint(APIView):
error_code=AUTHENTICATION_ERROR_CODES["USER_DOES_NOT_EXIST"],
error_message="USER_DOES_NOT_EXIST",
)
- return Response(
- exc.get_error_dict(),
- status=status.HTTP_400_BAD_REQUEST,
- )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
class ResetPasswordSpaceEndpoint(View):
-
def post(self, request, uidb64, token):
try:
# Decode the id from the uidb64
@@ -144,9 +116,7 @@ class ResetPasswordSpaceEndpoint(View):
# check if the token is valid for the user
if not PasswordResetTokenGenerator().check_token(user, token):
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INVALID_PASSWORD_TOKEN"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INVALID_PASSWORD_TOKEN"],
error_message="INVALID_PASSWORD_TOKEN",
)
params = exc.get_error_dict()
@@ -178,14 +148,10 @@ class ResetPasswordSpaceEndpoint(View):
user.is_password_autoset = False
user.save()
- return HttpResponseRedirect(
- base_host(request=request, is_space=True)
- )
+ return HttpResponseRedirect(base_host(request=request, is_space=True))
except DjangoUnicodeDecodeError:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "EXPIRED_PASSWORD_TOKEN"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["EXPIRED_PASSWORD_TOKEN"],
error_message="EXPIRED_PASSWORD_TOKEN",
)
url = f"{base_host(request=request, is_space=True)}/accounts/reset-password/?{urlencode(exc.get_error_dict())}"
diff --git a/apiserver/plane/authentication/views/space/signout.py b/apiserver/plane/authentication/views/space/signout.py
index d3f29bd8d..babd18ee9 100644
--- a/apiserver/plane/authentication/views/space/signout.py
+++ b/apiserver/plane/authentication/views/space/signout.py
@@ -10,7 +10,6 @@ from plane.db.models import User
class SignOutAuthSpaceEndpoint(View):
-
def post(self, request):
next_path = request.POST.get("next_path")
diff --git a/apiserver/plane/bgtasks/analytic_plot_export.py b/apiserver/plane/bgtasks/analytic_plot_export.py
index 7e8630e65..0a335e5b5 100644
--- a/apiserver/plane/bgtasks/analytic_plot_export.py
+++ b/apiserver/plane/bgtasks/analytic_plot_export.py
@@ -106,10 +106,7 @@ def get_assignee_details(slug, filters):
),
),
# If `avatar_asset` is None, fall back to using `avatar` field directly
- When(
- assignees__avatar_asset__isnull=True,
- then="assignees__avatar",
- ),
+ When(assignees__avatar_asset__isnull=True, then="assignees__avatar"),
default=Value(None),
output_field=models.CharField(),
)
@@ -143,10 +140,7 @@ def get_label_details(slug, filters):
def get_state_details(slug, filters):
return (
- Issue.issue_objects.filter(
- workspace__slug=slug,
- **filters,
- )
+ Issue.issue_objects.filter(workspace__slug=slug, **filters)
.distinct("state_id")
.order_by("state_id")
.values("state_id", "state__name", "state__color")
@@ -163,10 +157,7 @@ def get_module_details(slug, filters):
)
.distinct("issue_module__module_id")
.order_by("issue_module__module_id")
- .values(
- "issue_module__module_id",
- "issue_module__module__name",
- )
+ .values("issue_module__module_id", "issue_module__module__name")
)
@@ -180,10 +171,7 @@ def get_cycle_details(slug, filters):
)
.distinct("issue_cycle__cycle_id")
.order_by("issue_cycle__cycle_id")
- .values(
- "issue_cycle__cycle_id",
- "issue_cycle__cycle__name",
- )
+ .values("issue_cycle__cycle_id", "issue_cycle__cycle__name")
)
@@ -209,9 +197,7 @@ def generate_segmented_rows(
):
segment_zero = list(
set(
- item.get("segment")
- for sublist in distribution.values()
- for item in sublist
+ item.get("segment") for sublist in distribution.values() for item in sublist
)
)
@@ -230,9 +216,7 @@ def generate_segmented_rows(
]
for segment in segment_zero:
- value = next(
- (x.get(key) for x in data if x.get("segment") == segment), "0"
- )
+ value = next((x.get(key) for x in data if x.get("segment") == segment), "0")
generated_row.append(value)
if x_axis == ASSIGNEE_ID:
@@ -251,12 +235,7 @@ def generate_segmented_rows(
if x_axis == LABEL_ID:
label = next(
- (
- lab
- for lab in label_details
- if str(lab[LABEL_ID]) == str(item)
- ),
- None,
+ (lab for lab in label_details if str(lab[LABEL_ID]) == str(item)), None
)
if label:
@@ -264,12 +243,7 @@ def generate_segmented_rows(
if x_axis == STATE_ID:
state = next(
- (
- sta
- for sta in state_details
- if str(sta[STATE_ID]) == str(item)
- ),
- None,
+ (sta for sta in state_details if str(sta[STATE_ID]) == str(item)), None
)
if state:
@@ -277,12 +251,7 @@ def generate_segmented_rows(
if x_axis == CYCLE_ID:
cycle = next(
- (
- cyc
- for cyc in cycle_details
- if str(cyc[CYCLE_ID]) == str(item)
- ),
- None,
+ (cyc for cyc in cycle_details if str(cyc[CYCLE_ID]) == str(item)), None
)
if cycle:
@@ -290,11 +259,7 @@ def generate_segmented_rows(
if x_axis == MODULE_ID:
module = next(
- (
- mod
- for mod in module_details
- if str(mod[MODULE_ID]) == str(item)
- ),
+ (mod for mod in module_details if str(mod[MODULE_ID]) == str(item)),
None,
)
@@ -321,12 +286,7 @@ def generate_segmented_rows(
if segmented == LABEL_ID:
for index, segm in enumerate(row_zero[2:]):
label = next(
- (
- lab
- for lab in label_details
- if str(lab[LABEL_ID]) == str(segm)
- ),
- None,
+ (lab for lab in label_details if str(lab[LABEL_ID]) == str(segm)), None
)
if label:
row_zero[index + 2] = label["labels__name"]
@@ -334,12 +294,7 @@ def generate_segmented_rows(
if segmented == STATE_ID:
for index, segm in enumerate(row_zero[2:]):
state = next(
- (
- sta
- for sta in state_details
- if str(sta[STATE_ID]) == str(segm)
- ),
- None,
+ (sta for sta in state_details if str(sta[STATE_ID]) == str(segm)), None
)
if state:
row_zero[index + 2] = state["state__name"]
@@ -347,12 +302,7 @@ def generate_segmented_rows(
if segmented == MODULE_ID:
for index, segm in enumerate(row_zero[2:]):
module = next(
- (
- mod
- for mod in label_details
- if str(mod[MODULE_ID]) == str(segm)
- ),
- None,
+ (mod for mod in label_details if str(mod[MODULE_ID]) == str(segm)), None
)
if module:
row_zero[index + 2] = module["issue_module__module__name"]
@@ -360,12 +310,7 @@ def generate_segmented_rows(
if segmented == CYCLE_ID:
for index, segm in enumerate(row_zero[2:]):
cycle = next(
- (
- cyc
- for cyc in cycle_details
- if str(cyc[CYCLE_ID]) == str(segm)
- ),
- None,
+ (cyc for cyc in cycle_details if str(cyc[CYCLE_ID]) == str(segm)), None
)
if cycle:
row_zero[index + 2] = cycle["issue_cycle__cycle__name"]
@@ -386,10 +331,7 @@ def generate_non_segmented_rows(
):
rows = []
for item, data in distribution.items():
- row = [
- item,
- data[0].get("count" if y_axis == "issue_count" else "estimate"),
- ]
+ row = [item, data[0].get("count" if y_axis == "issue_count" else "estimate")]
if x_axis == ASSIGNEE_ID:
assignee = next(
@@ -407,12 +349,7 @@ def generate_non_segmented_rows(
if x_axis == LABEL_ID:
label = next(
- (
- lab
- for lab in label_details
- if str(lab[LABEL_ID]) == str(item)
- ),
- None,
+ (lab for lab in label_details if str(lab[LABEL_ID]) == str(item)), None
)
if label:
@@ -420,12 +357,7 @@ def generate_non_segmented_rows(
if x_axis == STATE_ID:
state = next(
- (
- sta
- for sta in state_details
- if str(sta[STATE_ID]) == str(item)
- ),
- None,
+ (sta for sta in state_details if str(sta[STATE_ID]) == str(item)), None
)
if state:
@@ -433,12 +365,7 @@ def generate_non_segmented_rows(
if x_axis == CYCLE_ID:
cycle = next(
- (
- cyc
- for cyc in cycle_details
- if str(cyc[CYCLE_ID]) == str(item)
- ),
- None,
+ (cyc for cyc in cycle_details if str(cyc[CYCLE_ID]) == str(item)), None
)
if cycle:
@@ -446,11 +373,7 @@ def generate_non_segmented_rows(
if x_axis == MODULE_ID:
module = next(
- (
- mod
- for mod in module_details
- if str(mod[MODULE_ID]) == str(item)
- ),
+ (mod for mod in module_details if str(mod[MODULE_ID]) == str(item)),
None,
)
@@ -459,10 +382,7 @@ def generate_non_segmented_rows(
rows.append(tuple(row))
- row_zero = [
- row_mapping.get(x_axis, "X-Axis"),
- row_mapping.get(y_axis, "Y-Axis"),
- ]
+ row_zero = [row_mapping.get(x_axis, "X-Axis"), row_mapping.get(y_axis, "Y-Axis")]
return [tuple(row_zero)] + rows
diff --git a/apiserver/plane/bgtasks/deletion_task.py b/apiserver/plane/bgtasks/deletion_task.py
index b0b2a6eb2..0752272e3 100644
--- a/apiserver/plane/bgtasks/deletion_task.py
+++ b/apiserver/plane/bgtasks/deletion_task.py
@@ -10,9 +10,7 @@ from celery import shared_task
@shared_task
-def soft_delete_related_objects(
- app_label, model_name, instance_pk, using=None
-):
+def soft_delete_related_objects(app_label, model_name, instance_pk, using=None):
model_class = apps.get_model(app_label, model_name)
instance = model_class.all_objects.get(pk=instance_pk)
related_fields = instance._meta.get_fields()
@@ -29,9 +27,7 @@ def soft_delete_related_objects(
elif field.one_to_one:
related_object = getattr(instance, field.name)
related_objects = (
- [related_object]
- if related_object is not None
- else []
+ [related_object] if related_object is not None else []
)
for obj in related_objects:
@@ -49,7 +45,6 @@ def restore_related_objects(app_label, model_name, instance_pk, using=None):
@shared_task
def hard_delete():
-
from plane.db.models import (
Workspace,
Project,
diff --git a/apiserver/plane/bgtasks/dummy_data_task.py b/apiserver/plane/bgtasks/dummy_data_task.py
index 889286219..a3f95d0bc 100644
--- a/apiserver/plane/bgtasks/dummy_data_task.py
+++ b/apiserver/plane/bgtasks/dummy_data_task.py
@@ -51,11 +51,7 @@ def create_project(workspace, user_id):
)
# Add current member as project member
- _ = ProjectMember.objects.create(
- project=project,
- member_id=user_id,
- role=20,
- )
+ _ = ProjectMember.objects.create(project=project, member_id=user_id, role=20)
return project
@@ -88,24 +84,14 @@ def create_states(workspace, project, user_id):
"group": "backlog",
"default": True,
},
- {
- "name": "Todo",
- "color": "#3A3A3A",
- "sequence": 25000,
- "group": "unstarted",
- },
+ {"name": "Todo", "color": "#3A3A3A", "sequence": 25000, "group": "unstarted"},
{
"name": "In Progress",
"color": "#F59E0B",
"sequence": 35000,
"group": "started",
},
- {
- "name": "Done",
- "color": "#16A34A",
- "sequence": 45000,
- "group": "completed",
- },
+ {"name": "Done", "color": "#16A34A", "sequence": 45000, "group": "completed"},
{
"name": "Cancelled",
"color": "#EF4444",
@@ -177,8 +163,7 @@ def create_cycles(workspace, project, user_id, cycle_count):
# Ensure end_date is strictly after start_date if start_date is not None
while start_date is not None and (
- end_date <= start_date
- or (start_date, end_date) in used_date_ranges
+ end_date <= start_date or (start_date, end_date) in used_date_ranges
):
end_date = fake.date_this_year()
@@ -259,11 +244,7 @@ def create_pages(workspace, project, user_id, pages_count):
# Add Page to project
ProjectPage.objects.bulk_create(
[
- ProjectPage(
- page=page,
- project=project,
- workspace=workspace,
- )
+ ProjectPage(page=page, project=project, workspace=workspace)
for page in pages
],
batch_size=1000,
@@ -274,26 +255,16 @@ def create_page_labels(workspace, project, user_id, pages_count):
# labels
labels = Label.objects.filter(project=project).values_list("id", flat=True)
pages = random.sample(
- list(
- Page.objects.filter(projects__id=project.id).values_list(
- "id", flat=True
- )
- ),
+ list(Page.objects.filter(projects__id=project.id).values_list("id", flat=True)),
int(pages_count / 2),
)
# Bulk page labels
bulk_page_labels = []
for page in pages:
- for label in random.sample(
- list(labels), random.randint(0, len(labels) - 1)
- ):
+ for label in random.sample(list(labels), random.randint(0, len(labels) - 1)):
bulk_page_labels.append(
- PageLabel(
- page_id=page,
- label_id=label,
- workspace=workspace,
- )
+ PageLabel(page_id=page, label_id=label, workspace=workspace)
)
# Page labels
@@ -318,9 +289,7 @@ def create_issues(workspace, project, user_id, issue_count):
issues = []
# Get the maximum sequence_id
- last_id = IssueSequence.objects.filter(
- project=project,
- ).aggregate(
+ last_id = IssueSequence.objects.filter(project=project).aggregate(
largest=Max("sequence")
)["largest"]
@@ -328,8 +297,7 @@ def create_issues(workspace, project, user_id, issue_count):
# Get the maximum sort order
largest_sort_order = Issue.objects.filter(
- project=project,
- state_id=states[random.randint(0, len(states) - 1)],
+ project=project, state_id=states[random.randint(0, len(states) - 1)]
).aggregate(largest=Max("sort_order"))["largest"]
largest_sort_order = (
@@ -370,9 +338,7 @@ def create_issues(workspace, project, user_id, issue_count):
largest_sort_order = largest_sort_order + random.randint(0, 1000)
last_id = last_id + 1
- issues = Issue.objects.bulk_create(
- issues, ignore_conflicts=True, batch_size=1000
- )
+ issues = Issue.objects.bulk_create(issues, ignore_conflicts=True, batch_size=1000)
# Sequences
_ = IssueSequence.objects.bulk_create(
[
@@ -409,9 +375,7 @@ def create_issues(workspace, project, user_id, issue_count):
def create_intake_issues(workspace, project, user_id, intake_issue_count):
issues = create_issues(workspace, project, user_id, intake_issue_count)
intake, create = Intake.objects.get_or_create(
- name="Intake",
- project=project,
- is_default=True,
+ name="Intake", project=project, is_default=True
)
IntakeIssue.objects.bulk_create(
[
@@ -435,21 +399,18 @@ def create_intake_issues(workspace, project, user_id, intake_issue_count):
def create_issue_parent(workspace, project, user_id, issue_count):
-
parent_count = issue_count / 4
- parent_issues = Issue.objects.filter(project=project).values_list(
- "id", flat=True
- )[: int(parent_count)]
- sub_issues = Issue.objects.filter(project=project).exclude(
- pk__in=parent_issues
- )[: int(issue_count / 2)]
+ parent_issues = Issue.objects.filter(project=project).values_list("id", flat=True)[
+ : int(parent_count)
+ ]
+ sub_issues = Issue.objects.filter(project=project).exclude(pk__in=parent_issues)[
+ : int(issue_count / 2)
+ ]
bulk_sub_issues = []
for sub_issue in sub_issues:
- sub_issue.parent_id = parent_issues[
- random.randint(0, int(parent_count - 1))
- ]
+ sub_issue.parent_id = parent_issues[random.randint(0, int(parent_count - 1))]
Issue.objects.bulk_update(bulk_sub_issues, ["parent"], batch_size=1000)
@@ -460,9 +421,7 @@ def create_issue_assignees(workspace, project, user_id, issue_count):
"member_id", flat=True
)
issues = random.sample(
- list(
- Issue.objects.filter(project=project).values_list("id", flat=True)
- ),
+ list(Issue.objects.filter(project=project).values_list("id", flat=True)),
int(issue_count / 2),
)
@@ -496,24 +455,17 @@ def create_issue_labels(workspace, project, user_id, issue_count):
# ),
# int(issue_count / 2),
# )
- issues = list(
- Issue.objects.filter(project=project).values_list("id", flat=True)
- )
+ issues = list(Issue.objects.filter(project=project).values_list("id", flat=True))
shuffled_labels = list(labels)
# Bulk issue
bulk_issue_labels = []
for issue in issues:
random.shuffle(shuffled_labels)
- for label in random.sample(
- shuffled_labels, random.randint(0, 5)
- ):
+ for label in random.sample(shuffled_labels, random.randint(0, 5)):
bulk_issue_labels.append(
IssueLabel(
- issue_id=issue,
- label_id=label,
- project=project,
- workspace=workspace,
+ issue_id=issue, label_id=label, project=project, workspace=workspace
)
)
@@ -527,9 +479,7 @@ def create_cycle_issues(workspace, project, user_id, issue_count):
# assignees
cycles = Cycle.objects.filter(project=project).values_list("id", flat=True)
issues = random.sample(
- list(
- Issue.objects.filter(project=project).values_list("id", flat=True)
- ),
+ list(Issue.objects.filter(project=project).values_list("id", flat=True)),
int(issue_count / 2),
)
@@ -539,10 +489,7 @@ def create_cycle_issues(workspace, project, user_id, issue_count):
cycle = cycles[random.randint(0, len(cycles) - 1)]
bulk_cycle_issues.append(
CycleIssue(
- cycle_id=cycle,
- issue_id=issue,
- project=project,
- workspace=workspace,
+ cycle_id=cycle, issue_id=issue, project=project, workspace=workspace
)
)
@@ -554,18 +501,14 @@ def create_cycle_issues(workspace, project, user_id, issue_count):
def create_module_issues(workspace, project, user_id, issue_count):
# assignees
- modules = Module.objects.filter(project=project).values_list(
- "id", flat=True
- )
+ modules = Module.objects.filter(project=project).values_list("id", flat=True)
# issues = random.sample(
# list(
# Issue.objects.filter(project=project).values_list("id", flat=True)
# ),
# int(issue_count / 2),
# )
- issues = list(
- Issue.objects.filter(project=project).values_list("id", flat=True)
- )
+ issues = list(Issue.objects.filter(project=project).values_list("id", flat=True))
shuffled_modules = list(modules)
@@ -573,9 +516,7 @@ def create_module_issues(workspace, project, user_id, issue_count):
bulk_module_issues = []
for issue in issues:
random.shuffle(shuffled_modules)
- for module in random.sample(
- shuffled_modules, random.randint(0, 5)
- ):
+ for module in random.sample(shuffled_modules, random.randint(0, 5)):
bulk_module_issues.append(
ModuleIssue(
module_id=module,
@@ -610,9 +551,7 @@ def create_dummy_data(
project = create_project(workspace=workspace, user_id=user_id)
# create project members
- create_project_members(
- workspace=workspace, project=project, members=members
- )
+ create_project_members(workspace=workspace, project=project, members=members)
# Create states
create_states(workspace=workspace, project=project, user_id=user_id)
@@ -622,42 +561,27 @@ def create_dummy_data(
# create cycles
create_cycles(
- workspace=workspace,
- project=project,
- user_id=user_id,
- cycle_count=cycle_count,
+ workspace=workspace, project=project, user_id=user_id, cycle_count=cycle_count
)
# create modules
create_modules(
- workspace=workspace,
- project=project,
- user_id=user_id,
- module_count=module_count,
+ workspace=workspace, project=project, user_id=user_id, module_count=module_count
)
# create pages
create_pages(
- workspace=workspace,
- project=project,
- user_id=user_id,
- pages_count=pages_count,
+ workspace=workspace, project=project, user_id=user_id, pages_count=pages_count
)
# create page labels
create_page_labels(
- workspace=workspace,
- project=project,
- user_id=user_id,
- pages_count=pages_count,
+ workspace=workspace, project=project, user_id=user_id, pages_count=pages_count
)
# create issues
create_issues(
- workspace=workspace,
- project=project,
- user_id=user_id,
- issue_count=issue_count,
+ workspace=workspace, project=project, user_id=user_id, issue_count=issue_count
)
# create intake issues
@@ -670,42 +594,27 @@ def create_dummy_data(
# create issue parent
create_issue_parent(
- workspace=workspace,
- project=project,
- user_id=user_id,
- issue_count=issue_count,
+ workspace=workspace, project=project, user_id=user_id, issue_count=issue_count
)
# create issue assignees
create_issue_assignees(
- workspace=workspace,
- project=project,
- user_id=user_id,
- issue_count=issue_count,
+ workspace=workspace, project=project, user_id=user_id, issue_count=issue_count
)
# create issue labels
create_issue_labels(
- workspace=workspace,
- project=project,
- user_id=user_id,
- issue_count=issue_count,
+ workspace=workspace, project=project, user_id=user_id, issue_count=issue_count
)
# create cycle issues
create_cycle_issues(
- workspace=workspace,
- project=project,
- user_id=user_id,
- issue_count=issue_count,
+ workspace=workspace, project=project, user_id=user_id, issue_count=issue_count
)
# create module issues
create_module_issues(
- workspace=workspace,
- project=project,
- user_id=user_id,
- issue_count=issue_count,
+ workspace=workspace, project=project, user_id=user_id, issue_count=issue_count
)
return
diff --git a/apiserver/plane/bgtasks/email_notification_task.py b/apiserver/plane/bgtasks/email_notification_task.py
index f2db0de59..b0f75b5dc 100644
--- a/apiserver/plane/bgtasks/email_notification_task.py
+++ b/apiserver/plane/bgtasks/email_notification_task.py
@@ -75,9 +75,7 @@ def stack_email_notification():
for receiver_notification in receiver_notifications:
payload.setdefault(
receiver_notification.get("entity_identifier"), {}
- ).setdefault(
- str(receiver_notification.get("triggered_by_id")), []
- ).append(
+ ).setdefault(str(receiver_notification.get("triggered_by_id")), []).append(
receiver_notification.get("data")
)
# append processed notifications
@@ -184,11 +182,7 @@ def send_email_notification(
if acquire_lock(lock_id=lock_id):
# get the redis instance
ri = redis_instance()
- base_api = (
- ri.get(str(issue_id)).decode()
- if ri.get(str(issue_id))
- else None
- )
+ base_api = ri.get(str(issue_id)).decode() if ri.get(str(issue_id)) else None
# Skip if base api is not present
if not base_api:
@@ -283,9 +277,7 @@ def send_email_notification(
"name": issue.name,
"issue_url": f"{base_api}/{str(issue.project.workspace.slug)}/projects/{str(issue.project.id)}/issues/{str(issue.id)}",
},
- "receiver": {
- "email": receiver.email,
- },
+ "receiver": {"email": receiver.email},
"issue_url": f"{base_api}/{str(issue.project.workspace.slug)}/projects/{str(issue.project.id)}/issues/{str(issue.id)}",
"project_url": f"{base_api}/{str(issue.project.workspace.slug)}/projects/{str(issue.project.id)}/issues/",
"workspace": str(issue.project.workspace.slug),
@@ -333,9 +325,7 @@ def send_email_notification(
release_lock(lock_id=lock_id)
return
else:
- logging.getLogger("plane").info(
- "Duplicate email received skipping"
- )
+ logging.getLogger("plane").info("Duplicate email received skipping")
return
except (Issue.DoesNotExist, User.DoesNotExist):
release_lock(lock_id=lock_id)
diff --git a/apiserver/plane/bgtasks/event_tracking_task.py b/apiserver/plane/bgtasks/event_tracking_task.py
index 135ae1dd1..0629db93a 100644
--- a/apiserver/plane/bgtasks/event_tracking_task.py
+++ b/apiserver/plane/bgtasks/event_tracking_task.py
@@ -17,10 +17,7 @@ def posthogConfiguration():
"key": "POSTHOG_API_KEY",
"default": os.environ.get("POSTHOG_API_KEY", None),
},
- {
- "key": "POSTHOG_HOST",
- "default": os.environ.get("POSTHOG_HOST", None),
- },
+ {"key": "POSTHOG_HOST", "default": os.environ.get("POSTHOG_HOST", None)},
]
)
if POSTHOG_API_KEY and POSTHOG_HOST:
@@ -42,10 +39,7 @@ def auth_events(user, email, user_agent, ip, event_name, medium, first_time):
properties={
"event_id": uuid.uuid4().hex,
"user": {"email": email, "id": str(user)},
- "device_ctx": {
- "ip": ip,
- "user_agent": user_agent,
- },
+ "device_ctx": {"ip": ip, "user_agent": user_agent},
"medium": medium,
"first_time": first_time,
},
@@ -56,9 +50,7 @@ def auth_events(user, email, user_agent, ip, event_name, medium, first_time):
@shared_task
-def workspace_invite_event(
- user, email, user_agent, ip, event_name, accepted_from
-):
+def workspace_invite_event(user, email, user_agent, ip, event_name, accepted_from):
try:
POSTHOG_API_KEY, POSTHOG_HOST = posthogConfiguration()
@@ -70,10 +62,7 @@ def workspace_invite_event(
properties={
"event_id": uuid.uuid4().hex,
"user": {"email": email, "id": str(user)},
- "device_ctx": {
- "ip": ip,
- "user_agent": user_agent,
- },
+ "device_ctx": {"ip": ip, "user_agent": user_agent},
"accepted_from": accepted_from,
},
)
diff --git a/apiserver/plane/bgtasks/export_task.py b/apiserver/plane/bgtasks/export_task.py
index b88aad327..2b21d83d9 100644
--- a/apiserver/plane/bgtasks/export_task.py
+++ b/apiserver/plane/bgtasks/export_task.py
@@ -69,7 +69,9 @@ def create_zip_file(files):
def upload_to_s3(zip_file, workspace_id, token_id, slug):
- file_name = f"{workspace_id}/export-{slug}-{token_id[:6]}-{str(timezone.now().date())}.zip"
+ file_name = (
+ f"{workspace_id}/export-{slug}-{token_id[:6]}-{str(timezone.now().date())}.zip"
+ )
expires_in = 7 * 24 * 60 * 60
if settings.USE_MINIO:
@@ -98,10 +100,7 @@ def upload_to_s3(zip_file, workspace_id, token_id, slug):
presigned_url = presign_s3.generate_presigned_url(
"get_object",
- Params={
- "Bucket": settings.AWS_STORAGE_BUCKET_NAME,
- "Key": file_name,
- },
+ Params={"Bucket": settings.AWS_STORAGE_BUCKET_NAME, "Key": file_name},
ExpiresIn=expires_in,
)
else:
@@ -134,10 +133,7 @@ def upload_to_s3(zip_file, workspace_id, token_id, slug):
# Generate presigned url for the uploaded file
presigned_url = s3.generate_presigned_url(
"get_object",
- Params={
- "Bucket": settings.AWS_STORAGE_BUCKET_NAME,
- "Key": file_name,
- },
+ Params={"Bucket": settings.AWS_STORAGE_BUCKET_NAME, "Key": file_name},
ExpiresIn=expires_in,
)
@@ -164,8 +160,7 @@ def generate_table_row(issue):
issue["priority"],
(
f"{issue['created_by__first_name']} {issue['created_by__last_name']}"
- if issue["created_by__first_name"]
- and issue["created_by__last_name"]
+ if issue["created_by__first_name"] and issue["created_by__last_name"]
else ""
),
(
@@ -197,8 +192,7 @@ def generate_json_row(issue):
"Priority": issue["priority"],
"Created By": (
f"{issue['created_by__first_name']} {issue['created_by__last_name']}"
- if issue["created_by__first_name"]
- and issue["created_by__last_name"]
+ if issue["created_by__first_name"] and issue["created_by__last_name"]
else ""
),
"Assignee": (
@@ -208,17 +202,11 @@ def generate_json_row(issue):
),
"Labels": issue["labels__name"] if issue["labels__name"] else "",
"Cycle Name": issue["issue_cycle__cycle__name"],
- "Cycle Start Date": dateConverter(
- issue["issue_cycle__cycle__start_date"]
- ),
+ "Cycle Start Date": dateConverter(issue["issue_cycle__cycle__start_date"]),
"Cycle End Date": dateConverter(issue["issue_cycle__cycle__end_date"]),
"Module Name": issue["issue_module__module__name"],
- "Module Start Date": dateConverter(
- issue["issue_module__module__start_date"]
- ),
- "Module Target Date": dateConverter(
- issue["issue_module__module__target_date"]
- ),
+ "Module Start Date": dateConverter(issue["issue_module__module__start_date"]),
+ "Module Target Date": dateConverter(issue["issue_module__module__target_date"]),
"Created At": dateTimeConverter(issue["created_at"]),
"Updated At": dateTimeConverter(issue["updated_at"]),
"Completed At": dateTimeConverter(issue["completed_at"]),
@@ -257,11 +245,7 @@ def update_json_row(rows, row):
def update_table_row(rows, row):
matched_index = next(
- (
- index
- for index, existing_row in enumerate(rows)
- if existing_row[0] == row[0]
- ),
+ (index for index, existing_row in enumerate(rows) if existing_row[0] == row[0]),
None,
)
@@ -285,9 +269,7 @@ def generate_csv(header, project_id, issues, files):
"""
Generate CSV export for all the passed issues.
"""
- rows = [
- header,
- ]
+ rows = [header]
for issue in issues:
row = generate_table_row(issue)
update_table_row(rows, row)
@@ -314,9 +296,7 @@ def generate_xlsx(header, project_id, issues, files):
@shared_task
-def issue_export_task(
- provider, workspace_id, project_ids, token_id, multiple, slug
-):
+def issue_export_task(provider, workspace_id, project_ids, token_id, multiple, slug):
try:
exporter_instance = ExporterHistory.objects.get(token=token_id)
exporter_instance.status = "processing"
@@ -331,14 +311,9 @@ def issue_export_task(
project__project_projectmember__is_active=True,
project__archived_at__isnull=True,
)
- .select_related(
- "project", "workspace", "state", "parent", "created_by"
- )
+ .select_related("project", "workspace", "state", "parent", "created_by")
.prefetch_related(
- "assignees",
- "labels",
- "issue_cycle__cycle",
- "issue_module__module",
+ "assignees", "labels", "issue_cycle__cycle", "issue_module__module"
)
.values(
"id",
@@ -405,22 +380,12 @@ def issue_export_task(
issues = workspace_issues.filter(project__id=project_id)
exporter = EXPORTER_MAPPER.get(provider)
if exporter is not None:
- exporter(
- header,
- project_id,
- issues,
- files,
- )
+ exporter(header, project_id, issues, files)
else:
exporter = EXPORTER_MAPPER.get(provider)
if exporter is not None:
- exporter(
- header,
- workspace_id,
- workspace_issues,
- files,
- )
+ exporter(header, workspace_id, workspace_issues, files)
zip_buffer = create_zip_file(files)
upload_to_s3(zip_buffer, workspace_id, token_id, slug)
diff --git a/apiserver/plane/bgtasks/exporter_expired_task.py b/apiserver/plane/bgtasks/exporter_expired_task.py
index d408c6476..30b638c84 100644
--- a/apiserver/plane/bgtasks/exporter_expired_task.py
+++ b/apiserver/plane/bgtasks/exporter_expired_task.py
@@ -19,8 +19,7 @@ from plane.db.models import ExporterHistory
def delete_old_s3_link():
# Get a list of keys and IDs to process
expired_exporter_history = ExporterHistory.objects.filter(
- Q(url__isnull=False)
- & Q(created_at__lte=timezone.now() - timedelta(days=8))
+ Q(url__isnull=False) & Q(created_at__lte=timezone.now() - timedelta(days=8))
).values_list("key", "id")
if settings.USE_MINIO:
s3 = boto3.client(
@@ -43,12 +42,8 @@ def delete_old_s3_link():
# Delete object from S3
if file_name:
if settings.USE_MINIO:
- s3.delete_object(
- Bucket=settings.AWS_STORAGE_BUCKET_NAME, Key=file_name
- )
+ s3.delete_object(Bucket=settings.AWS_STORAGE_BUCKET_NAME, Key=file_name)
else:
- s3.delete_object(
- Bucket=settings.AWS_STORAGE_BUCKET_NAME, Key=file_name
- )
+ s3.delete_object(Bucket=settings.AWS_STORAGE_BUCKET_NAME, Key=file_name)
ExporterHistory.objects.filter(id=exporter_id).update(url=None)
diff --git a/apiserver/plane/bgtasks/file_asset_task.py b/apiserver/plane/bgtasks/file_asset_task.py
index e05ed6d37..b7b05df3b 100644
--- a/apiserver/plane/bgtasks/file_asset_task.py
+++ b/apiserver/plane/bgtasks/file_asset_task.py
@@ -19,9 +19,7 @@ def delete_unuploaded_file_asset():
FileAsset.objects.filter(
Q(
created_at__lt=timezone.now()
- - timedelta(
- days=int(os.environ.get("UNUPLOADED_ASSET_DELETE_DAYS", "7"))
- )
+ - timedelta(days=int(os.environ.get("UNUPLOADED_ASSET_DELETE_DAYS", "7")))
)
& Q(is_uploaded=False)
).delete()
diff --git a/apiserver/plane/bgtasks/forgot_password_task.py b/apiserver/plane/bgtasks/forgot_password_task.py
index f830eb1e2..6e8990ad1 100644
--- a/apiserver/plane/bgtasks/forgot_password_task.py
+++ b/apiserver/plane/bgtasks/forgot_password_task.py
@@ -18,7 +18,9 @@ from plane.utils.exception_logger import log_exception
@shared_task
def forgot_password(first_name, email, uidb64, token, current_site):
try:
- relative_link = f"/accounts/reset-password/?uidb64={uidb64}&token={token}&email={email}"
+ relative_link = (
+ f"/accounts/reset-password/?uidb64={uidb64}&token={token}&email={email}"
+ )
abs_url = str(current_site) + relative_link
(
@@ -39,9 +41,7 @@ def forgot_password(first_name, email, uidb64, token, current_site):
"email": email,
}
- html_content = render_to_string(
- "emails/auth/forgot_password.html", context
- )
+ html_content = render_to_string("emails/auth/forgot_password.html", context)
text_content = strip_tags(html_content)
diff --git a/apiserver/plane/bgtasks/issue_activities_task.py b/apiserver/plane/bgtasks/issue_activities_task.py
index 23239dddb..e0e2ea84e 100644
--- a/apiserver/plane/bgtasks/issue_activities_task.py
+++ b/apiserver/plane/bgtasks/issue_activities_task.py
@@ -147,12 +147,8 @@ def track_parent(
project_id=project_id,
workspace_id=workspace_id,
comment="updated the parent issue to",
- old_identifier=(
- old_parent.id if old_parent is not None else None
- ),
- new_identifier=(
- new_parent.id if new_parent is not None else None
- ),
+ old_identifier=(old_parent.id if old_parent is not None else None),
+ new_identifier=(new_parent.id if new_parent is not None else None),
epoch=epoch,
)
)
@@ -199,9 +195,7 @@ def track_state(
):
if current_instance.get("state_id") != requested_data.get("state_id"):
new_state = State.objects.get(pk=requested_data.get("state_id", None))
- old_state = State.objects.get(
- pk=current_instance.get("state_id", None)
- )
+ old_state = State.objects.get(pk=current_instance.get("state_id", None))
issue_activities.append(
IssueActivity(
@@ -232,9 +226,7 @@ def track_target_date(
issue_activities,
epoch,
):
- if current_instance.get("target_date") != requested_data.get(
- "target_date"
- ):
+ if current_instance.get("target_date") != requested_data.get("target_date"):
issue_activities.append(
IssueActivity(
issue_id=issue_id,
@@ -306,12 +298,8 @@ def track_labels(
issue_activities,
epoch,
):
- requested_labels = set(
- [str(lab) for lab in requested_data.get("label_ids", [])]
- )
- current_labels = set(
- [str(lab) for lab in current_instance.get("label_ids", [])]
- )
+ requested_labels = set([str(lab) for lab in requested_data.get("label_ids", [])])
+ current_labels = set([str(lab) for lab in current_instance.get("label_ids", [])])
added_labels = requested_labels - current_labels
dropped_labels = current_labels - requested_labels
@@ -445,9 +433,7 @@ def track_estimate_points(
issue_activities,
epoch,
):
- if current_instance.get("estimate_point") != requested_data.get(
- "estimate_point"
- ):
+ if current_instance.get("estimate_point") != requested_data.get("estimate_point"):
old_estimate = (
EstimatePoint.objects.filter(
pk=current_instance.get("estimate_point")
@@ -498,9 +484,7 @@ def track_archive_at(
issue_activities,
epoch,
):
- if current_instance.get("archived_at") != requested_data.get(
- "archived_at"
- ):
+ if current_instance.get("archived_at") != requested_data.get("archived_at"):
if requested_data.get("archived_at") is None:
issue_activities.append(
IssueActivity(
@@ -594,9 +578,7 @@ def create_issue_activity(
issue_activity.created_at = issue.created_at
issue_activity.actor_id = issue.created_by_id
issue_activity.save(update_fields=["created_at", "actor_id"])
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
if requested_data.get("assignee_ids") is not None:
track_assignees(
requested_data,
@@ -635,9 +617,7 @@ def update_issue_activity(
"closed_to": track_closed_to,
}
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
@@ -691,9 +671,7 @@ def create_comment_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
@@ -725,16 +703,12 @@ def update_comment_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
- if current_instance.get("comment_html") != requested_data.get(
- "comment_html"
- ):
+ if current_instance.get("comment_html") != requested_data.get("comment_html"):
issue_activities.append(
IssueActivity(
issue_id=issue_id,
@@ -788,18 +762,14 @@ def create_cycle_issue_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
# Updated Records:
updated_records = current_instance.get("updated_cycle_issues", [])
- created_records = json.loads(
- current_instance.get("created_cycle_issues", [])
- )
+ created_records = json.loads(current_instance.get("created_cycle_issues", []))
for updated_record in updated_records:
old_cycle = Cycle.objects.filter(
@@ -868,9 +838,7 @@ def delete_cycle_issue_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
@@ -911,9 +879,7 @@ def create_module_issue_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
module = Module.objects.filter(pk=requested_data.get("module_id")).first()
issue = Issue.objects.filter(pk=issue_id).first()
if issue:
@@ -946,9 +912,7 @@ def delete_module_issue_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
@@ -988,9 +952,7 @@ def create_link_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
@@ -1021,9 +983,7 @@ def update_link_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
@@ -1087,9 +1047,7 @@ def create_attachment_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
@@ -1144,9 +1102,7 @@ def create_issue_reaction_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
if requested_data and requested_data.get("reaction") is not None:
issue_reaction = (
IssueReaction.objects.filter(
@@ -1218,9 +1174,7 @@ def create_comment_reaction_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
if requested_data and requested_data.get("reaction") is not None:
comment_reaction_id, comment_id = (
CommentReaction.objects.filter(
@@ -1231,9 +1185,7 @@ def create_comment_reaction_activity(
.values_list("id", "comment__id")
.first()
)
- comment = IssueComment.objects.get(
- pk=comment_id, project_id=project_id
- )
+ comment = IssueComment.objects.get(pk=comment_id, project_id=project_id)
if (
comment is not None
and comment_reaction_id is not None
@@ -1307,9 +1259,7 @@ def create_issue_vote_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
if requested_data and requested_data.get("vote") is not None:
issue_activities.append(
IssueActivity(
@@ -1371,9 +1321,7 @@ def create_issue_relation_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
@@ -1395,9 +1343,7 @@ def create_issue_relation_activity(
epoch=epoch,
)
)
- inverse_relation = get_inverse_relation(
- requested_data.get("relation_type")
- )
+ inverse_relation = get_inverse_relation(requested_data.get("relation_type"))
issue = Issue.objects.get(pk=issue_id)
issue_activities.append(
IssueActivity(
@@ -1426,9 +1372,7 @@ def delete_issue_relation_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
@@ -1508,9 +1452,7 @@ def update_draft_issue_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
@@ -1577,9 +1519,7 @@ def create_intake_activity(
issue_activities,
epoch,
):
- requested_data = (
- json.loads(requested_data) if requested_data is not None else None
- )
+ requested_data = json.loads(requested_data) if requested_data is not None else None
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
@@ -1685,9 +1625,7 @@ def issue_activity(
)
# Save all the values to database
- issue_activities_created = IssueActivity.objects.bulk_create(
- issue_activities
- )
+ issue_activities_created = IssueActivity.objects.bulk_create(issue_activities)
# Post the updates to segway for integrations and webhooks
if len(issue_activities_created):
for activity in issue_activities_created:
@@ -1695,28 +1633,26 @@ def issue_activity(
event=(
"issue_comment"
if activity.field == "comment"
- else "intake_issue" if intake else "issue"
+ else "intake_issue"
+ if intake
+ else "issue"
),
event_id=(
activity.issue_comment_id
if activity.field == "comment"
- else intake if intake else activity.issue_id
+ else intake
+ if intake
+ else activity.issue_id
),
verb=activity.verb,
field=(
- "description"
- if activity.field == "comment"
- else activity.field
+ "description" if activity.field == "comment" else activity.field
),
old_value=(
- activity.old_value
- if activity.old_value != ""
- else None
+ activity.old_value if activity.old_value != "" else None
),
new_value=(
- activity.new_value
- if activity.new_value != ""
- else None
+ activity.new_value if activity.new_value != "" else None
),
actor_id=activity.actor_id,
current_site=origin,
@@ -1733,9 +1669,7 @@ def issue_activity(
project_id=project_id,
subscriber=subscriber,
issue_activities_created=json.dumps(
- IssueActivitySerializer(
- issue_activities_created, many=True
- ).data,
+ IssueActivitySerializer(issue_activities_created, many=True).data,
cls=DjangoJSONEncoder,
),
requested_data=requested_data,
diff --git a/apiserver/plane/bgtasks/issue_automation_task.py b/apiserver/plane/bgtasks/issue_automation_task.py
index 7e50106a0..68f3d32da 100644
--- a/apiserver/plane/bgtasks/issue_automation_task.py
+++ b/apiserver/plane/bgtasks/issue_automation_task.py
@@ -35,9 +35,7 @@ def archive_old_issues():
Q(
project=project_id,
archived_at__isnull=True,
- updated_at__lte=(
- timezone.now() - timedelta(days=archive_in * 30)
- ),
+ updated_at__lte=(timezone.now() - timedelta(days=archive_in * 30)),
state__group__in=["completed", "cancelled"],
),
Q(issue_cycle__isnull=True)
@@ -76,10 +74,7 @@ def archive_old_issues():
issue_activity.delay(
type="issue.activity.updated",
requested_data=json.dumps(
- {
- "archived_at": str(archive_at),
- "automation": True,
- }
+ {"archived_at": str(archive_at), "automation": True}
),
actor_id=str(project.created_by_id),
issue_id=issue.id,
@@ -113,9 +108,7 @@ def close_old_issues():
Q(
project=project_id,
archived_at__isnull=True,
- updated_at__lte=(
- timezone.now() - timedelta(days=close_in * 30)
- ),
+ updated_at__lte=(timezone.now() - timedelta(days=close_in * 30)),
state__group__in=["backlog", "unstarted", "started"],
),
Q(issue_cycle__isnull=True)
@@ -138,9 +131,7 @@ def close_old_issues():
# Check if Issues
if issues:
if project.default_state is None:
- close_state = State.objects.filter(
- group="cancelled"
- ).first()
+ close_state = State.objects.filter(group="cancelled").first()
else:
close_state = project.default_state
diff --git a/apiserver/plane/bgtasks/magic_link_code_task.py b/apiserver/plane/bgtasks/magic_link_code_task.py
index 7be0ae9f8..848ea623f 100644
--- a/apiserver/plane/bgtasks/magic_link_code_task.py
+++ b/apiserver/plane/bgtasks/magic_link_code_task.py
@@ -32,9 +32,7 @@ def magic_link(email, key, token, current_site):
subject = f"Your unique Plane login code is {token}"
context = {"code": token, "email": email}
- html_content = render_to_string(
- "emails/auth/magic_signin.html", context
- )
+ html_content = render_to_string("emails/auth/magic_signin.html", context)
text_content = strip_tags(html_content)
connection = get_connection(
diff --git a/apiserver/plane/bgtasks/notification_task.py b/apiserver/plane/bgtasks/notification_task.py
index 44f325015..49dc46cb6 100644
--- a/apiserver/plane/bgtasks/notification_task.py
+++ b/apiserver/plane/bgtasks/notification_task.py
@@ -40,9 +40,7 @@ def update_mentions_for_issue(issue, project, new_mentions, removed_mention):
)
IssueMention.objects.bulk_create(aggregated_issue_mentions, batch_size=100)
- IssueMention.objects.filter(
- issue=issue, mention__in=removed_mention
- ).delete()
+ IssueMention.objects.filter(issue=issue, mention__in=removed_mention).delete()
def get_new_mentions(requested_instance, current_instance):
@@ -89,14 +87,10 @@ def extract_mentions_as_subscribers(project_id, issue_id, mentions):
# If the particular mention has not already been subscribed to the issue, he must be sent the mentioned notification
if (
not IssueSubscriber.objects.filter(
- issue_id=issue_id,
- subscriber_id=mention_id,
- project_id=project_id,
+ issue_id=issue_id, subscriber_id=mention_id, project_id=project_id
).exists()
and not IssueAssignee.objects.filter(
- project_id=project_id,
- issue_id=issue_id,
- assignee_id=mention_id,
+ project_id=project_id, issue_id=issue_id, assignee_id=mention_id
).exists()
and not Issue.objects.filter(
project_id=project_id, pk=issue_id, created_by_id=mention_id
@@ -124,13 +118,9 @@ def extract_mentions(issue_instance):
data = json.loads(issue_instance)
html = data.get("description_html")
soup = BeautifulSoup(html, "html.parser")
- mention_tags = soup.find_all(
- "mention-component", attrs={"target": "users"}
- )
+ mention_tags = soup.find_all("mention-component", attrs={"target": "users"})
- mentions = [
- mention_tag["entity_identifier"] for mention_tag in mention_tags
- ]
+ mentions = [mention_tag["entity_identifier"] for mention_tag in mention_tags]
return list(set(mentions))
except Exception:
@@ -142,9 +132,7 @@ def extract_comment_mentions(comment_value):
try:
mentions = []
soup = BeautifulSoup(comment_value, "html.parser")
- mentions_tags = soup.find_all(
- "mention-component", attrs={"target": "users"}
- )
+ mentions_tags = soup.find_all("mention-component", attrs={"target": "users"})
for mention_tag in mentions_tags:
mentions.append(mention_tag["entity_identifier"])
return list(set(mentions))
@@ -167,13 +155,7 @@ def get_new_comment_mentions(new_value, old_value):
def create_mention_notification(
- project,
- notification_comment,
- issue,
- actor_id,
- mention_id,
- issue_id,
- activity,
+ project, notification_comment, issue, actor_id, mention_id, issue_id, activity
):
return Notification(
workspace=project.workspace,
@@ -259,25 +241,19 @@ def notifications(
# Get new mentions from the newer instance
new_mentions = get_new_mentions(
- requested_instance=requested_data,
- current_instance=current_instance,
+ requested_instance=requested_data, current_instance=current_instance
)
removed_mention = get_removed_mentions(
- requested_instance=requested_data,
- current_instance=current_instance,
+ requested_instance=requested_data, current_instance=current_instance
)
comment_mentions = []
all_comment_mentions = []
# Get New Subscribers from the mentions of the newer instance
- requested_mentions = extract_mentions(
- issue_instance=requested_data
- )
+ requested_mentions = extract_mentions(issue_instance=requested_data)
mention_subscribers = extract_mentions_as_subscribers(
- project_id=project_id,
- issue_id=issue_id,
- mentions=requested_mentions,
+ project_id=project_id, issue_id=issue_id, mentions=requested_mentions
)
for issue_activity in issue_activities_created:
@@ -299,9 +275,7 @@ def notifications(
comment_mentions = comment_mentions + new_comment_mentions
comment_mention_subscribers = extract_mentions_as_subscribers(
- project_id=project_id,
- issue_id=issue_id,
- mentions=all_comment_mentions,
+ project_id=project_id, issue_id=issue_id, mentions=all_comment_mentions
)
"""
We will not send subscription activity notification to the below mentioned user sets
@@ -312,13 +286,9 @@ def notifications(
# ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #
issue_subscribers = list(
- IssueSubscriber.objects.filter(
- project_id=project_id, issue_id=issue_id
- )
+ IssueSubscriber.objects.filter(project_id=project_id, issue_id=issue_id)
.exclude(
- subscriber_id__in=list(
- new_mentions + comment_mentions + [actor_id]
- )
+ subscriber_id__in=list(new_mentions + comment_mentions + [actor_id])
)
.values_list("subscriber", flat=True)
)
@@ -329,9 +299,7 @@ def notifications(
# add the user to issue subscriber
try:
_ = IssueSubscriber.objects.get_or_create(
- project_id=project_id,
- issue_id=issue_id,
- subscriber_id=actor_id,
+ project_id=project_id, issue_id=issue_id, subscriber_id=actor_id
)
except Exception:
pass
@@ -342,9 +310,7 @@ def notifications(
issue_id=issue_id, project_id=project_id
).values_list("assignee", flat=True)
- issue_subscribers = list(
- set(issue_subscribers) - {uuid.UUID(actor_id)}
- )
+ issue_subscribers = list(set(issue_subscribers) - {uuid.UUID(actor_id)})
for subscriber in issue_subscribers:
if issue.created_by_id and issue.created_by_id == subscriber:
@@ -357,16 +323,11 @@ def notifications(
else:
sender = "in_app:issue_activities:subscribed"
- preference = UserNotificationPreference.objects.get(
- user_id=subscriber
- )
+ preference = UserNotificationPreference.objects.get(user_id=subscriber)
for issue_activity in issue_activities_created:
# If activity done in blocking then blocked by email should not go
- if (
- issue_activity.get("issue_detail").get("id")
- != issue_id
- ):
+ if issue_activity.get("issue_detail").get("id") != issue_id:
continue
# Do not send notification for description update
@@ -391,8 +352,7 @@ def notifications(
):
send_email = True
elif (
- issue_activity.get("field") == "comment"
- and preference.comment
+ issue_activity.get("field") == "comment" and preference.comment
):
send_email = True
elif preference.property_change:
@@ -427,9 +387,7 @@ def notifications(
"issue": {
"id": str(issue_id),
"name": str(issue.name),
- "identifier": str(
- issue.project.identifier
- ),
+ "identifier": str(issue.project.identifier),
"sequence_id": issue.sequence_id,
"state_name": issue.state.name,
"state_group": issue.state.group,
@@ -438,35 +396,21 @@ def notifications(
"id": str(issue_activity.get("id")),
"verb": str(issue_activity.get("verb")),
"field": str(issue_activity.get("field")),
- "actor": str(
- issue_activity.get("actor_id")
- ),
- "new_value": str(
- issue_activity.get("new_value")
- ),
- "old_value": str(
- issue_activity.get("old_value")
- ),
+ "actor": str(issue_activity.get("actor_id")),
+ "new_value": str(issue_activity.get("new_value")),
+ "old_value": str(issue_activity.get("old_value")),
"issue_comment": str(
issue_comment.comment_stripped
if issue_comment is not None
else ""
),
"old_identifier": (
- str(
- issue_activity.get(
- "old_identifier"
- )
- )
+ str(issue_activity.get("old_identifier"))
if issue_activity.get("old_identifier")
else None
),
"new_identifier": (
- str(
- issue_activity.get(
- "new_identifier"
- )
- )
+ str(issue_activity.get("new_identifier"))
if issue_activity.get("new_identifier")
else None
),
@@ -486,9 +430,7 @@ def notifications(
"issue": {
"id": str(issue_id),
"name": str(issue.name),
- "identifier": str(
- issue.project.identifier
- ),
+ "identifier": str(issue.project.identifier),
"project_id": str(issue.project.id),
"workspace_slug": str(
issue.project.workspace.slug
@@ -499,15 +441,9 @@ def notifications(
},
"issue_activity": {
"id": str(issue_activity.get("id")),
- "verb": str(
- issue_activity.get("verb")
- ),
- "field": str(
- issue_activity.get("field")
- ),
- "actor": str(
- issue_activity.get("actor_id")
- ),
+ "verb": str(issue_activity.get("verb")),
+ "field": str(issue_activity.get("field")),
+ "actor": str(issue_activity.get("actor_id")),
"new_value": str(
issue_activity.get("new_value")
),
@@ -520,25 +456,13 @@ def notifications(
else ""
),
"old_identifier": (
- str(
- issue_activity.get(
- "old_identifier"
- )
- )
- if issue_activity.get(
- "old_identifier"
- )
+ str(issue_activity.get("old_identifier"))
+ if issue_activity.get("old_identifier")
else None
),
"new_identifier": (
- str(
- issue_activity.get(
- "new_identifier"
- )
- )
- if issue_activity.get(
- "new_identifier"
- )
+ str(issue_activity.get("new_identifier"))
+ if issue_activity.get("new_identifier")
else None
),
"activity_time": issue_activity.get(
@@ -594,26 +518,18 @@ def notifications(
"issue": {
"id": str(issue_id),
"name": str(issue.name),
- "identifier": str(
- issue.project.identifier
- ),
+ "identifier": str(issue.project.identifier),
"sequence_id": issue.sequence_id,
"state_name": issue.state.name,
"state_group": issue.state.group,
- "project_id": str(
- issue.project.id
- ),
+ "project_id": str(issue.project.id),
"workspace_slug": str(
issue.project.workspace.slug
),
},
"issue_activity": {
- "id": str(
- issue_activity.get("id")
- ),
- "verb": str(
- issue_activity.get("verb")
- ),
+ "id": str(issue_activity.get("id")),
+ "verb": str(issue_activity.get("verb")),
"field": str("mention"),
"actor": str(
issue_activity.get("actor_id")
@@ -626,24 +542,16 @@ def notifications(
),
"old_identifier": (
str(
- issue_activity.get(
- "old_identifier"
- )
- )
- if issue_activity.get(
- "old_identifier"
+ issue_activity.get("old_identifier")
)
+ if issue_activity.get("old_identifier")
else None
),
"new_identifier": (
str(
- issue_activity.get(
- "new_identifier"
- )
- )
- if issue_activity.get(
- "new_identifier"
+ issue_activity.get("new_identifier")
)
+ if issue_activity.get("new_identifier")
else None
),
"activity_time": issue_activity.get(
@@ -679,9 +587,7 @@ def notifications(
"issue": {
"id": str(issue_id),
"name": str(issue.name),
- "identifier": str(
- issue.project.identifier
- ),
+ "identifier": str(issue.project.identifier),
"sequence_id": issue.sequence_id,
"state_name": issue.state.name,
"state_group": issue.state.group,
@@ -695,32 +601,16 @@ def notifications(
"verb": str(last_activity.verb),
"field": str(last_activity.field),
"actor": str(last_activity.actor_id),
- "new_value": str(
- last_activity.new_value
- ),
- "old_value": str(
- last_activity.old_value
- ),
+ "new_value": str(last_activity.new_value),
+ "old_value": str(last_activity.old_value),
"old_identifier": (
- str(
- issue_activity.get(
- "old_identifier"
- )
- )
- if issue_activity.get(
- "old_identifier"
- )
+ str(issue_activity.get("old_identifier"))
+ if issue_activity.get("old_identifier")
else None
),
"new_identifier": (
- str(
- issue_activity.get(
- "new_identifier"
- )
- )
- if issue_activity.get(
- "new_identifier"
- )
+ str(issue_activity.get("new_identifier"))
+ if issue_activity.get("new_identifier")
else None
),
},
@@ -738,9 +628,7 @@ def notifications(
"issue": {
"id": str(issue_id),
"name": str(issue.name),
- "identifier": str(
- issue.project.identifier
- ),
+ "identifier": str(issue.project.identifier),
"sequence_id": issue.sequence_id,
"state_name": issue.state.name,
"state_group": issue.state.group,
@@ -749,35 +637,21 @@ def notifications(
"id": str(last_activity.id),
"verb": str(last_activity.verb),
"field": "mention",
- "actor": str(
- last_activity.actor_id
- ),
- "new_value": str(
- last_activity.new_value
- ),
- "old_value": str(
- last_activity.old_value
- ),
+ "actor": str(last_activity.actor_id),
+ "new_value": str(last_activity.new_value),
+ "old_value": str(last_activity.old_value),
"old_identifier": (
str(
- issue_activity.get(
- "old_identifier"
- )
- )
- if issue_activity.get(
- "old_identifier"
+ issue_activity.get("old_identifier")
)
+ if issue_activity.get("old_identifier")
else None
),
"new_identifier": (
str(
- issue_activity.get(
- "new_identifier"
- )
- )
- if issue_activity.get(
- "new_identifier"
+ issue_activity.get("new_identifier")
)
+ if issue_activity.get("new_identifier")
else None
),
"activity_time": str(
@@ -817,27 +691,17 @@ def notifications(
"state_group": issue.state.group,
},
"issue_activity": {
- "id": str(
- issue_activity.get("id")
- ),
- "verb": str(
- issue_activity.get("verb")
- ),
+ "id": str(issue_activity.get("id")),
+ "verb": str(issue_activity.get("verb")),
"field": str("mention"),
"actor": str(
- issue_activity.get(
- "actor_id"
- )
+ issue_activity.get("actor_id")
),
"new_value": str(
- issue_activity.get(
- "new_value"
- )
+ issue_activity.get("new_value")
),
"old_value": str(
- issue_activity.get(
- "old_value"
- )
+ issue_activity.get("old_value")
),
"old_identifier": (
str(
@@ -878,9 +742,7 @@ def notifications(
removed_mention=removed_mention,
)
# Bulk create notifications
- Notification.objects.bulk_create(
- bulk_notifications, batch_size=100
- )
+ Notification.objects.bulk_create(bulk_notifications, batch_size=100)
EmailNotificationLog.objects.bulk_create(
bulk_email_logs, batch_size=100, ignore_conflicts=True
)
diff --git a/apiserver/plane/bgtasks/page_version_task.py b/apiserver/plane/bgtasks/page_version_task.py
index 628fe62b7..7a5f94c9e 100644
--- a/apiserver/plane/bgtasks/page_version_task.py
+++ b/apiserver/plane/bgtasks/page_version_task.py
@@ -10,20 +10,14 @@ from plane.utils.exception_logger import log_exception
@shared_task
-def page_version(
- page_id,
- existing_instance,
- user_id,
-):
+def page_version(page_id, existing_instance, user_id):
try:
# Get the page
page = Page.objects.get(id=page_id)
# Get the current instance
current_instance = (
- json.loads(existing_instance)
- if existing_instance is not None
- else {}
+ json.loads(existing_instance) if existing_instance is not None else {}
)
# Create a version if description_html is updated
diff --git a/apiserver/plane/bgtasks/recent_visited_task.py b/apiserver/plane/bgtasks/recent_visited_task.py
index 9569abf5e..e8e3eb60f 100644
--- a/apiserver/plane/bgtasks/recent_visited_task.py
+++ b/apiserver/plane/bgtasks/recent_visited_task.py
@@ -10,9 +10,7 @@ from plane.utils.exception_logger import log_exception
@shared_task
-def recent_visited_task(
- entity_name, entity_identifier, user_id, project_id, slug
-):
+def recent_visited_task(entity_name, entity_identifier, user_id, project_id, slug):
try:
workspace = Workspace.objects.get(slug=slug)
recent_visited = UserRecentVisit.objects.filter(
@@ -27,7 +25,6 @@ def recent_visited_task(
recent_visited.visited_at = timezone.now()
recent_visited.save(update_fields=["visited_at"])
else:
-
recent_visited_count = UserRecentVisit.objects.filter(
user_id=user_id, workspace_id=workspace.id
).count()
@@ -51,9 +48,7 @@ def recent_visited_task(
)
recent_activity.created_by_id = user_id
recent_activity.updated_by_id = user_id
- recent_activity.save(
- update_fields=["created_by_id", "updated_by_id"]
- )
+ recent_activity.save(update_fields=["created_by_id", "updated_by_id"])
return
except Exception as e:
diff --git a/apiserver/plane/bgtasks/user_activation_email_task.py b/apiserver/plane/bgtasks/user_activation_email_task.py
index 2fdfc4ddb..23f0e1d01 100644
--- a/apiserver/plane/bgtasks/user_activation_email_task.py
+++ b/apiserver/plane/bgtasks/user_activation_email_task.py
@@ -22,15 +22,10 @@ def user_activation_email(current_site, user_id):
user = User.objects.get(id=user_id)
subject = f"{user.first_name or user.display_name or user.email} has been activated on Plane"
- context = {
- "email": str(user.email),
- "profile_url": current_site + "/profile",
- }
+ context = {"email": str(user.email), "profile_url": current_site + "/profile"}
# Send email to user
- html_content = render_to_string(
- "emails/user/user_activation.html", context
- )
+ html_content = render_to_string("emails/user/user_activation.html", context)
text_content = strip_tags(html_content)
# Configure email connection from the database
diff --git a/apiserver/plane/bgtasks/user_deactivation_email_task.py b/apiserver/plane/bgtasks/user_deactivation_email_task.py
index fa8523d50..9425dc324 100644
--- a/apiserver/plane/bgtasks/user_deactivation_email_task.py
+++ b/apiserver/plane/bgtasks/user_deactivation_email_task.py
@@ -22,15 +22,10 @@ def user_deactivation_email(current_site, user_id):
user = User.objects.get(id=user_id)
subject = f"{user.first_name or user.display_name or user.email} has been deactivated on Plane"
- context = {
- "email": str(user.email),
- "login_url": current_site + "/login",
- }
+ context = {"email": str(user.email), "login_url": current_site + "/login"}
# Send email to user
- html_content = render_to_string(
- "emails/user/user_deactivation.html", context
- )
+ html_content = render_to_string("emails/user/user_deactivation.html", context)
text_content = strip_tags(html_content)
# Configure email connection from the database
diff --git a/apiserver/plane/bgtasks/webhook_task.py b/apiserver/plane/bgtasks/webhook_task.py
index 4670b084d..d5d8b0043 100644
--- a/apiserver/plane/bgtasks/webhook_task.py
+++ b/apiserver/plane/bgtasks/webhook_task.py
@@ -131,12 +131,7 @@ def webhook_task(self, webhook, slug, event, event_data, action, current_site):
headers["X-Plane-Signature"] = signature
# Send the webhook event
- response = requests.post(
- webhook.url,
- headers=headers,
- json=payload,
- timeout=30,
- )
+ response = requests.post(webhook.url, headers=headers, json=payload, timeout=30)
# Log the webhook request
WebhookLog.objects.create(
@@ -190,9 +185,7 @@ def webhook_task(self, webhook, slug, event, event_data, action, current_site):
@shared_task
-def send_webhook_deactivation_email(
- webhook_id, receiver_id, current_site, reason
-):
+def send_webhook_deactivation_email(webhook_id, receiver_id, current_site, reason):
# Get email configurations
(
EMAIL_HOST,
@@ -207,9 +200,7 @@ def send_webhook_deactivation_email(
receiver = User.objects.get(pk=receiver_id)
webhook = Webhook.objects.get(pk=webhook_id)
subject = "Webhook Deactivated"
- message = (
- f"Webhook {webhook.url} has been deactivated due to failed requests."
- )
+ message = f"Webhook {webhook.url} has been deactivated due to failed requests."
# Send the mail
context = {
@@ -256,14 +247,7 @@ def send_webhook_deactivation_email(
retry_jitter=True,
)
def webhook_send_task(
- self,
- webhook,
- slug,
- event,
- event_data,
- action,
- current_site,
- activity,
+ self, webhook, slug, event, event_data, action, current_site, activity
):
try:
webhook = Webhook.objects.get(id=webhook, workspace__slug=slug)
@@ -315,12 +299,7 @@ def webhook_send_task(
headers["X-Plane-Signature"] = signature
# Send the webhook event
- response = requests.post(
- webhook.url,
- headers=headers,
- json=payload,
- timeout=30,
- )
+ response = requests.post(webhook.url, headers=headers, json=payload, timeout=30)
# Log the webhook request
WebhookLog.objects.create(
@@ -408,10 +387,7 @@ def webhook_activity(
webhook=webhook.id,
slug=slug,
event=event,
- event_data=get_model_data(
- event=event,
- event_id=event_id,
- ),
+ event_data=get_model_data(event=event, event_id=event_id),
action=verb,
current_site=current_site,
activity={
@@ -436,13 +412,7 @@ def webhook_activity(
@shared_task
def model_activity(
- model_name,
- model_id,
- requested_data,
- current_instance,
- actor_id,
- slug,
- origin=None,
+ model_name, model_id, requested_data, current_instance, actor_id, slug, origin=None
):
"""Function takes in two json and computes differences between keys of both the json"""
if current_instance is None:
diff --git a/apiserver/plane/db/management/commands/clear_cache.py b/apiserver/plane/db/management/commands/clear_cache.py
index c1908eee7..c9189ca32 100644
--- a/apiserver/plane/db/management/commands/clear_cache.py
+++ b/apiserver/plane/db/management/commands/clear_cache.py
@@ -8,18 +8,14 @@ class Command(BaseCommand):
def add_arguments(self, parser):
# Positional argument
- parser.add_argument(
- "--key", type=str, nargs="?", help="Key to clear cache"
- )
+ parser.add_argument("--key", type=str, nargs="?", help="Key to clear cache")
def handle(self, *args, **options):
try:
if options["key"]:
cache.delete(options["key"])
self.stdout.write(
- self.style.SUCCESS(
- f"Cache Cleared for key: {options['key']}"
- )
+ self.style.SUCCESS(f"Cache Cleared for key: {options['key']}")
)
return
diff --git a/apiserver/plane/db/management/commands/create_bucket.py b/apiserver/plane/db/management/commands/create_bucket.py
index 9313b6b1c..838edd6c6 100644
--- a/apiserver/plane/db/management/commands/create_bucket.py
+++ b/apiserver/plane/db/management/commands/create_bucket.py
@@ -15,9 +15,7 @@ class Command(BaseCommand):
try:
s3_client = boto3.client(
"s3",
- endpoint_url=os.environ.get(
- "AWS_S3_ENDPOINT_URL"
- ), # MinIO endpoint
+ endpoint_url=os.environ.get("AWS_S3_ENDPOINT_URL"), # MinIO endpoint
aws_access_key_id=os.environ.get(
"AWS_ACCESS_KEY_ID"
), # MinIO access key
@@ -33,9 +31,7 @@ class Command(BaseCommand):
# Check if the bucket exists
s3_client.head_bucket(Bucket=bucket_name)
# If the bucket exists, print a success message
- self.stdout.write(
- self.style.SUCCESS(f"Bucket '{bucket_name}' exists.")
- )
+ self.stdout.write(self.style.SUCCESS(f"Bucket '{bucket_name}' exists."))
return
except ClientError as e:
error_code = int(e.response["Error"]["Code"])
@@ -58,9 +54,7 @@ class Command(BaseCommand):
# Handle the exception if the bucket creation fails
except ClientError as create_error:
self.stdout.write(
- self.style.ERROR(
- f"Failed to create bucket: {create_error}"
- )
+ self.style.ERROR(f"Failed to create bucket: {create_error}")
)
# Handle the exception if access to the bucket is forbidden
@@ -73,9 +67,7 @@ class Command(BaseCommand):
)
else:
# Another ClientError occurred
- self.stdout.write(
- self.style.ERROR(f"Failed to check bucket: {e}")
- )
+ self.stdout.write(self.style.ERROR(f"Failed to check bucket: {e}"))
except Exception as ex:
# Handle any other exception
self.stdout.write(self.style.ERROR(f"An error occurred: {ex}"))
diff --git a/apiserver/plane/db/management/commands/create_dummy_data.py b/apiserver/plane/db/management/commands/create_dummy_data.py
index 64637864d..3eedc390c 100644
--- a/apiserver/plane/db/management/commands/create_dummy_data.py
+++ b/apiserver/plane/db/management/commands/create_dummy_data.py
@@ -10,7 +10,6 @@ class Command(BaseCommand):
help = "Create dump issues, cycles etc. for a project in a given workspace"
def handle(self, *args: Any, **options: Any) -> str | None:
-
try:
workspace_name = input("Workspace Name: ")
workspace_slug = input("Workspace slug: ")
@@ -23,10 +22,7 @@ class Command(BaseCommand):
creator = input("Your email: ")
- if (
- creator == ""
- or not User.objects.filter(email=creator).exists()
- ):
+ if creator == "" or not User.objects.filter(email=creator).exists():
raise CommandError(
"User email is required and should have signed in plane"
)
@@ -37,23 +33,15 @@ class Command(BaseCommand):
members = members.split(",") if members != "" else []
# Create workspace
workspace = Workspace.objects.create(
- slug=workspace_slug,
- name=workspace_name,
- owner=user,
+ slug=workspace_slug, name=workspace_name, owner=user
)
# Create workspace member
- WorkspaceMember.objects.create(
- workspace=workspace, role=20, member=user
- )
+ WorkspaceMember.objects.create(workspace=workspace, role=20, member=user)
user_ids = User.objects.filter(email__in=members)
_ = WorkspaceMember.objects.bulk_create(
[
- WorkspaceMember(
- workspace=workspace,
- member=user_id,
- role=20,
- )
+ WorkspaceMember(workspace=workspace, member=user_id, role=20)
for user_id in user_ids
],
ignore_conflicts=True,
@@ -62,9 +50,7 @@ class Command(BaseCommand):
project_count = int(input("Number of projects to be created: "))
for i in range(project_count):
- print(
- f"Please provide the following details for project {i+1}:"
- )
+ print(f"Please provide the following details for project {i+1}:")
issue_count = int(input("Number of issues to be created: "))
cycle_count = int(input("Number of cycles to be created: "))
module_count = int(input("Number of modules to be created: "))
@@ -86,12 +72,8 @@ class Command(BaseCommand):
intake_issue_count=intake_issue_count,
)
- self.stdout.write(
- self.style.SUCCESS("Data is pushed to the queue")
- )
+ self.stdout.write(self.style.SUCCESS("Data is pushed to the queue"))
return
except Exception as e:
- self.stdout.write(
- self.style.ERROR(f"Command errored out {str(e)}")
- )
+ self.stdout.write(self.style.ERROR(f"Command errored out {str(e)}"))
return
diff --git a/apiserver/plane/db/management/commands/create_instance_admin.py b/apiserver/plane/db/management/commands/create_instance_admin.py
index 21f79c15e..8b957f7fc 100644
--- a/apiserver/plane/db/management/commands/create_instance_admin.py
+++ b/apiserver/plane/db/management/commands/create_instance_admin.py
@@ -11,12 +11,9 @@ class Command(BaseCommand):
def add_arguments(self, parser):
# Positional argument
- parser.add_argument(
- "admin_email", type=str, help="Instance Admin Email"
- )
+ parser.add_argument("admin_email", type=str, help="Instance Admin Email")
def handle(self, *args, **options):
-
admin_email = options.get("admin_email", False)
if not admin_email:
@@ -36,13 +33,9 @@ class Command(BaseCommand):
)
if not created:
- raise CommandError(
- "The provided email is already an instance admin."
- )
+ raise CommandError("The provided email is already an instance admin.")
- self.stdout.write(
- self.style.SUCCESS("Successfully created the admin")
- )
+ self.stdout.write(self.style.SUCCESS("Successfully created the admin"))
except Exception as e:
print(e)
raise CommandError("Failed to create the instance admin.")
diff --git a/apiserver/plane/db/management/commands/reset_password.py b/apiserver/plane/db/management/commands/reset_password.py
index 9c137d320..8ec472bfa 100644
--- a/apiserver/plane/db/management/commands/reset_password.py
+++ b/apiserver/plane/db/management/commands/reset_password.py
@@ -52,15 +52,11 @@ class Command(BaseCommand):
results = zxcvbn(password)
if results["score"] < 3:
- raise CommandError(
- "Password is too common please set a complex password"
- )
+ raise CommandError("Password is too common please set a complex password")
# Set user password
user.set_password(password)
user.is_password_autoset = False
user.save()
- self.stdout.write(
- self.style.SUCCESS("User password updated succesfully")
- )
+ self.stdout.write(self.style.SUCCESS("User password updated succesfully"))
diff --git a/apiserver/plane/db/management/commands/test_email.py b/apiserver/plane/db/management/commands/test_email.py
index facea7e9c..2ed20eeb3 100644
--- a/apiserver/plane/db/management/commands/test_email.py
+++ b/apiserver/plane/db/management/commands/test_email.py
@@ -53,9 +53,7 @@ class Command(BaseCommand):
subject=subject,
body=text_content,
from_email=EMAIL_FROM,
- to=[
- receiver_email,
- ],
+ to=[receiver_email],
connection=connection,
)
msg.attach_alternative(html_content, "text/html")
@@ -63,7 +61,5 @@ class Command(BaseCommand):
self.stdout.write(self.style.SUCCESS("Email successfully sent"))
except Exception as e:
self.stdout.write(
- self.style.ERROR(
- f"Error: Email could not be delivered due to {e}"
- )
+ self.style.ERROR(f"Error: Email could not be delivered due to {e}")
)
diff --git a/apiserver/plane/db/management/commands/update_bucket.py b/apiserver/plane/db/management/commands/update_bucket.py
index 4feddef2e..27eb5c83e 100644
--- a/apiserver/plane/db/management/commands/update_bucket.py
+++ b/apiserver/plane/db/management/commands/update_bucket.py
@@ -14,12 +14,8 @@ class Command(BaseCommand):
def get_s3_client(self):
s3_client = boto3.client(
"s3",
- endpoint_url=os.environ.get(
- "AWS_S3_ENDPOINT_URL"
- ), # MinIO endpoint
- aws_access_key_id=os.environ.get(
- "AWS_ACCESS_KEY_ID"
- ), # MinIO access key
+ endpoint_url=os.environ.get("AWS_S3_ENDPOINT_URL"), # MinIO endpoint
+ aws_access_key_id=os.environ.get("AWS_ACCESS_KEY_ID"), # MinIO access key
aws_secret_access_key=os.environ.get(
"AWS_SECRET_ACCESS_KEY"
), # MinIO secret key
@@ -64,9 +60,7 @@ class Command(BaseCommand):
# 3. Test s3:PutObject (attempt to upload an object)
try:
s3_client.put_object(
- Bucket=bucket_name,
- Key="test_permission_check.txt",
- Body=b"Test",
+ Bucket=bucket_name, Key="test_permission_check.txt", Body=b"Test"
)
permissions["s3:PutObject"] = True
# Clean up
@@ -78,9 +72,7 @@ class Command(BaseCommand):
# Clean up
try:
- s3_client.delete_object(
- Bucket=bucket_name, Key="test_permission_check.txt"
- )
+ s3_client.delete_object(Bucket=bucket_name, Key="test_permission_check.txt")
except ClientError:
self.stdout.write("Coudn't delete test object")
@@ -97,9 +89,7 @@ class Command(BaseCommand):
}
],
}
- s3_client.put_bucket_policy(
- Bucket=bucket_name, Policy=json.dumps(policy)
- )
+ s3_client.put_bucket_policy(Bucket=bucket_name, Policy=json.dumps(policy))
permissions["s3:PutBucketPolicy"] = True
except ClientError as e:
if e.response["Error"]["Code"] == "AccessDenied":
@@ -142,9 +132,7 @@ class Command(BaseCommand):
Bucket=bucket_name, Policy=json.dumps(bucket_policy)
)
# Print a success message
- self.stdout.write(
- "Bucket is private, but existing objects remain public."
- )
+ self.stdout.write("Bucket is private, but existing objects remain public.")
return
def handle(self, *args, **options):
@@ -177,9 +165,7 @@ class Command(BaseCommand):
else:
self.stdout.write(f"Error: {e}")
# If the bucket exists, print a success message
- self.stdout.write(
- self.style.SUCCESS(f"Bucket '{bucket_name}' exists.")
- )
+ self.stdout.write(self.style.SUCCESS(f"Bucket '{bucket_name}' exists."))
try:
# Check the permissions of the access key
@@ -192,9 +178,7 @@ class Command(BaseCommand):
try:
if all(permissions.values()):
self.stdout.write(
- self.style.SUCCESS(
- "Access key has the required permissions."
- )
+ self.style.SUCCESS("Access key has the required permissions.")
)
# Making the existing objects public
self.make_objects_public(bucket_name)
@@ -213,9 +197,7 @@ class Command(BaseCommand):
with open("permissions.json", "w") as f:
f.write(json.dumps(self.generate_bucket_policy(bucket_name)))
self.stdout.write(
- self.style.WARNING(
- "Permissions have been written to permissions.json."
- )
+ self.style.WARNING("Permissions have been written to permissions.json.")
)
return
except IOError as e:
diff --git a/apiserver/plane/db/mixins.py b/apiserver/plane/db/mixins.py
index 4d4cee978..b198de121 100644
--- a/apiserver/plane/db/mixins.py
+++ b/apiserver/plane/db/mixins.py
@@ -9,13 +9,8 @@ from plane.bgtasks.deletion_task import soft_delete_related_objects
class TimeAuditModel(models.Model):
"""To path when the record was created and last modified"""
- created_at = models.DateTimeField(
- auto_now_add=True,
- verbose_name="Created At",
- )
- updated_at = models.DateTimeField(
- auto_now=True, verbose_name="Last Modified At"
- )
+ created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created At")
+ updated_at = models.DateTimeField(auto_now=True, verbose_name="Last Modified At")
class Meta:
abstract = True
@@ -61,11 +56,7 @@ class SoftDeletionManager(models.Manager):
class SoftDeleteModel(models.Model):
"""To soft delete records"""
- deleted_at = models.DateTimeField(
- verbose_name="Deleted At",
- null=True,
- blank=True,
- )
+ deleted_at = models.DateTimeField(verbose_name="Deleted At", null=True, blank=True)
objects = SoftDeletionManager()
all_objects = models.Manager()
@@ -80,10 +71,7 @@ class SoftDeleteModel(models.Model):
self.save(using=using)
soft_delete_related_objects.delay(
- self._meta.app_label,
- self._meta.model_name,
- self.pk,
- using=using,
+ self._meta.app_label, self._meta.model_name, self.pk, using=using
)
else:
diff --git a/apiserver/plane/db/models/__init__.py b/apiserver/plane/db/models/__init__.py
index ff930447a..d00a2fa07 100644
--- a/apiserver/plane/db/models/__init__.py
+++ b/apiserver/plane/db/models/__init__.py
@@ -42,25 +42,9 @@ from .issue import (
IssueSubscriber,
IssueVote,
)
-from .module import (
- Module,
- ModuleIssue,
- ModuleLink,
- ModuleMember,
- ModuleUserProperties,
-)
-from .notification import (
- EmailNotificationLog,
- Notification,
- UserNotificationPreference,
-)
-from .page import (
- Page,
- PageLabel,
- PageLog,
- ProjectPage,
- PageVersion,
-)
+from .module import Module, ModuleIssue, ModuleLink, ModuleMember, ModuleUserProperties
+from .notification import EmailNotificationLog, Notification, UserNotificationPreference
+from .page import Page, PageLabel, PageLog, ProjectPage, PageVersion
from .project import (
Project,
ProjectBaseModel,
@@ -97,11 +81,7 @@ from .intake import Intake, IntakeIssue
from .analytic import AnalyticView
-from .notification import (
- Notification,
- UserNotificationPreference,
- EmailNotificationLog,
-)
+from .notification import Notification, UserNotificationPreference, EmailNotificationLog
from .exporter import ExporterHistory
diff --git a/apiserver/plane/db/models/api.py b/apiserver/plane/db/models/api.py
index bc24ee8a8..01be8e643 100644
--- a/apiserver/plane/db/models/api.py
+++ b/apiserver/plane/db/models/api.py
@@ -30,18 +30,13 @@ class APIToken(BaseModel):
# User Information
user = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- related_name="bot_tokens",
+ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="bot_tokens"
)
user_type = models.PositiveSmallIntegerField(
choices=((0, "Human"), (1, "Bot")), default=0
)
workspace = models.ForeignKey(
- "db.Workspace",
- related_name="api_tokens",
- on_delete=models.CASCADE,
- null=True,
+ "db.Workspace", related_name="api_tokens", on_delete=models.CASCADE, null=True
)
expired_at = models.DateTimeField(blank=True, null=True)
is_service = models.BooleanField(default=False)
diff --git a/apiserver/plane/db/models/asset.py b/apiserver/plane/db/models/asset.py
index e230d3aec..d7a380003 100644
--- a/apiserver/plane/db/models/asset.py
+++ b/apiserver/plane/db/models/asset.py
@@ -11,7 +11,6 @@ from .base import BaseModel
def get_upload_path(instance, filename):
-
if instance.workspace_id is not None:
return f"{instance.workspace.id}/{uuid4().hex}-{filename}"
return f"user-{uuid4().hex}-{filename}"
@@ -40,57 +39,30 @@ class FileAsset(BaseModel):
DRAFT_ISSUE_DESCRIPTION = "DRAFT_ISSUE_DESCRIPTION"
attributes = models.JSONField(default=dict)
- asset = models.FileField(
- upload_to=get_upload_path,
- max_length=800,
- )
+ asset = models.FileField(upload_to=get_upload_path, max_length=800)
user = models.ForeignKey(
- "db.User",
- on_delete=models.CASCADE,
- null=True,
- related_name="assets",
+ "db.User", on_delete=models.CASCADE, null=True, related_name="assets"
)
workspace = models.ForeignKey(
- "db.Workspace",
- on_delete=models.CASCADE,
- null=True,
- related_name="assets",
+ "db.Workspace", on_delete=models.CASCADE, null=True, related_name="assets"
)
draft_issue = models.ForeignKey(
- "db.DraftIssue",
- on_delete=models.CASCADE,
- null=True,
- related_name="assets",
+ "db.DraftIssue", on_delete=models.CASCADE, null=True, related_name="assets"
)
project = models.ForeignKey(
- "db.Project",
- on_delete=models.CASCADE,
- null=True,
- related_name="assets",
+ "db.Project", on_delete=models.CASCADE, null=True, related_name="assets"
)
issue = models.ForeignKey(
- "db.Issue",
- on_delete=models.CASCADE,
- null=True,
- related_name="assets",
+ "db.Issue", on_delete=models.CASCADE, null=True, related_name="assets"
)
comment = models.ForeignKey(
- "db.IssueComment",
- on_delete=models.CASCADE,
- null=True,
- related_name="assets",
+ "db.IssueComment", on_delete=models.CASCADE, null=True, related_name="assets"
)
page = models.ForeignKey(
- "db.Page",
- on_delete=models.CASCADE,
- null=True,
- related_name="assets",
+ "db.Page", on_delete=models.CASCADE, null=True, related_name="assets"
)
entity_type = models.CharField(
- max_length=255,
- choices=EntityTypeContext.choices,
- null=True,
- blank=True,
+ max_length=255, choices=EntityTypeContext.choices, null=True, blank=True
)
is_deleted = models.BooleanField(default=False)
is_archived = models.BooleanField(default=False)
diff --git a/apiserver/plane/db/models/base.py b/apiserver/plane/db/models/base.py
index 63c08afa4..d0531e881 100644
--- a/apiserver/plane/db/models/base.py
+++ b/apiserver/plane/db/models/base.py
@@ -12,11 +12,7 @@ from ..mixins import AuditModel
class BaseModel(AuditModel):
id = models.UUIDField(
- default=uuid.uuid4,
- unique=True,
- editable=False,
- db_index=True,
- primary_key=True,
+ default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True
)
class Meta:
diff --git a/apiserver/plane/db/models/cycle.py b/apiserver/plane/db/models/cycle.py
index c3dccb0c8..6449fd145 100644
--- a/apiserver/plane/db/models/cycle.py
+++ b/apiserver/plane/db/models/cycle.py
@@ -55,15 +55,9 @@ def get_default_display_properties():
class Cycle(ProjectBaseModel):
name = models.CharField(max_length=255, verbose_name="Cycle Name")
- description = models.TextField(
- verbose_name="Cycle Description", blank=True
- )
- start_date = models.DateTimeField(
- verbose_name="Start Date", blank=True, null=True
- )
- end_date = models.DateTimeField(
- verbose_name="End Date", blank=True, null=True
- )
+ description = models.TextField(verbose_name="Cycle Description", blank=True)
+ start_date = models.DateTimeField(verbose_name="Start Date", blank=True, null=True)
+ end_date = models.DateTimeField(verbose_name="End Date", blank=True, null=True)
owned_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
@@ -78,9 +72,7 @@ class Cycle(ProjectBaseModel):
logo_props = models.JSONField(default=dict)
# timezone
TIMEZONE_CHOICES = tuple(zip(pytz.all_timezones, pytz.all_timezones))
- timezone = models.CharField(
- max_length=255, default="UTC", choices=TIMEZONE_CHOICES
- )
+ timezone = models.CharField(max_length=255, default="UTC", choices=TIMEZONE_CHOICES)
version = models.IntegerField(default=1)
class Meta:
@@ -91,9 +83,9 @@ class Cycle(ProjectBaseModel):
def save(self, *args, **kwargs):
if self._state.adding:
- smallest_sort_order = Cycle.objects.filter(
- project=self.project
- ).aggregate(smallest=models.Min("sort_order"))["smallest"]
+ smallest_sort_order = Cycle.objects.filter(project=self.project).aggregate(
+ smallest=models.Min("sort_order")
+ )["smallest"]
if smallest_sort_order is not None:
self.sort_order = smallest_sort_order - 10000
@@ -137,9 +129,7 @@ class CycleIssue(ProjectBaseModel):
class CycleUserProperties(ProjectBaseModel):
cycle = models.ForeignKey(
- "db.Cycle",
- on_delete=models.CASCADE,
- related_name="cycle_user_properties",
+ "db.Cycle", on_delete=models.CASCADE, related_name="cycle_user_properties"
)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
@@ -148,9 +138,7 @@ class CycleUserProperties(ProjectBaseModel):
)
filters = models.JSONField(default=get_default_filters)
display_filters = models.JSONField(default=get_default_display_filters)
- display_properties = models.JSONField(
- default=get_default_display_properties
- )
+ display_properties = models.JSONField(default=get_default_display_properties)
class Meta:
unique_together = ["cycle", "user", "deleted_at"]
diff --git a/apiserver/plane/db/models/dashboard.py b/apiserver/plane/db/models/dashboard.py
index b9c3c45b0..e0f401753 100644
--- a/apiserver/plane/db/models/dashboard.py
+++ b/apiserver/plane/db/models/dashboard.py
@@ -20,9 +20,7 @@ class Dashboard(BaseModel):
description_html = models.TextField(blank=True, default="")
identifier = models.UUIDField(null=True)
owned_by = models.ForeignKey(
- "db.User",
- on_delete=models.CASCADE,
- related_name="dashboards",
+ "db.User", on_delete=models.CASCADE, related_name="dashboards"
)
is_default = models.BooleanField(default=False)
type_identifier = models.CharField(
@@ -46,11 +44,7 @@ class Dashboard(BaseModel):
class Widget(TimeAuditModel):
id = models.UUIDField(
- default=uuid.uuid4,
- unique=True,
- editable=False,
- db_index=True,
- primary_key=True,
+ default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True
)
key = models.CharField(max_length=255)
filters = models.JSONField(default=dict)
@@ -69,14 +63,10 @@ class Widget(TimeAuditModel):
class DashboardWidget(BaseModel):
widget = models.ForeignKey(
- Widget,
- on_delete=models.CASCADE,
- related_name="dashboard_widgets",
+ Widget, on_delete=models.CASCADE, related_name="dashboard_widgets"
)
dashboard = models.ForeignKey(
- Dashboard,
- on_delete=models.CASCADE,
- related_name="dashboard_widgets",
+ Dashboard, on_delete=models.CASCADE, related_name="dashboard_widgets"
)
is_visible = models.BooleanField(default=True)
sort_order = models.FloatField(default=65535)
diff --git a/apiserver/plane/db/models/deploy_board.py b/apiserver/plane/db/models/deploy_board.py
index f72d1155b..f053f4a82 100644
--- a/apiserver/plane/db/models/deploy_board.py
+++ b/apiserver/plane/db/models/deploy_board.py
@@ -24,21 +24,14 @@ class DeployBoard(WorkspaceBaseModel):
)
entity_identifier = models.UUIDField(null=True)
- entity_name = models.CharField(
- max_length=30,
- null=True,
- blank=True,
- )
+ entity_name = models.CharField(max_length=30, null=True, blank=True)
anchor = models.CharField(
max_length=255, default=get_anchor, unique=True, db_index=True
)
is_comments_enabled = models.BooleanField(default=False)
is_reactions_enabled = models.BooleanField(default=False)
intake = models.ForeignKey(
- "db.Intake",
- related_name="publish_intake",
- on_delete=models.SET_NULL,
- null=True,
+ "db.Intake", related_name="publish_intake", on_delete=models.SET_NULL, null=True
)
is_votes_enabled = models.BooleanField(default=False)
view_props = models.JSONField(default=dict)
diff --git a/apiserver/plane/db/models/device.py b/apiserver/plane/db/models/device.py
index 862861f90..055d8ccc4 100644
--- a/apiserver/plane/db/models/device.py
+++ b/apiserver/plane/db/models/device.py
@@ -12,9 +12,7 @@ class Device(BaseModel):
DESKTOP = "DESKTOP", "Desktop"
user = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- related_name="devices",
+ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="devices"
)
device_id = models.CharField(max_length=255, blank=True, null=True)
device_type = models.CharField(max_length=255, choices=DeviceType.choices)
@@ -29,14 +27,10 @@ class Device(BaseModel):
class DeviceSession(BaseModel):
device = models.ForeignKey(
- Device,
- on_delete=models.CASCADE,
- related_name="sessions",
+ Device, on_delete=models.CASCADE, related_name="sessions"
)
session = models.ForeignKey(
- "db.Session",
- on_delete=models.CASCADE,
- related_name="device_sessions",
+ "db.Session", on_delete=models.CASCADE, related_name="device_sessions"
)
is_active = models.BooleanField(default=True)
user_agent = models.CharField(max_length=255, null=True, blank=True)
diff --git a/apiserver/plane/db/models/draft.py b/apiserver/plane/db/models/draft.py
index e80ccdaaf..42148d5bb 100644
--- a/apiserver/plane/db/models/draft.py
+++ b/apiserver/plane/db/models/draft.py
@@ -61,10 +61,7 @@ class DraftIssue(WorkspaceBaseModel):
through_fields=("draft_issue", "assignee"),
)
labels = models.ManyToManyField(
- "db.Label",
- blank=True,
- related_name="draft_labels",
- through="DraftIssueLabel",
+ "db.Label", blank=True, related_name="draft_labels", through="DraftIssueLabel"
)
sort_order = models.FloatField(default=65535)
completed_at = models.DateTimeField(null=True)
@@ -90,9 +87,7 @@ class DraftIssue(WorkspaceBaseModel):
from plane.db.models import State
default_state = State.objects.filter(
- ~models.Q(is_triage=True),
- project=self.project,
- default=True,
+ ~models.Q(is_triage=True), project=self.project, default=True
).first()
if default_state is None:
random_state = State.objects.filter(
@@ -118,10 +113,7 @@ class DraftIssue(WorkspaceBaseModel):
# Strip the html tags using html parser
self.description_stripped = (
None
- if (
- self.description_html == ""
- or self.description_html is None
- )
+ if (self.description_html == "" or self.description_html is None)
else strip_tags(self.description_html)
)
largest_sort_order = DraftIssue.objects.filter(
@@ -136,10 +128,7 @@ class DraftIssue(WorkspaceBaseModel):
# Strip the html tags using html parser
self.description_stripped = (
None
- if (
- self.description_html == ""
- or self.description_html is None
- )
+ if (self.description_html == "" or self.description_html is None)
else strip_tags(self.description_html)
)
super(DraftIssue, self).save(*args, **kwargs)
@@ -151,9 +140,7 @@ class DraftIssue(WorkspaceBaseModel):
class DraftIssueAssignee(WorkspaceBaseModel):
draft_issue = models.ForeignKey(
- DraftIssue,
- on_delete=models.CASCADE,
- related_name="draft_issue_assignee",
+ DraftIssue, on_delete=models.CASCADE, related_name="draft_issue_assignee"
)
assignee = models.ForeignKey(
settings.AUTH_USER_MODEL,
@@ -181,9 +168,7 @@ class DraftIssueAssignee(WorkspaceBaseModel):
class DraftIssueLabel(WorkspaceBaseModel):
draft_issue = models.ForeignKey(
- "db.DraftIssue",
- on_delete=models.CASCADE,
- related_name="draft_label_issue",
+ "db.DraftIssue", on_delete=models.CASCADE, related_name="draft_label_issue"
)
label = models.ForeignKey(
"db.Label", on_delete=models.CASCADE, related_name="draft_label_issue"
@@ -201,14 +186,10 @@ class DraftIssueLabel(WorkspaceBaseModel):
class DraftIssueModule(WorkspaceBaseModel):
module = models.ForeignKey(
- "db.Module",
- on_delete=models.CASCADE,
- related_name="draft_issue_module",
+ "db.Module", on_delete=models.CASCADE, related_name="draft_issue_module"
)
draft_issue = models.ForeignKey(
- "db.DraftIssue",
- on_delete=models.CASCADE,
- related_name="draft_issue_module",
+ "db.DraftIssue", on_delete=models.CASCADE, related_name="draft_issue_module"
)
class Meta:
@@ -235,9 +216,7 @@ class DraftIssueCycle(WorkspaceBaseModel):
"""
draft_issue = models.ForeignKey(
- "db.DraftIssue",
- on_delete=models.CASCADE,
- related_name="draft_issue_cycle",
+ "db.DraftIssue", on_delete=models.CASCADE, related_name="draft_issue_cycle"
)
cycle = models.ForeignKey(
"db.Cycle", on_delete=models.CASCADE, related_name="draft_issue_cycle"
diff --git a/apiserver/plane/db/models/estimate.py b/apiserver/plane/db/models/estimate.py
index eb2eaf49b..b0097562d 100644
--- a/apiserver/plane/db/models/estimate.py
+++ b/apiserver/plane/db/models/estimate.py
@@ -9,9 +9,7 @@ from .project import ProjectBaseModel
class Estimate(ProjectBaseModel):
name = models.CharField(max_length=255)
- description = models.TextField(
- verbose_name="Estimate Description", blank=True
- )
+ description = models.TextField(verbose_name="Estimate Description", blank=True)
type = models.CharField(max_length=255, default="categories")
last_used = models.BooleanField(default=False)
@@ -36,9 +34,7 @@ class Estimate(ProjectBaseModel):
class EstimatePoint(ProjectBaseModel):
estimate = models.ForeignKey(
- "db.Estimate",
- on_delete=models.CASCADE,
- related_name="points",
+ "db.Estimate", on_delete=models.CASCADE, related_name="points"
)
key = models.IntegerField(
default=0, validators=[MinValueValidator(0), MaxValueValidator(12)]
diff --git a/apiserver/plane/db/models/exporter.py b/apiserver/plane/db/models/exporter.py
index d26f03450..48d40a1aa 100644
--- a/apiserver/plane/db/models/exporter.py
+++ b/apiserver/plane/db/models/exporter.py
@@ -30,20 +30,11 @@ class ExporterHistory(BaseModel):
),
)
workspace = models.ForeignKey(
- "db.WorkSpace",
- on_delete=models.CASCADE,
- related_name="workspace_exporters",
- )
- project = ArrayField(
- models.UUIDField(default=uuid.uuid4), blank=True, null=True
+ "db.WorkSpace", on_delete=models.CASCADE, related_name="workspace_exporters"
)
+ project = ArrayField(models.UUIDField(default=uuid.uuid4), blank=True, null=True)
provider = models.CharField(
- max_length=50,
- choices=(
- ("json", "json"),
- ("csv", "csv"),
- ("xlsx", "xlsx"),
- ),
+ max_length=50, choices=(("json", "json"), ("csv", "csv"), ("xlsx", "xlsx"))
)
status = models.CharField(
max_length=50,
@@ -58,9 +49,7 @@ class ExporterHistory(BaseModel):
reason = models.TextField(blank=True)
key = models.TextField(blank=True)
url = models.URLField(max_length=800, blank=True, null=True)
- token = models.CharField(
- max_length=255, default=generate_token, unique=True
- )
+ token = models.CharField(max_length=255, default=generate_token, unique=True)
initiated_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
diff --git a/apiserver/plane/db/models/favorite.py b/apiserver/plane/db/models/favorite.py
index b921a8bd6..680bf7e37 100644
--- a/apiserver/plane/db/models/favorite.py
+++ b/apiserver/plane/db/models/favorite.py
@@ -13,9 +13,7 @@ class UserFavorite(WorkspaceBaseModel):
"""
user = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- related_name="favorites",
+ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="favorites"
)
entity_type = models.CharField(max_length=100)
entity_identifier = models.UUIDField(null=True, blank=True)
@@ -31,12 +29,7 @@ class UserFavorite(WorkspaceBaseModel):
)
class Meta:
- unique_together = [
- "entity_type",
- "user",
- "entity_identifier",
- "deleted_at",
- ]
+ unique_together = ["entity_type", "user", "entity_identifier", "deleted_at"]
constraints = [
models.UniqueConstraint(
fields=["entity_type", "entity_identifier", "user"],
@@ -57,7 +50,7 @@ class UserFavorite(WorkspaceBaseModel):
).aggregate(largest=models.Max("sequence"))["largest"]
else:
largest_sequence = UserFavorite.objects.filter(
- workspace=self.workspace,
+ workspace=self.workspace
).aggregate(largest=models.Max("sequence"))["largest"]
if largest_sequence is not None:
self.sequence = largest_sequence + 10000
diff --git a/apiserver/plane/db/models/importer.py b/apiserver/plane/db/models/importer.py
index ebc7571d5..df93b95d1 100644
--- a/apiserver/plane/db/models/importer.py
+++ b/apiserver/plane/db/models/importer.py
@@ -8,11 +8,7 @@ from .project import ProjectBaseModel
class Importer(ProjectBaseModel):
service = models.CharField(
- max_length=50,
- choices=(
- ("github", "GitHub"),
- ("jira", "Jira"),
- ),
+ max_length=50, choices=(("github", "GitHub"), ("jira", "Jira"))
)
status = models.CharField(
max_length=50,
@@ -25,9 +21,7 @@ class Importer(ProjectBaseModel):
default="queued",
)
initiated_by = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- related_name="imports",
+ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="imports"
)
metadata = models.JSONField(default=dict)
config = models.JSONField(default=dict)
diff --git a/apiserver/plane/db/models/intake.py b/apiserver/plane/db/models/intake.py
index 2a4bf75ca..3860b97f2 100644
--- a/apiserver/plane/db/models/intake.py
+++ b/apiserver/plane/db/models/intake.py
@@ -7,9 +7,7 @@ from plane.db.models.project import ProjectBaseModel
class Intake(ProjectBaseModel):
name = models.CharField(max_length=255)
- description = models.TextField(
- verbose_name="Intake Description", blank=True
- )
+ description = models.TextField(verbose_name="Intake Description", blank=True)
is_default = models.BooleanField(default=False)
view_props = models.JSONField(default=dict)
logo_props = models.JSONField(default=dict)
@@ -57,12 +55,7 @@ class IntakeIssue(ProjectBaseModel):
on_delete=models.SET_NULL,
null=True,
)
- source = models.CharField(
- max_length=255,
- default="IN_APP",
- null=True,
- blank=True,
- )
+ source = models.CharField(max_length=255, default="IN_APP", null=True, blank=True)
source_email = models.TextField(blank=True, null=True)
external_source = models.CharField(max_length=255, null=True, blank=True)
external_id = models.CharField(max_length=255, blank=True, null=True)
diff --git a/apiserver/plane/db/models/integration/base.py b/apiserver/plane/db/models/integration/base.py
index 3c296895f..61dad67b0 100644
--- a/apiserver/plane/db/models/integration/base.py
+++ b/apiserver/plane/db/models/integration/base.py
@@ -11,11 +11,7 @@ from plane.db.mixins import AuditModel
class Integration(AuditModel):
id = models.UUIDField(
- default=uuid.uuid4,
- unique=True,
- editable=False,
- db_index=True,
- primary_key=True,
+ default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True
)
title = models.CharField(max_length=400)
provider = models.CharField(max_length=400, unique=True)
@@ -44,18 +40,14 @@ class Integration(AuditModel):
class WorkspaceIntegration(BaseModel):
workspace = models.ForeignKey(
- "db.Workspace",
- related_name="workspace_integrations",
- on_delete=models.CASCADE,
+ "db.Workspace", related_name="workspace_integrations", on_delete=models.CASCADE
)
# Bot user
actor = models.ForeignKey(
"db.User", related_name="integrations", on_delete=models.CASCADE
)
integration = models.ForeignKey(
- "db.Integration",
- related_name="integrated_workspaces",
- on_delete=models.CASCADE,
+ "db.Integration", related_name="integrated_workspaces", on_delete=models.CASCADE
)
api_token = models.ForeignKey(
"db.APIToken", related_name="integrations", on_delete=models.CASCADE
diff --git a/apiserver/plane/db/models/integration/github.py b/apiserver/plane/db/models/integration/github.py
index 9e4294175..410972404 100644
--- a/apiserver/plane/db/models/integration/github.py
+++ b/apiserver/plane/db/models/integration/github.py
@@ -35,15 +35,10 @@ class GithubRepositorySync(ProjectBaseModel):
"db.User", related_name="user_syncs", on_delete=models.CASCADE
)
workspace_integration = models.ForeignKey(
- "db.WorkspaceIntegration",
- related_name="github_syncs",
- on_delete=models.CASCADE,
+ "db.WorkspaceIntegration", related_name="github_syncs", on_delete=models.CASCADE
)
label = models.ForeignKey(
- "db.Label",
- on_delete=models.SET_NULL,
- null=True,
- related_name="repo_syncs",
+ "db.Label", on_delete=models.SET_NULL, null=True, related_name="repo_syncs"
)
def __str__(self):
@@ -66,9 +61,7 @@ class GithubIssueSync(ProjectBaseModel):
"db.Issue", related_name="github_syncs", on_delete=models.CASCADE
)
repository_sync = models.ForeignKey(
- "db.GithubRepositorySync",
- related_name="issue_syncs",
- on_delete=models.CASCADE,
+ "db.GithubRepositorySync", related_name="issue_syncs", on_delete=models.CASCADE
)
def __str__(self):
@@ -86,14 +79,10 @@ class GithubIssueSync(ProjectBaseModel):
class GithubCommentSync(ProjectBaseModel):
repo_comment_id = models.BigIntegerField()
comment = models.ForeignKey(
- "db.IssueComment",
- related_name="comment_syncs",
- on_delete=models.CASCADE,
+ "db.IssueComment", related_name="comment_syncs", on_delete=models.CASCADE
)
issue_sync = models.ForeignKey(
- "db.GithubIssueSync",
- related_name="comment_syncs",
- on_delete=models.CASCADE,
+ "db.GithubIssueSync", related_name="comment_syncs", on_delete=models.CASCADE
)
def __str__(self):
diff --git a/apiserver/plane/db/models/integration/slack.py b/apiserver/plane/db/models/integration/slack.py
index 94d5d7d83..1e8ea469b 100644
--- a/apiserver/plane/db/models/integration/slack.py
+++ b/apiserver/plane/db/models/integration/slack.py
@@ -16,9 +16,7 @@ class SlackProjectSync(ProjectBaseModel):
team_id = models.CharField(max_length=30)
team_name = models.CharField(max_length=300)
workspace_integration = models.ForeignKey(
- "db.WorkspaceIntegration",
- related_name="slack_syncs",
- on_delete=models.CASCADE,
+ "db.WorkspaceIntegration", related_name="slack_syncs", on_delete=models.CASCADE
)
def __str__(self):
diff --git a/apiserver/plane/db/models/issue.py b/apiserver/plane/db/models/issue.py
index adede2982..e37c0e7c1 100644
--- a/apiserver/plane/db/models/issue.py
+++ b/apiserver/plane/db/models/issue.py
@@ -122,9 +122,7 @@ class Issue(ProjectBaseModel):
related_name="state_issue",
)
point = models.IntegerField(
- validators=[MinValueValidator(0), MaxValueValidator(12)],
- null=True,
- blank=True,
+ validators=[MinValueValidator(0), MaxValueValidator(12)], null=True, blank=True
)
estimate_point = models.ForeignKey(
"db.EstimatePoint",
@@ -153,9 +151,7 @@ class Issue(ProjectBaseModel):
through="IssueAssignee",
through_fields=("issue", "assignee"),
)
- sequence_id = models.IntegerField(
- default=1, verbose_name="Issue Sequence ID"
- )
+ sequence_id = models.IntegerField(default=1, verbose_name="Issue Sequence ID")
labels = models.ManyToManyField(
"db.Label", blank=True, related_name="labels", through="IssueLabel"
)
@@ -187,9 +183,7 @@ class Issue(ProjectBaseModel):
from plane.db.models import State
default_state = State.objects.filter(
- ~models.Q(is_triage=True),
- project=self.project,
- default=True,
+ ~models.Q(is_triage=True), project=self.project, default=True
).first()
if default_state is None:
random_state = State.objects.filter(
@@ -222,10 +216,7 @@ class Issue(ProjectBaseModel):
# Strip the html tags using html parser
self.description_stripped = (
None
- if (
- self.description_html == ""
- or self.description_html is None
- )
+ if (self.description_html == "" or self.description_html is None)
else strip_tags(self.description_html)
)
largest_sort_order = Issue.objects.filter(
@@ -243,10 +234,7 @@ class Issue(ProjectBaseModel):
# Strip the html tags using html parser
self.description_stripped = (
None
- if (
- self.description_html == ""
- or self.description_html is None
- )
+ if (self.description_html == "" or self.description_html is None)
else strip_tags(self.description_html)
)
super(Issue, self).save(*args, **kwargs)
@@ -319,9 +307,7 @@ class IssueMention(ProjectBaseModel):
Issue, on_delete=models.CASCADE, related_name="issue_mention"
)
mention = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- related_name="issue_mention",
+ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="issue_mention"
)
class Meta:
@@ -400,12 +386,7 @@ def file_size(value):
class IssueAttachment(ProjectBaseModel):
attributes = models.JSONField(default=dict)
- asset = models.FileField(
- upload_to=get_upload_path,
- validators=[
- file_size,
- ],
- )
+ asset = models.FileField(upload_to=get_upload_path, validators=[file_size])
issue = models.ForeignKey(
"db.Issue", on_delete=models.CASCADE, related_name="issue_attachment"
)
@@ -424,28 +405,17 @@ class IssueAttachment(ProjectBaseModel):
class IssueActivity(ProjectBaseModel):
issue = models.ForeignKey(
- Issue,
- on_delete=models.SET_NULL,
- null=True,
- related_name="issue_activity",
- )
- verb = models.CharField(
- max_length=255, verbose_name="Action", default="created"
+ Issue, on_delete=models.SET_NULL, null=True, related_name="issue_activity"
)
+ verb = models.CharField(max_length=255, verbose_name="Action", default="created")
field = models.CharField(
max_length=255, verbose_name="Field Name", blank=True, null=True
)
- old_value = models.TextField(
- verbose_name="Old Value", blank=True, null=True
- )
- new_value = models.TextField(
- verbose_name="New Value", blank=True, null=True
- )
+ old_value = models.TextField(verbose_name="Old Value", blank=True, null=True)
+ new_value = models.TextField(verbose_name="New Value", blank=True, null=True)
comment = models.TextField(verbose_name="Comment", blank=True)
- attachments = ArrayField(
- models.URLField(), size=10, blank=True, default=list
- )
+ attachments = ArrayField(models.URLField(), size=10, blank=True, default=list)
issue_comment = models.ForeignKey(
"db.IssueComment",
on_delete=models.SET_NULL,
@@ -477,9 +447,7 @@ class IssueComment(ProjectBaseModel):
comment_stripped = models.TextField(verbose_name="Comment", blank=True)
comment_json = models.JSONField(blank=True, default=dict)
comment_html = models.TextField(blank=True, default="")
- attachments = ArrayField(
- models.URLField(), size=10, blank=True, default=list
- )
+ attachments = ArrayField(models.URLField(), size=10, blank=True, default=list)
issue = models.ForeignKey(
Issue, on_delete=models.CASCADE, related_name="issue_comments"
)
@@ -491,10 +459,7 @@ class IssueComment(ProjectBaseModel):
null=True,
)
access = models.CharField(
- choices=(
- ("INTERNAL", "INTERNAL"),
- ("EXTERNAL", "EXTERNAL"),
- ),
+ choices=(("INTERNAL", "INTERNAL"), ("EXTERNAL", "EXTERNAL")),
default="INTERNAL",
max_length=100,
)
@@ -526,9 +491,7 @@ class IssueUserProperty(ProjectBaseModel):
)
filters = models.JSONField(default=get_default_filters)
display_filters = models.JSONField(default=get_default_display_filters)
- display_properties = models.JSONField(
- default=get_default_display_properties
- )
+ display_properties = models.JSONField(default=get_default_display_properties)
class Meta:
verbose_name = "Issue User Property"
@@ -648,9 +611,7 @@ class CommentReaction(ProjectBaseModel):
related_name="comment_reactions",
)
comment = models.ForeignKey(
- IssueComment,
- on_delete=models.CASCADE,
- related_name="comment_reactions",
+ IssueComment, on_delete=models.CASCADE, related_name="comment_reactions"
)
reaction = models.CharField(max_length=20)
@@ -673,28 +634,14 @@ class CommentReaction(ProjectBaseModel):
class IssueVote(ProjectBaseModel):
- issue = models.ForeignKey(
- Issue, on_delete=models.CASCADE, related_name="votes"
- )
+ issue = models.ForeignKey(Issue, on_delete=models.CASCADE, related_name="votes")
actor = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- related_name="votes",
- )
- vote = models.IntegerField(
- choices=(
- (-1, "DOWNVOTE"),
- (1, "UPVOTE"),
- ),
- default=1,
+ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="votes"
)
+ vote = models.IntegerField(choices=((-1, "DOWNVOTE"), (1, "UPVOTE")), default=1)
class Meta:
- unique_together = [
- "issue",
- "actor",
- "deleted_at",
- ]
+ unique_together = ["issue", "actor", "deleted_at"]
constraints = [
models.UniqueConstraint(
fields=["issue", "actor"],
diff --git a/apiserver/plane/db/models/issue_type.py b/apiserver/plane/db/models/issue_type.py
index e6e409c84..953afcc8b 100644
--- a/apiserver/plane/db/models/issue_type.py
+++ b/apiserver/plane/db/models/issue_type.py
@@ -9,9 +9,7 @@ from .base import BaseModel
class IssueType(BaseModel):
workspace = models.ForeignKey(
- "db.Workspace",
- related_name="issue_types",
- on_delete=models.CASCADE,
+ "db.Workspace", related_name="issue_types", on_delete=models.CASCADE
)
name = models.CharField(max_length=255)
description = models.TextField(blank=True)
@@ -34,9 +32,7 @@ class IssueType(BaseModel):
class ProjectIssueType(ProjectBaseModel):
issue_type = models.ForeignKey(
- "db.IssueType",
- related_name="project_issue_types",
- on_delete=models.CASCADE,
+ "db.IssueType", related_name="project_issue_types", on_delete=models.CASCADE
)
level = models.PositiveIntegerField(default=0)
is_default = models.BooleanField(default=False)
diff --git a/apiserver/plane/db/models/module.py b/apiserver/plane/db/models/module.py
index 6238fbd21..6fba4d03c 100644
--- a/apiserver/plane/db/models/module.py
+++ b/apiserver/plane/db/models/module.py
@@ -53,9 +53,7 @@ def get_default_display_properties():
class Module(ProjectBaseModel):
name = models.CharField(max_length=255, verbose_name="Module Name")
- description = models.TextField(
- verbose_name="Module Description", blank=True
- )
+ description = models.TextField(verbose_name="Module Description", blank=True)
description_text = models.JSONField(
verbose_name="Module Description RT", blank=True, null=True
)
@@ -77,10 +75,7 @@ class Module(ProjectBaseModel):
max_length=20,
)
lead = models.ForeignKey(
- "db.User",
- on_delete=models.SET_NULL,
- related_name="module_leads",
- null=True,
+ "db.User", on_delete=models.SET_NULL, related_name="module_leads", null=True
)
members = models.ManyToManyField(
settings.AUTH_USER_MODEL,
@@ -112,9 +107,9 @@ class Module(ProjectBaseModel):
def save(self, *args, **kwargs):
if self._state.adding:
- smallest_sort_order = Module.objects.filter(
- project=self.project
- ).aggregate(smallest=models.Min("sort_order"))["smallest"]
+ smallest_sort_order = Module.objects.filter(project=self.project).aggregate(
+ smallest=models.Min("sort_order")
+ )["smallest"]
if smallest_sort_order is not None:
self.sort_order = smallest_sort_order - 10000
@@ -193,9 +188,7 @@ class ModuleLink(ProjectBaseModel):
class ModuleUserProperties(ProjectBaseModel):
module = models.ForeignKey(
- "db.Module",
- on_delete=models.CASCADE,
- related_name="module_user_properties",
+ "db.Module", on_delete=models.CASCADE, related_name="module_user_properties"
)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
@@ -204,9 +197,7 @@ class ModuleUserProperties(ProjectBaseModel):
)
filters = models.JSONField(default=get_default_filters)
display_filters = models.JSONField(default=get_default_display_filters)
- display_properties = models.JSONField(
- default=get_default_display_properties
- )
+ display_properties = models.JSONField(default=get_default_display_properties)
class Meta:
unique_together = ["module", "user", "deleted_at"]
diff --git a/apiserver/plane/db/models/notification.py b/apiserver/plane/db/models/notification.py
index 33241e05d..2847c07cf 100644
--- a/apiserver/plane/db/models/notification.py
+++ b/apiserver/plane/db/models/notification.py
@@ -6,16 +6,12 @@ from django.db import models
from .base import BaseModel
-
class Notification(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", related_name="notifications", on_delete=models.CASCADE
)
project = models.ForeignKey(
- "db.Project",
- related_name="notifications",
- on_delete=models.CASCADE,
- null=True,
+ "db.Project", related_name="notifications", on_delete=models.CASCADE, null=True
)
data = models.JSONField(null=True)
entity_identifier = models.UUIDField(null=True)
@@ -32,9 +28,7 @@ class Notification(BaseModel):
null=True,
)
receiver = models.ForeignKey(
- "db.User",
- related_name="received_notifications",
- on_delete=models.CASCADE,
+ "db.User", related_name="received_notifications", on_delete=models.CASCADE
)
read_at = models.DateTimeField(null=True)
snoozed_till = models.DateTimeField(null=True)
@@ -53,18 +47,10 @@ class Notification(BaseModel):
def get_default_preference():
return {
- "property_change": {
- "email": True,
- },
- "state": {
- "email": True,
- },
- "comment": {
- "email": True,
- },
- "mentions": {
- "email": True,
- },
+ "property_change": {"email": True},
+ "state": {"email": True},
+ "comment": {"email": True},
+ "mentions": {"email": True},
}
diff --git a/apiserver/plane/db/models/page.py b/apiserver/plane/db/models/page.py
index 433e74a12..91fd6ac44 100644
--- a/apiserver/plane/db/models/page.py
+++ b/apiserver/plane/db/models/page.py
@@ -26,9 +26,7 @@ class Page(BaseModel):
description_html = models.TextField(blank=True, default="")
description_stripped = models.TextField(blank=True, null=True)
owned_by = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- related_name="pages",
+ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="pages"
)
access = models.PositiveSmallIntegerField(
choices=((0, "Public"), (1, "Private")), default=0
@@ -92,19 +90,13 @@ class PageLog(BaseModel):
("user_mention", "User Mention"),
)
transaction = models.UUIDField(default=uuid.uuid4)
- page = models.ForeignKey(
- Page, related_name="page_log", on_delete=models.CASCADE
- )
+ page = models.ForeignKey(Page, related_name="page_log", on_delete=models.CASCADE)
entity_identifier = models.UUIDField(null=True)
entity_name = models.CharField(
- max_length=30,
- choices=TYPE_CHOICES,
- verbose_name="Transaction Type",
+ max_length=30, choices=TYPE_CHOICES, verbose_name="Transaction Type"
)
workspace = models.ForeignKey(
- "db.Workspace",
- on_delete=models.CASCADE,
- related_name="workspace_page_log",
+ "db.Workspace", on_delete=models.CASCADE, related_name="workspace_page_log"
)
class Meta:
@@ -126,9 +118,7 @@ class PageLabel(BaseModel):
"db.Page", on_delete=models.CASCADE, related_name="page_labels"
)
workspace = models.ForeignKey(
- "db.Workspace",
- on_delete=models.CASCADE,
- related_name="workspace_page_label",
+ "db.Workspace", on_delete=models.CASCADE, related_name="workspace_page_label"
)
class Meta:
@@ -198,20 +188,14 @@ class TeamPage(BaseModel):
class PageVersion(BaseModel):
workspace = models.ForeignKey(
- "db.Workspace",
- on_delete=models.CASCADE,
- related_name="page_versions",
+ "db.Workspace", on_delete=models.CASCADE, related_name="page_versions"
)
page = models.ForeignKey(
- "db.Page",
- on_delete=models.CASCADE,
- related_name="page_versions",
+ "db.Page", on_delete=models.CASCADE, related_name="page_versions"
)
last_saved_at = models.DateTimeField(default=timezone.now)
owned_by = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- related_name="page_versions",
+ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="page_versions"
)
description_binary = models.BinaryField(null=True)
description_html = models.TextField(blank=True, default="")
diff --git a/apiserver/plane/db/models/project.py b/apiserver/plane/db/models/project.py
index c55ffe646..c97c550ee 100644
--- a/apiserver/plane/db/models/project.py
+++ b/apiserver/plane/db/models/project.py
@@ -14,11 +14,7 @@ from plane.db.mixins import AuditModel
# Module imports
from .base import BaseModel
-ROLE_CHOICES = (
- (20, "Admin"),
- (15, "Member"),
- (5, "Guest"),
-)
+ROLE_CHOICES = ((20, "Admin"), (15, "Member"), (5, "Guest"))
def get_default_props():
@@ -53,27 +49,19 @@ def get_default_preferences():
class Project(BaseModel):
NETWORK_CHOICES = ((0, "Secret"), (2, "Public"))
name = models.CharField(max_length=255, verbose_name="Project Name")
- description = models.TextField(
- verbose_name="Project Description", blank=True
- )
+ description = models.TextField(verbose_name="Project Description", blank=True)
description_text = models.JSONField(
verbose_name="Project Description RT", blank=True, null=True
)
description_html = models.JSONField(
verbose_name="Project Description HTML", blank=True, null=True
)
- network = models.PositiveSmallIntegerField(
- default=2, choices=NETWORK_CHOICES
- )
+ network = models.PositiveSmallIntegerField(default=2, choices=NETWORK_CHOICES)
workspace = models.ForeignKey(
- "db.WorkSpace",
- on_delete=models.CASCADE,
- related_name="workspace_project",
+ "db.WorkSpace", on_delete=models.CASCADE, related_name="workspace_project"
)
identifier = models.CharField(
- max_length=12,
- verbose_name="Project Identifier",
- db_index=True,
+ max_length=12, verbose_name="Project Identifier", db_index=True
)
default_assignee = models.ForeignKey(
settings.AUTH_USER_MODEL,
@@ -108,10 +96,7 @@ class Project(BaseModel):
related_name="project_cover_image",
)
estimate = models.ForeignKey(
- "db.Estimate",
- on_delete=models.SET_NULL,
- related_name="projects",
- null=True,
+ "db.Estimate", on_delete=models.SET_NULL, related_name="projects", null=True
)
archive_in = models.IntegerField(
default=0, validators=[MinValueValidator(0), MaxValueValidator(12)]
@@ -121,17 +106,12 @@ class Project(BaseModel):
)
logo_props = models.JSONField(default=dict)
default_state = models.ForeignKey(
- "db.State",
- on_delete=models.SET_NULL,
- null=True,
- related_name="default_state",
+ "db.State", on_delete=models.SET_NULL, null=True, related_name="default_state"
)
archived_at = models.DateTimeField(null=True)
# timezone
TIMEZONE_CHOICES = tuple(zip(pytz.all_timezones, pytz.all_timezones))
- timezone = models.CharField(
- max_length=255, default="UTC", choices=TIMEZONE_CHOICES
- )
+ timezone = models.CharField(max_length=255, default="UTC", choices=TIMEZONE_CHOICES)
@property
def cover_image_url(self):
@@ -181,9 +161,7 @@ class ProjectBaseModel(BaseModel):
Project, on_delete=models.CASCADE, related_name="project_%(class)s"
)
workspace = models.ForeignKey(
- "db.Workspace",
- on_delete=models.CASCADE,
- related_name="workspace_%(class)s",
+ "db.Workspace", on_delete=models.CASCADE, related_name="workspace_%(class)s"
)
class Meta:
@@ -262,10 +240,7 @@ class ProjectMember(ProjectBaseModel):
# TODO: Remove workspace relation later
class ProjectIdentifier(AuditModel):
workspace = models.ForeignKey(
- "db.Workspace",
- models.CASCADE,
- related_name="project_identifiers",
- null=True,
+ "db.Workspace", models.CASCADE, related_name="project_identifiers", null=True
)
project = models.OneToOneField(
Project, on_delete=models.CASCADE, related_name="project_identifier"
@@ -310,10 +285,7 @@ class ProjectDeployBoard(ProjectBaseModel):
comments = models.BooleanField(default=False)
reactions = models.BooleanField(default=False)
intake = models.ForeignKey(
- "db.Intake",
- related_name="board_intake",
- on_delete=models.SET_NULL,
- null=True,
+ "db.Intake", related_name="board_intake", on_delete=models.SET_NULL, null=True
)
votes = models.BooleanField(default=False)
views = models.JSONField(default=get_default_views)
diff --git a/apiserver/plane/db/models/recent_visit.py b/apiserver/plane/db/models/recent_visit.py
index 4696ead46..14737eba5 100644
--- a/apiserver/plane/db/models/recent_visit.py
+++ b/apiserver/plane/db/models/recent_visit.py
@@ -17,10 +17,7 @@ class EntityNameEnum(models.TextChoices):
class UserRecentVisit(WorkspaceBaseModel):
entity_identifier = models.UUIDField(null=True)
- entity_name = models.CharField(
- max_length=30,
- choices=EntityNameEnum.choices,
- )
+ entity_name = models.CharField(max_length=30, choices=EntityNameEnum.choices)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
diff --git a/apiserver/plane/db/models/session.py b/apiserver/plane/db/models/session.py
index 95e8e0b7d..3b35ebc70 100644
--- a/apiserver/plane/db/models/session.py
+++ b/apiserver/plane/db/models/session.py
@@ -11,19 +11,9 @@ VALID_KEY_CHARS = string.ascii_lowercase + string.digits
class Session(AbstractBaseSession):
- device_info = models.JSONField(
- null=True,
- blank=True,
- default=None,
- )
- session_key = models.CharField(
- max_length=128,
- primary_key=True,
- )
- user_id = models.CharField(
- null=True,
- max_length=50,
- )
+ device_info = models.JSONField(null=True, blank=True, default=None)
+ session_key = models.CharField(max_length=128, primary_key=True)
+ user_id = models.CharField(null=True, max_length=50)
@classmethod
def get_session_store_class(cls):
@@ -34,7 +24,6 @@ class Session(AbstractBaseSession):
class SessionStore(DBSessionStore):
-
@classmethod
def get_model_class(cls):
return Session
@@ -59,7 +48,5 @@ class SessionStore(DBSessionStore):
# Save the device info
device_info = data.get("device_info")
- obj.device_info = (
- device_info if isinstance(device_info, dict) else None
- )
+ obj.device_info = device_info if isinstance(device_info, dict) else None
return obj
diff --git a/apiserver/plane/db/models/social_connection.py b/apiserver/plane/db/models/social_connection.py
index 2a21c55fd..9a85a320d 100644
--- a/apiserver/plane/db/models/social_connection.py
+++ b/apiserver/plane/db/models/social_connection.py
@@ -10,7 +10,12 @@ from .base import BaseModel
class SocialLoginConnection(BaseModel):
medium = models.CharField(
max_length=20,
- choices=(("Google", "google"), ("Github", "github"), ("GitLab", "gitlab"), ("Jira", "jira")),
+ choices=(
+ ("Google", "google"),
+ ("Github", "github"),
+ ("GitLab", "gitlab"),
+ ("Jira", "jira"),
+ ),
default=None,
)
last_login_at = models.DateTimeField(default=timezone.now, null=True)
diff --git a/apiserver/plane/db/models/state.py b/apiserver/plane/db/models/state.py
index c661a4d61..3478d70d2 100644
--- a/apiserver/plane/db/models/state.py
+++ b/apiserver/plane/db/models/state.py
@@ -9,9 +9,7 @@ from .project import ProjectBaseModel
class State(ProjectBaseModel):
name = models.CharField(max_length=255, verbose_name="State Name")
- description = models.TextField(
- verbose_name="State Description", blank=True
- )
+ description = models.TextField(verbose_name="State Description", blank=True)
color = models.CharField(max_length=255, verbose_name="State Color")
slug = models.SlugField(max_length=100, blank=True)
sequence = models.FloatField(default=65535)
@@ -22,7 +20,7 @@ class State(ProjectBaseModel):
("started", "Started"),
("completed", "Completed"),
("cancelled", "Cancelled"),
- ("triage", "Triage")
+ ("triage", "Triage"),
),
default="backlog",
max_length=20,
diff --git a/apiserver/plane/db/models/user.py b/apiserver/plane/db/models/user.py
index e97d04e7a..34a86a251 100644
--- a/apiserver/plane/db/models/user.py
+++ b/apiserver/plane/db/models/user.py
@@ -4,11 +4,7 @@ import string
import uuid
import pytz
-from django.contrib.auth.models import (
- AbstractBaseUser,
- PermissionsMixin,
- UserManager,
-)
+from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager
# Django imports
from django.db import models
@@ -32,18 +28,12 @@ def get_default_onboarding():
class User(AbstractBaseUser, PermissionsMixin):
id = models.UUIDField(
- default=uuid.uuid4,
- unique=True,
- editable=False,
- db_index=True,
- primary_key=True,
+ default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True
)
username = models.CharField(max_length=128, unique=True)
# user fields
mobile_number = models.CharField(max_length=255, blank=True, null=True)
- email = models.CharField(
- max_length=255, null=True, blank=True, unique=True
- )
+ email = models.CharField(max_length=255, null=True, blank=True, unique=True)
# identity
display_name = models.CharField(max_length=255, default="")
@@ -69,15 +59,9 @@ class User(AbstractBaseUser, PermissionsMixin):
)
# tracking metrics
- date_joined = models.DateTimeField(
- auto_now_add=True, verbose_name="Created At"
- )
- created_at = models.DateTimeField(
- auto_now_add=True, verbose_name="Created At"
- )
- updated_at = models.DateTimeField(
- auto_now=True, verbose_name="Last Modified At"
- )
+ date_joined = models.DateTimeField(auto_now_add=True, verbose_name="Created At")
+ created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created At")
+ updated_at = models.DateTimeField(auto_now=True, verbose_name="Last Modified At")
last_location = models.CharField(max_length=255, blank=True)
created_location = models.CharField(max_length=255, blank=True)
@@ -98,20 +82,14 @@ class User(AbstractBaseUser, PermissionsMixin):
last_logout_time = models.DateTimeField(null=True)
last_login_ip = models.CharField(max_length=255, blank=True)
last_logout_ip = models.CharField(max_length=255, blank=True)
- last_login_medium = models.CharField(
- max_length=20,
- default="email",
- )
+ last_login_medium = models.CharField(max_length=20, default="email")
last_login_uagent = models.TextField(blank=True)
token_updated_at = models.DateTimeField(null=True)
# my_issues_prop = models.JSONField(null=True)
is_bot = models.BooleanField(default=False)
bot_type = models.CharField(
- max_length=30,
- verbose_name="Bot Type",
- blank=True,
- null=True,
+ max_length=30, verbose_name="Bot Type", blank=True, null=True
)
# timezone
@@ -168,9 +146,7 @@ class User(AbstractBaseUser, PermissionsMixin):
self.display_name = (
self.email.split("@")[0]
if len(self.email.split("@"))
- else "".join(
- random.choice(string.ascii_letters) for _ in range(6)
- )
+ else "".join(random.choice(string.ascii_letters) for _ in range(6))
)
if self.is_superuser:
@@ -181,11 +157,7 @@ class User(AbstractBaseUser, PermissionsMixin):
class Profile(TimeAuditModel):
id = models.UUIDField(
- default=uuid.uuid4,
- unique=True,
- editable=False,
- db_index=True,
- primary_key=True,
+ default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True
)
# User
user = models.OneToOneField(
@@ -222,19 +194,13 @@ class Account(TimeAuditModel):
)
id = models.UUIDField(
- default=uuid.uuid4,
- unique=True,
- editable=False,
- db_index=True,
- primary_key=True,
+ default=uuid.uuid4, unique=True, editable=False, db_index=True, primary_key=True
)
user = models.ForeignKey(
"db.User", on_delete=models.CASCADE, related_name="accounts"
)
provider_account_id = models.CharField(max_length=255)
- provider = models.CharField(
- choices=PROVIDER_CHOICES,
- )
+ provider = models.CharField(choices=PROVIDER_CHOICES)
access_token = models.TextField()
access_token_expired_at = models.DateTimeField(null=True)
refresh_token = models.TextField(null=True, blank=True)
diff --git a/apiserver/plane/db/models/view.py b/apiserver/plane/db/models/view.py
index 586ab257d..c9182acce 100644
--- a/apiserver/plane/db/models/view.py
+++ b/apiserver/plane/db/models/view.py
@@ -57,18 +57,14 @@ class IssueView(WorkspaceBaseModel):
query = models.JSONField(verbose_name="View Query")
filters = models.JSONField(default=dict)
display_filters = models.JSONField(default=get_default_display_filters)
- display_properties = models.JSONField(
- default=get_default_display_properties
- )
+ display_properties = models.JSONField(default=get_default_display_properties)
access = models.PositiveSmallIntegerField(
default=1, choices=((0, "Private"), (1, "Public"))
)
sort_order = models.FloatField(default=65535)
logo_props = models.JSONField(default=dict)
owned_by = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- related_name="views",
+ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="views"
)
is_locked = models.BooleanField(default=False)
@@ -80,9 +76,7 @@ class IssueView(WorkspaceBaseModel):
def save(self, *args, **kwargs):
query_params = self.filters
- self.query = (
- issue_filters(query_params, "POST") if query_params else {}
- )
+ self.query = issue_filters(query_params, "POST") if query_params else {}
if self._state.adding:
if self.project:
diff --git a/apiserver/plane/db/models/webhook.py b/apiserver/plane/db/models/webhook.py
index fbe74d03a..be2a5e9a3 100644
--- a/apiserver/plane/db/models/webhook.py
+++ b/apiserver/plane/db/models/webhook.py
@@ -17,9 +17,7 @@ def generate_token():
def validate_schema(value):
parsed_url = urlparse(value)
if parsed_url.scheme not in ["http", "https"]:
- raise ValidationError(
- "Invalid schema. Only HTTP and HTTPS are allowed."
- )
+ raise ValidationError("Invalid schema. Only HTTP and HTTPS are allowed.")
def validate_domain(value):
@@ -31,16 +29,9 @@ def validate_domain(value):
class Webhook(BaseModel):
workspace = models.ForeignKey(
- "db.Workspace",
- on_delete=models.CASCADE,
- related_name="workspace_webhooks",
- )
- url = models.URLField(
- validators=[
- validate_schema,
- validate_domain,
- ]
+ "db.Workspace", on_delete=models.CASCADE, related_name="workspace_webhooks"
)
+ url = models.URLField(validators=[validate_schema, validate_domain])
is_active = models.BooleanField(default=True)
secret_key = models.CharField(max_length=255, default=generate_token)
project = models.BooleanField(default=False)
@@ -65,9 +56,7 @@ class WebhookLog(BaseModel):
"db.Workspace", on_delete=models.CASCADE, related_name="webhook_logs"
)
# Associated webhook
- webhook = models.ForeignKey(
- Webhook, on_delete=models.CASCADE, related_name="logs"
- )
+ webhook = models.ForeignKey(Webhook, on_delete=models.CASCADE, related_name="logs")
# Basic request details
event_type = models.CharField(max_length=255, blank=True, null=True)
diff --git a/apiserver/plane/db/models/workspace.py b/apiserver/plane/db/models/workspace.py
index 8dd4d44f0..93f8a24e0 100644
--- a/apiserver/plane/db/models/workspace.py
+++ b/apiserver/plane/db/models/workspace.py
@@ -10,11 +10,7 @@ from django.db import models
from .base import BaseModel
from plane.utils.constants import RESTRICTED_WORKSPACE_SLUGS
-ROLE_CHOICES = (
- (20, "Admin"),
- (15, "Member"),
- (5, "Guest"),
-)
+ROLE_CHOICES = ((20, "Admin"), (15, "Member"), (5, "Guest"))
def get_default_props():
@@ -81,7 +77,7 @@ def get_default_display_filters():
"show_empty_groups": True,
"layout": "list",
"calendar_date_range": "",
- },
+ }
}
@@ -101,17 +97,12 @@ def get_default_display_properties():
"state": True,
"sub_issue_count": True,
"updated_on": True,
- },
+ }
}
def get_issue_props():
- return {
- "subscribed": True,
- "assigned": True,
- "created": True,
- "all_issues": True,
- }
+ return {"subscribed": True, "assigned": True, "created": True, "all_issues": True}
def slug_validator(value):
@@ -137,17 +128,10 @@ class Workspace(BaseModel):
related_name="owner_workspace",
)
slug = models.SlugField(
- max_length=48,
- db_index=True,
- unique=True,
- validators=[
- slug_validator,
- ],
+ max_length=48, db_index=True, unique=True, validators=[slug_validator]
)
organization_size = models.CharField(max_length=20, blank=True, null=True)
- timezone = models.CharField(
- max_length=255, default="UTC", choices=TIMEZONE_CHOICES
- )
+ timezone = models.CharField(max_length=255, default="UTC", choices=TIMEZONE_CHOICES)
def __str__(self):
"""Return name of the Workspace"""
@@ -176,10 +160,7 @@ class WorkspaceBaseModel(BaseModel):
"db.Workspace", models.CASCADE, related_name="workspace_%(class)s"
)
project = models.ForeignKey(
- "db.Project",
- models.CASCADE,
- related_name="project_%(class)s",
- null=True,
+ "db.Project", models.CASCADE, related_name="project_%(class)s", null=True
)
class Meta:
@@ -193,9 +174,7 @@ class WorkspaceBaseModel(BaseModel):
class WorkspaceMember(BaseModel):
workspace = models.ForeignKey(
- "db.Workspace",
- on_delete=models.CASCADE,
- related_name="workspace_member",
+ "db.Workspace", on_delete=models.CASCADE, related_name="workspace_member"
)
member = models.ForeignKey(
settings.AUTH_USER_MODEL,
@@ -230,9 +209,7 @@ class WorkspaceMember(BaseModel):
class WorkspaceMemberInvite(BaseModel):
workspace = models.ForeignKey(
- "db.Workspace",
- on_delete=models.CASCADE,
- related_name="workspace_member_invite",
+ "db.Workspace", on_delete=models.CASCADE, related_name="workspace_member_invite"
)
email = models.CharField(max_length=255)
accepted = models.BooleanField(default=False)
@@ -297,13 +274,9 @@ class TeamMember(BaseModel):
workspace = models.ForeignKey(
Workspace, on_delete=models.CASCADE, related_name="team_member"
)
- team = models.ForeignKey(
- Team, on_delete=models.CASCADE, related_name="team_member"
- )
+ team = models.ForeignKey(Team, on_delete=models.CASCADE, related_name="team_member")
member = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- related_name="team_member",
+ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="team_member"
)
def __str__(self):
@@ -330,9 +303,7 @@ class WorkspaceTheme(BaseModel):
)
name = models.CharField(max_length=300)
actor = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- related_name="themes",
+ settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="themes"
)
colors = models.JSONField(default=dict)
@@ -367,9 +338,7 @@ class WorkspaceUserProperties(BaseModel):
)
filters = models.JSONField(default=get_default_filters)
display_filters = models.JSONField(default=get_default_display_filters)
- display_properties = models.JSONField(
- default=get_default_display_properties
- )
+ display_properties = models.JSONField(default=get_default_display_properties)
class Meta:
unique_together = ["workspace", "user", "deleted_at"]
diff --git a/apiserver/plane/license/api/permissions/instance.py b/apiserver/plane/license/api/permissions/instance.py
index 9ee85404b..848de4d7b 100644
--- a/apiserver/plane/license/api/permissions/instance.py
+++ b/apiserver/plane/license/api/permissions/instance.py
@@ -12,7 +12,5 @@ class InstanceAdminPermission(BasePermission):
instance = Instance.objects.first()
return InstanceAdmin.objects.filter(
- role__gte=15,
- instance=instance,
- user=request.user,
+ role__gte=15, instance=instance, user=request.user
).exists()
diff --git a/apiserver/plane/license/api/serializers/__init__.py b/apiserver/plane/license/api/serializers/__init__.py
index 7b9cb676f..681dbeb5c 100644
--- a/apiserver/plane/license/api/serializers/__init__.py
+++ b/apiserver/plane/license/api/serializers/__init__.py
@@ -1,6 +1,4 @@
-from .instance import (
- InstanceSerializer,
-)
+from .instance import InstanceSerializer
from .configuration import InstanceConfigurationSerializer
from .admin import InstanceAdminSerializer, InstanceAdminMeSerializer
diff --git a/apiserver/plane/license/api/serializers/admin.py b/apiserver/plane/license/api/serializers/admin.py
index 119460b4b..4df6901ca 100644
--- a/apiserver/plane/license/api/serializers/admin.py
+++ b/apiserver/plane/license/api/serializers/admin.py
@@ -35,8 +35,4 @@ class InstanceAdminSerializer(BaseSerializer):
class Meta:
model = InstanceAdmin
fields = "__all__"
- read_only_fields = [
- "id",
- "instance",
- "user",
- ]
+ read_only_fields = ["id", "instance", "user"]
diff --git a/apiserver/plane/license/api/serializers/instance.py b/apiserver/plane/license/api/serializers/instance.py
index b5b9c4762..49c5194c8 100644
--- a/apiserver/plane/license/api/serializers/instance.py
+++ b/apiserver/plane/license/api/serializers/instance.py
@@ -12,9 +12,4 @@ class InstanceSerializer(BaseSerializer):
class Meta:
model = Instance
fields = "__all__"
- read_only_fields = [
- "id",
- "email",
- "last_checked_at",
- "is_setup_done",
- ]
+ read_only_fields = ["id", "email", "last_checked_at", "is_setup_done"]
diff --git a/apiserver/plane/license/api/views/__init__.py b/apiserver/plane/license/api/views/__init__.py
index ad1aaa58d..9427ed15e 100644
--- a/apiserver/plane/license/api/views/__init__.py
+++ b/apiserver/plane/license/api/views/__init__.py
@@ -1,13 +1,7 @@
-from .instance import (
- InstanceEndpoint,
- SignUpScreenVisitedEndpoint,
-)
+from .instance import InstanceEndpoint, SignUpScreenVisitedEndpoint
-from .configuration import (
- EmailCredentialCheckEndpoint,
- InstanceConfigurationEndpoint,
-)
+from .configuration import EmailCredentialCheckEndpoint, InstanceConfigurationEndpoint
from .admin import (
diff --git a/apiserver/plane/license/api/views/admin.py b/apiserver/plane/license/api/views/admin.py
index 5d93aba49..10c6df5c3 100644
--- a/apiserver/plane/license/api/views/admin.py
+++ b/apiserver/plane/license/api/views/admin.py
@@ -36,9 +36,7 @@ from plane.authentication.adapter.error import (
class InstanceAdminEndpoint(BaseAPIView):
- permission_classes = [
- InstanceAdminPermission,
- ]
+ permission_classes = [InstanceAdminPermission]
@invalidate_cache(path="/api/instances/", user=False)
# Create an instance admin
@@ -48,8 +46,7 @@ class InstanceAdminEndpoint(BaseAPIView):
if not email:
return Response(
- {"error": "Email is required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Email is required"}, status=status.HTTP_400_BAD_REQUEST
)
instance = Instance.objects.first()
@@ -63,9 +60,7 @@ class InstanceAdminEndpoint(BaseAPIView):
user = User.objects.get(email=email)
instance_admin = InstanceAdmin.objects.create(
- instance=instance,
- user=user,
- role=role,
+ instance=instance, user=user, role=role
)
serializer = InstanceAdminSerializer(instance_admin)
return Response(serializer.data, status=status.HTTP_201_CREATED)
@@ -90,9 +85,7 @@ class InstanceAdminEndpoint(BaseAPIView):
class InstanceAdminSignUpEndpoint(View):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
@invalidate_cache(path="/api/instances/", user=False)
def post(self, request):
@@ -100,9 +93,7 @@ class InstanceAdminSignUpEndpoint(View):
instance = Instance.objects.first()
if instance is None:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
url = urljoin(
@@ -178,9 +169,7 @@ class InstanceAdminSignUpEndpoint(View):
# Existing user
if User.objects.filter(email=email).exists():
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "ADMIN_USER_ALREADY_EXIST"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["ADMIN_USER_ALREADY_EXIST"],
error_message="ADMIN_USER_ALREADY_EXIST",
payload={
"email": email,
@@ -196,13 +185,10 @@ class InstanceAdminSignUpEndpoint(View):
)
return HttpResponseRedirect(url)
else:
-
results = zxcvbn(password)
if results["score"] < 3:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INVALID_ADMIN_PASSWORD"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INVALID_ADMIN_PASSWORD"],
error_message="INVALID_ADMIN_PASSWORD",
payload={
"email": email,
@@ -237,10 +223,7 @@ class InstanceAdminSignUpEndpoint(View):
user.save()
# Register the user as an instance admin
- _ = InstanceAdmin.objects.create(
- user=user,
- instance=instance,
- )
+ _ = InstanceAdmin.objects.create(user=user, instance=instance)
# Make the setup flag True
instance.is_setup_done = True
instance.instance_name = company_name
@@ -254,9 +237,7 @@ class InstanceAdminSignUpEndpoint(View):
class InstanceAdminSignInEndpoint(View):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
@invalidate_cache(path="/api/instances/", user=False)
def post(self, request):
@@ -264,9 +245,7 @@ class InstanceAdminSignInEndpoint(View):
instance = Instance.objects.first()
if instance is None:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "INSTANCE_NOT_CONFIGURED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
error_message="INSTANCE_NOT_CONFIGURED",
)
url = urljoin(
@@ -282,13 +261,9 @@ class InstanceAdminSignInEndpoint(View):
# return error if the email and password is not present
if not email or not password:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "REQUIRED_ADMIN_EMAIL_PASSWORD"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["REQUIRED_ADMIN_EMAIL_PASSWORD"],
error_message="REQUIRED_ADMIN_EMAIL_PASSWORD",
- payload={
- "email": email,
- },
+ payload={"email": email},
)
url = urljoin(
base_host(request=request, is_admin=True),
@@ -304,9 +279,7 @@ class InstanceAdminSignInEndpoint(View):
exc = AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES["INVALID_ADMIN_EMAIL"],
error_message="INVALID_ADMIN_EMAIL",
- payload={
- "email": email,
- },
+ payload={"email": email},
)
url = urljoin(
base_host(request=request, is_admin=True),
@@ -320,9 +293,7 @@ class InstanceAdminSignInEndpoint(View):
# is_active
if not user.is_active:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "ADMIN_USER_DEACTIVATED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["ADMIN_USER_DEACTIVATED"],
error_message="ADMIN_USER_DEACTIVATED",
)
url = urljoin(
@@ -334,13 +305,9 @@ class InstanceAdminSignInEndpoint(View):
# Error out if the user is not present
if not user:
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "ADMIN_USER_DOES_NOT_EXIST"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["ADMIN_USER_DOES_NOT_EXIST"],
error_message="ADMIN_USER_DOES_NOT_EXIST",
- payload={
- "email": email,
- },
+ payload={"email": email},
)
url = urljoin(
base_host(request=request, is_admin=True),
@@ -351,13 +318,9 @@ class InstanceAdminSignInEndpoint(View):
# Check password of the user
if not user.check_password(password):
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "ADMIN_AUTHENTICATION_FAILED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["ADMIN_AUTHENTICATION_FAILED"],
error_message="ADMIN_AUTHENTICATION_FAILED",
- payload={
- "email": email,
- },
+ payload={"email": email},
)
url = urljoin(
base_host(request=request, is_admin=True),
@@ -368,13 +331,9 @@ class InstanceAdminSignInEndpoint(View):
# Check if the user is an instance admin
if not InstanceAdmin.objects.filter(instance=instance, user=user):
exc = AuthenticationException(
- error_code=AUTHENTICATION_ERROR_CODES[
- "ADMIN_AUTHENTICATION_FAILED"
- ],
+ error_code=AUTHENTICATION_ERROR_CODES["ADMIN_AUTHENTICATION_FAILED"],
error_message="ADMIN_AUTHENTICATION_FAILED",
- payload={
- "email": email,
- },
+ payload={"email": email},
)
url = urljoin(
base_host(request=request, is_admin=True),
@@ -397,24 +356,15 @@ class InstanceAdminSignInEndpoint(View):
class InstanceAdminUserMeEndpoint(BaseAPIView):
-
- permission_classes = [
- InstanceAdminPermission,
- ]
+ permission_classes = [InstanceAdminPermission]
def get(self, request):
serializer = InstanceAdminMeSerializer(request.user)
- return Response(
- serializer.data,
- status=status.HTTP_200_OK,
- )
+ return Response(serializer.data, status=status.HTTP_200_OK)
class InstanceAdminUserSessionEndpoint(BaseAPIView):
-
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request):
if (
@@ -424,21 +374,13 @@ class InstanceAdminUserSessionEndpoint(BaseAPIView):
serializer = InstanceAdminMeSerializer(request.user)
data = {"is_authenticated": True}
data["user"] = serializer.data
- return Response(
- data,
- status=status.HTTP_200_OK,
- )
+ return Response(data, status=status.HTTP_200_OK)
else:
- return Response(
- {"is_authenticated": False}, status=status.HTTP_200_OK
- )
+ return Response({"is_authenticated": False}, status=status.HTTP_200_OK)
class InstanceAdminSignOutEndpoint(View):
-
- permission_classes = [
- InstanceAdminPermission,
- ]
+ permission_classes = [InstanceAdminPermission]
def post(self, request):
# Get user
@@ -452,6 +394,4 @@ class InstanceAdminSignOutEndpoint(View):
url = urljoin(base_host(request=request, is_admin=True))
return HttpResponseRedirect(url)
except Exception:
- return HttpResponseRedirect(
- base_host(request=request, is_admin=True)
- )
+ return HttpResponseRedirect(base_host(request=request, is_admin=True))
diff --git a/apiserver/plane/license/api/views/base.py b/apiserver/plane/license/api/views/base.py
index 7e367f941..05b42b801 100644
--- a/apiserver/plane/license/api/views/base.py
+++ b/apiserver/plane/license/api/views/base.py
@@ -36,18 +36,11 @@ class TimezoneMixin:
class BaseAPIView(TimezoneMixin, APIView, BasePaginator):
- permission_classes = [
- InstanceAdminPermission,
- ]
+ permission_classes = [InstanceAdminPermission]
- filter_backends = (
- DjangoFilterBackend,
- SearchFilter,
- )
+ filter_backends = (DjangoFilterBackend, SearchFilter)
- authentication_classes = [
- BaseSessionAuthentication,
- ]
+ authentication_classes = [BaseSessionAuthentication]
filterset_fields = []
@@ -116,17 +109,13 @@ class BaseAPIView(TimezoneMixin, APIView, BasePaginator):
@property
def fields(self):
fields = [
- field
- for field in self.request.GET.get("fields", "").split(",")
- if field
+ field for field in self.request.GET.get("fields", "").split(",") if field
]
return fields if fields else None
@property
def expand(self):
expand = [
- expand
- for expand in self.request.GET.get("expand", "").split(",")
- if expand
+ expand for expand in self.request.GET.get("expand", "").split(",") if expand
]
return expand if expand else None
diff --git a/apiserver/plane/license/api/views/changelog.py b/apiserver/plane/license/api/views/changelog.py
index a81504e47..52583a35f 100644
--- a/apiserver/plane/license/api/views/changelog.py
+++ b/apiserver/plane/license/api/views/changelog.py
@@ -14,9 +14,7 @@ from .base import BaseAPIView
class ChangeLogEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def fetch_change_logs(self):
response = requests.get(settings.INSTANCE_CHANGELOG_URL)
diff --git a/apiserver/plane/license/api/views/configuration.py b/apiserver/plane/license/api/views/configuration.py
index 06f53b753..594a899eb 100644
--- a/apiserver/plane/license/api/views/configuration.py
+++ b/apiserver/plane/license/api/views/configuration.py
@@ -8,11 +8,7 @@ from smtplib import (
)
# Django imports
-from django.core.mail import (
- BadHeaderError,
- EmailMultiAlternatives,
- get_connection,
-)
+from django.core.mail import BadHeaderError, EmailMultiAlternatives, get_connection
# Third party imports
from rest_framework import status
@@ -25,22 +21,16 @@ from plane.license.models import InstanceConfiguration
from plane.license.api.serializers import InstanceConfigurationSerializer
from plane.license.utils.encryption import encrypt_data
from plane.utils.cache import cache_response, invalidate_cache
-from plane.license.utils.instance_value import (
- get_email_configuration,
-)
+from plane.license.utils.instance_value import get_email_configuration
class InstanceConfigurationEndpoint(BaseAPIView):
- permission_classes = [
- InstanceAdminPermission,
- ]
+ permission_classes = [InstanceAdminPermission]
@cache_response(60 * 60 * 2, user=False)
def get(self, request):
instance_configurations = InstanceConfiguration.objects.all()
- serializer = InstanceConfigurationSerializer(
- instance_configurations, many=True
- )
+ serializer = InstanceConfigurationSerializer(instance_configurations, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
@invalidate_cache(path="/api/instances/configurations/", user=False)
@@ -68,7 +58,6 @@ class InstanceConfigurationEndpoint(BaseAPIView):
class EmailCredentialCheckEndpoint(BaseAPIView):
-
def post(self, request):
receiver_email = request.data.get("receiver_email", False)
if not receiver_email:
@@ -98,9 +87,7 @@ class EmailCredentialCheckEndpoint(BaseAPIView):
)
# Prepare email details
subject = "Email Notification from Plane"
- message = (
- "This is a sample email notification sent from Plane application."
- )
+ message = "This is a sample email notification sent from Plane application."
# Send the email
try:
msg = EmailMultiAlternatives(
@@ -112,13 +99,11 @@ class EmailCredentialCheckEndpoint(BaseAPIView):
)
msg.send(fail_silently=False)
return Response(
- {"message": "Email successfully sent."},
- status=status.HTTP_200_OK,
+ {"message": "Email successfully sent."}, status=status.HTTP_200_OK
)
except BadHeaderError:
return Response(
- {"error": "Invalid email header."},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Invalid email header."}, status=status.HTTP_400_BAD_REQUEST
)
except SMTPAuthenticationError:
return Response(
@@ -147,9 +132,7 @@ class EmailCredentialCheckEndpoint(BaseAPIView):
)
except TimeoutError:
return Response(
- {
- "error": "Timeout error while trying to connect to the SMTP server."
- },
+ {"error": "Timeout error while trying to connect to the SMTP server."},
status=status.HTTP_400_BAD_REQUEST,
)
except ConnectionError:
@@ -161,8 +144,6 @@ class EmailCredentialCheckEndpoint(BaseAPIView):
)
except Exception:
return Response(
- {
- "error": "Could not send email. Please check your configuration"
- },
+ {"error": "Could not send email. Please check your configuration"},
status=status.HTTP_400_BAD_REQUEST,
)
diff --git a/apiserver/plane/license/api/views/instance.py b/apiserver/plane/license/api/views/instance.py
index c61b55bb6..883fb7c97 100644
--- a/apiserver/plane/license/api/views/instance.py
+++ b/apiserver/plane/license/api/views/instance.py
@@ -12,16 +12,10 @@ from rest_framework.response import Response
# Module imports
from plane.app.views import BaseAPIView
from plane.db.models import Workspace
-from plane.license.api.permissions import (
- InstanceAdminPermission,
-)
-from plane.license.api.serializers import (
- InstanceSerializer,
-)
+from plane.license.api.permissions import InstanceAdminPermission
+from plane.license.api.serializers import InstanceSerializer
from plane.license.models import Instance
-from plane.license.utils.instance_value import (
- get_configuration_value,
-)
+from plane.license.utils.instance_value import get_configuration_value
from plane.utils.cache import cache_response, invalidate_cache
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_control
@@ -30,12 +24,8 @@ from django.views.decorators.cache import cache_control
class InstanceEndpoint(BaseAPIView):
def get_permissions(self):
if self.request.method == "PATCH":
- return [
- InstanceAdminPermission(),
- ]
- return [
- AllowAny(),
- ]
+ return [InstanceAdminPermission()]
+ return [AllowAny()]
@cache_response(60 * 60 * 2, user=False)
@method_decorator(cache_control(private=True, max_age=12))
@@ -91,10 +81,7 @@ class InstanceEndpoint(BaseAPIView):
"key": "IS_GITLAB_ENABLED",
"default": os.environ.get("IS_GITLAB_ENABLED", "0"),
},
- {
- "key": "EMAIL_HOST",
- "default": os.environ.get("EMAIL_HOST", ""),
- },
+ {"key": "EMAIL_HOST", "default": os.environ.get("EMAIL_HOST", "")},
{
"key": "ENABLE_MAGIC_LINK_LOGIN",
"default": os.environ.get("ENABLE_MAGIC_LINK_LOGIN", "1"),
@@ -161,9 +148,7 @@ class InstanceEndpoint(BaseAPIView):
data["has_openai_configured"] = bool(OPENAI_API_KEY)
# File size settings
- data["file_size_limit"] = float(
- os.environ.get("FILE_SIZE_LIMIT", 5242880)
- )
+ data["file_size_limit"] = float(os.environ.get("FILE_SIZE_LIMIT", 5242880))
# is smtp configured
data["is_smtp_configured"] = bool(EMAIL_HOST)
@@ -189,9 +174,7 @@ class InstanceEndpoint(BaseAPIView):
def patch(self, request):
# Get the instance
instance = Instance.objects.first()
- serializer = InstanceSerializer(
- instance, data=request.data, partial=True
- )
+ serializer = InstanceSerializer(instance, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
@@ -199,9 +182,7 @@ class InstanceEndpoint(BaseAPIView):
class SignUpScreenVisitedEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
@invalidate_cache(path="/api/instances/", user=False)
def post(self, request):
diff --git a/apiserver/plane/license/bgtasks/tracer.py b/apiserver/plane/license/bgtasks/tracer.py
index 44b2be569..60588f5b7 100644
--- a/apiserver/plane/license/bgtasks/tracer.py
+++ b/apiserver/plane/license/bgtasks/tracer.py
@@ -49,12 +49,8 @@ def instance_traces():
span.set_attribute("instance_name", instance.instance_name)
span.set_attribute("current_version", instance.current_version)
span.set_attribute("latest_version", instance.latest_version)
- span.set_attribute(
- "is_telemetry_enabled", instance.is_telemetry_enabled
- )
- span.set_attribute(
- "is_support_required", instance.is_support_required
- )
+ span.set_attribute("is_telemetry_enabled", instance.is_telemetry_enabled)
+ span.set_attribute("is_support_required", instance.is_support_required)
span.set_attribute("is_setup_done", instance.is_setup_done)
span.set_attribute(
"is_signup_screen_visited", instance.is_signup_screen_visited
@@ -80,16 +76,10 @@ def instance_traces():
issue_count = Issue.objects.filter(workspace=workspace).count()
module_count = Module.objects.filter(workspace=workspace).count()
cycle_count = Cycle.objects.filter(workspace=workspace).count()
- cycle_issue_count = CycleIssue.objects.filter(
- workspace=workspace
- ).count()
- module_issue_count = ModuleIssue.objects.filter(
- workspace=workspace
- ).count()
+ cycle_issue_count = CycleIssue.objects.filter(workspace=workspace).count()
+ module_issue_count = ModuleIssue.objects.filter(workspace=workspace).count()
page_count = Page.objects.filter(workspace=workspace).count()
- member_count = WorkspaceMember.objects.filter(
- workspace=workspace
- ).count()
+ member_count = WorkspaceMember.objects.filter(workspace=workspace).count()
# Set span attributes
with tracer.start_as_current_span("workspace_details") as span:
diff --git a/apiserver/plane/license/management/commands/configure_instance.py b/apiserver/plane/license/management/commands/configure_instance.py
index ba6a57d4b..a1c27851e 100644
--- a/apiserver/plane/license/management/commands/configure_instance.py
+++ b/apiserver/plane/license/management/commands/configure_instance.py
@@ -177,32 +177,24 @@ class Command(BaseCommand):
)
else:
self.stdout.write(
- self.style.WARNING(
- f"{obj.key} configuration already exists"
- )
+ self.style.WARNING(f"{obj.key} configuration already exists")
)
keys = ["IS_GOOGLE_ENABLED", "IS_GITHUB_ENABLED", "IS_GITLAB_ENABLED"]
if not InstanceConfiguration.objects.filter(key__in=keys).exists():
for key in keys:
if key == "IS_GOOGLE_ENABLED":
- GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET = (
- get_configuration_value(
- [
- {
- "key": "GOOGLE_CLIENT_ID",
- "default": os.environ.get(
- "GOOGLE_CLIENT_ID", ""
- ),
- },
- {
- "key": "GOOGLE_CLIENT_SECRET",
- "default": os.environ.get(
- "GOOGLE_CLIENT_SECRET", "0"
- ),
- },
- ]
- )
+ GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET = get_configuration_value(
+ [
+ {
+ "key": "GOOGLE_CLIENT_ID",
+ "default": os.environ.get("GOOGLE_CLIENT_ID", ""),
+ },
+ {
+ "key": "GOOGLE_CLIENT_SECRET",
+ "default": os.environ.get("GOOGLE_CLIENT_SECRET", "0"),
+ },
+ ]
)
if bool(GOOGLE_CLIENT_ID) and bool(GOOGLE_CLIENT_SECRET):
value = "1"
@@ -220,23 +212,17 @@ class Command(BaseCommand):
)
)
if key == "IS_GITHUB_ENABLED":
- GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET = (
- get_configuration_value(
- [
- {
- "key": "GITHUB_CLIENT_ID",
- "default": os.environ.get(
- "GITHUB_CLIENT_ID", ""
- ),
- },
- {
- "key": "GITHUB_CLIENT_SECRET",
- "default": os.environ.get(
- "GITHUB_CLIENT_SECRET", "0"
- ),
- },
- ]
- )
+ GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET = get_configuration_value(
+ [
+ {
+ "key": "GITHUB_CLIENT_ID",
+ "default": os.environ.get("GITHUB_CLIENT_ID", ""),
+ },
+ {
+ "key": "GITHUB_CLIENT_SECRET",
+ "default": os.environ.get("GITHUB_CLIENT_SECRET", "0"),
+ },
+ ]
)
if bool(GITHUB_CLIENT_ID) and bool(GITHUB_CLIENT_SECRET):
value = "1"
@@ -265,9 +251,7 @@ class Command(BaseCommand):
},
{
"key": "GITLAB_CLIENT_ID",
- "default": os.environ.get(
- "GITLAB_CLIENT_ID", ""
- ),
+ "default": os.environ.get("GITLAB_CLIENT_ID", ""),
},
{
"key": "GITLAB_CLIENT_SECRET",
diff --git a/apiserver/plane/license/management/commands/register_instance.py b/apiserver/plane/license/management/commands/register_instance.py
index 2ee4239d1..692ca350f 100644
--- a/apiserver/plane/license/management/commands/register_instance.py
+++ b/apiserver/plane/license/management/commands/register_instance.py
@@ -18,9 +18,7 @@ class Command(BaseCommand):
def add_arguments(self, parser):
# Positional argument
- parser.add_argument(
- "machine_signature", type=str, help="Machine signature"
- )
+ parser.add_argument("machine_signature", type=str, help="Machine signature")
def read_package_json(self):
with open("package.json", "r") as file:
@@ -39,9 +37,7 @@ class Command(BaseCommand):
# If instance is None then register this instance
if instance is None:
- machine_signature = options.get(
- "machine_signature", "machine-signature"
- )
+ machine_signature = options.get("machine_signature", "machine-signature")
if not machine_signature:
raise CommandError("Machine signature is required")
@@ -60,9 +56,7 @@ class Command(BaseCommand):
self.stdout.write(self.style.SUCCESS("Instance registered"))
else:
- self.stdout.write(
- self.style.SUCCESS("Instance already registered")
- )
+ self.stdout.write(self.style.SUCCESS("Instance already registered"))
payload = self.read_package_json()
# Update the instance details
instance.last_checked_at = timezone.now()
diff --git a/apiserver/plane/license/models/__init__.py b/apiserver/plane/license/models/__init__.py
index 7580abf89..d49524024 100644
--- a/apiserver/plane/license/models/__init__.py
+++ b/apiserver/plane/license/models/__init__.py
@@ -1,6 +1 @@
-from .instance import (
- Instance,
- InstanceAdmin,
- InstanceConfiguration,
- InstanceEdition,
-)
+from .instance import Instance, InstanceAdmin, InstanceConfiguration, InstanceEdition
diff --git a/apiserver/plane/license/urls.py b/apiserver/plane/license/urls.py
index 444d2a119..50e6d0de8 100644
--- a/apiserver/plane/license/urls.py
+++ b/apiserver/plane/license/urls.py
@@ -11,30 +11,14 @@ from plane.license.api.views import (
InstanceAdminUserMeEndpoint,
InstanceAdminSignOutEndpoint,
InstanceAdminUserSessionEndpoint,
- ChangeLogEndpoint
+ ChangeLogEndpoint,
)
urlpatterns = [
- path(
- "",
- InstanceEndpoint.as_view(),
- name="instance",
- ),
- path(
- "changelog/",
- ChangeLogEndpoint.as_view(),
- name="instance-changelog",
- ),
- path(
- "admins/",
- InstanceAdminEndpoint.as_view(),
- name="instance-admins",
- ),
- path(
- "admins/me/",
- InstanceAdminUserMeEndpoint.as_view(),
- name="instance-admins",
- ),
+ path("", InstanceEndpoint.as_view(), name="instance"),
+ path("changelog/", ChangeLogEndpoint.as_view(), name="instance-changelog"),
+ path("admins/", InstanceAdminEndpoint.as_view(), name="instance-admins"),
+ path("admins/me/", InstanceAdminUserMeEndpoint.as_view(), name="instance-admins"),
path(
"admins/session/",
InstanceAdminUserSessionEndpoint.as_view(),
@@ -45,11 +29,7 @@ urlpatterns = [
InstanceAdminSignOutEndpoint.as_view(),
name="instance-admins",
),
- path(
- "admins//",
- InstanceAdminEndpoint.as_view(),
- name="instance-admins",
- ),
+ path("admins//", InstanceAdminEndpoint.as_view(), name="instance-admins"),
path(
"configurations/",
InstanceConfigurationEndpoint.as_view(),
diff --git a/apiserver/plane/license/utils/instance_value.py b/apiserver/plane/license/utils/instance_value.py
index 4c191feda..72241fe54 100644
--- a/apiserver/plane/license/utils/instance_value.py
+++ b/apiserver/plane/license/utils/instance_value.py
@@ -22,9 +22,7 @@ def get_configuration_value(keys):
for item in instance_configuration:
if key.get("key") == item.get("key"):
if item.get("is_encrypted", False):
- environment_list.append(
- decrypt_data(item.get("value"))
- )
+ environment_list.append(decrypt_data(item.get("value")))
else:
environment_list.append(item.get("value"))
@@ -34,9 +32,7 @@ def get_configuration_value(keys):
else:
# Get the configuration from os
for key in keys:
- environment_list.append(
- os.environ.get(key.get("key"), key.get("default"))
- )
+ environment_list.append(os.environ.get(key.get("key"), key.get("default")))
return tuple(environment_list)
@@ -44,30 +40,15 @@ def get_configuration_value(keys):
def get_email_configuration():
return get_configuration_value(
[
- {
- "key": "EMAIL_HOST",
- "default": os.environ.get("EMAIL_HOST"),
- },
- {
- "key": "EMAIL_HOST_USER",
- "default": os.environ.get("EMAIL_HOST_USER"),
- },
+ {"key": "EMAIL_HOST", "default": os.environ.get("EMAIL_HOST")},
+ {"key": "EMAIL_HOST_USER", "default": os.environ.get("EMAIL_HOST_USER")},
{
"key": "EMAIL_HOST_PASSWORD",
"default": os.environ.get("EMAIL_HOST_PASSWORD"),
},
- {
- "key": "EMAIL_PORT",
- "default": os.environ.get("EMAIL_PORT", 587),
- },
- {
- "key": "EMAIL_USE_TLS",
- "default": os.environ.get("EMAIL_USE_TLS", "1"),
- },
- {
- "key": "EMAIL_USE_SSL",
- "default": os.environ.get("EMAIL_USE_SSL", "0"),
- },
+ {"key": "EMAIL_PORT", "default": os.environ.get("EMAIL_PORT", 587)},
+ {"key": "EMAIL_USE_TLS", "default": os.environ.get("EMAIL_USE_TLS", "1")},
+ {"key": "EMAIL_USE_SSL", "default": os.environ.get("EMAIL_USE_SSL", "0")},
{
"key": "EMAIL_FROM",
"default": os.environ.get(
diff --git a/apiserver/plane/middleware/api_log_middleware.py b/apiserver/plane/middleware/api_log_middleware.py
index 96c62c2fd..c7a0841ad 100644
--- a/apiserver/plane/middleware/api_log_middleware.py
+++ b/apiserver/plane/middleware/api_log_middleware.py
@@ -23,13 +23,9 @@ class APITokenLogMiddleware:
method=request.method,
query_params=request.META.get("QUERY_STRING", ""),
headers=str(request.headers),
- body=(
- request_body.decode("utf-8") if request_body else None
- ),
+ body=(request_body.decode("utf-8") if request_body else None),
response_body=(
- response.content.decode("utf-8")
- if response.content
- else None
+ response.content.decode("utf-8") if response.content else None
),
response_code=response.status_code,
ip_address=request.META.get("REMOTE_ADDR", None),
diff --git a/apiserver/plane/settings/common.py b/apiserver/plane/settings/common.py
index a7096ef2a..864010d3c 100644
--- a/apiserver/plane/settings/common.py
+++ b/apiserver/plane/settings/common.py
@@ -18,9 +18,7 @@ from corsheaders.defaults import default_headers
# OpenTelemetry
from opentelemetry import trace
-from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
- OTLPSpanExporter,
-)
+from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.resources import Resource
@@ -93,20 +91,14 @@ REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.SessionAuthentication",
),
- "DEFAULT_PERMISSION_CLASSES": (
- "rest_framework.permissions.IsAuthenticated",
- ),
+ "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
"DEFAULT_RENDERER_CLASSES": ("rest_framework.renderers.JSONRenderer",),
- "DEFAULT_FILTER_BACKENDS": (
- "django_filters.rest_framework.DjangoFilterBackend",
- ),
+ "DEFAULT_FILTER_BACKENDS": ("django_filters.rest_framework.DjangoFilterBackend",),
"EXCEPTION_HANDLER": "plane.authentication.adapter.exception.auth_exception_handler",
}
# Django Auth Backend
-AUTHENTICATION_BACKENDS = (
- "django.contrib.auth.backends.ModelBackend",
-) # default
+AUTHENTICATION_BACKENDS = ("django.contrib.auth.backends.ModelBackend",) # default
# Root Urls
ROOT_URLCONF = "plane.urls"
@@ -115,9 +107,7 @@ ROOT_URLCONF = "plane.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
- "DIRS": [
- "templates",
- ],
+ "DIRS": ["templates"],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
@@ -125,9 +115,9 @@ TEMPLATES = [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
- ],
+ ]
},
- },
+ }
]
@@ -164,9 +154,7 @@ AUTH_USER_MODEL = "db.User"
# Database
if bool(os.environ.get("DATABASE_URL")):
# Parse database configuration from $DATABASE_URL
- DATABASES = {
- "default": dj_database_url.config(),
- }
+ DATABASES = {"default": dj_database_url.config()}
else:
DATABASES = {
"default": {
@@ -199,26 +187,18 @@ else:
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": REDIS_URL,
- "OPTIONS": {
- "CLIENT_CLASS": "django_redis.client.DefaultClient",
- },
+ "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
}
}
# Password validations
AUTH_PASSWORD_VALIDATORS = [
{
- "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
- },
- {
- "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
- },
- {
- "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
- },
- {
- "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
+ "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
},
+ {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
+ {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
+ {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
]
# Password reset time the number of seconds the uniquely generated uid will be valid
@@ -254,12 +234,10 @@ USE_MINIO = int(os.environ.get("USE_MINIO", 0)) == 1
STORAGES = {
"staticfiles": {
- "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
- },
-}
-STORAGES["default"] = {
- "BACKEND": "plane.settings.storage.S3Storage",
+ "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"
+ }
}
+STORAGES["default"] = {"BACKEND": "plane.settings.storage.S3Storage"}
AWS_ACCESS_KEY_ID = os.environ.get("AWS_ACCESS_KEY_ID", "access-key")
AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ACCESS_KEY", "secret-key")
AWS_STORAGE_BUCKET_NAME = os.environ.get("AWS_S3_BUCKET_NAME", "uploads")
@@ -267,9 +245,9 @@ AWS_REGION = os.environ.get("AWS_REGION", "")
AWS_DEFAULT_ACL = "public-read"
AWS_QUERYSTRING_AUTH = False
AWS_S3_FILE_OVERWRITE = False
-AWS_S3_ENDPOINT_URL = os.environ.get(
- "AWS_S3_ENDPOINT_URL", None
-) or os.environ.get("MINIO_ENDPOINT_URL", None)
+AWS_S3_ENDPOINT_URL = os.environ.get("AWS_S3_ENDPOINT_URL", None) or os.environ.get(
+ "MINIO_ENDPOINT_URL", None
+)
if AWS_S3_ENDPOINT_URL and USE_MINIO:
parsed_url = urlparse(os.environ.get("WEB_URL", "http://localhost"))
AWS_S3_CUSTOM_DOMAIN = f"{parsed_url.netloc}/{AWS_STORAGE_BUCKET_NAME}"
@@ -322,9 +300,7 @@ if bool(os.environ.get("SENTRY_DSN", False)) and os.environ.get(
traces_sample_rate=1,
send_default_pii=True,
environment=os.environ.get("SENTRY_ENVIRONMENT", "development"),
- profiles_sample_rate=float(
- os.environ.get("SENTRY_PROFILE_SAMPLE_RATE", 0)
- ),
+ profiles_sample_rate=float(os.environ.get("SENTRY_PROFILE_SAMPLE_RATE", 0)),
)
@@ -346,8 +322,7 @@ POSTHOG_HOST = os.environ.get("POSTHOG_HOST", False)
# instance key
INSTANCE_KEY = os.environ.get(
- "INSTANCE_KEY",
- "ae6517d563dfc13d8270bd45cf17b08f70b37d989128a9dab46ff687603333c3",
+ "INSTANCE_KEY", "ae6517d563dfc13d8270bd45cf17b08f70b37d989128a9dab46ff687603333c3"
)
# Skip environment variable configuration
@@ -362,9 +337,7 @@ SESSION_ENGINE = "plane.db.models.session"
SESSION_COOKIE_AGE = os.environ.get("SESSION_COOKIE_AGE", 604800)
SESSION_COOKIE_NAME = os.environ.get("SESSION_COOKIE_NAME", "session-id")
SESSION_COOKIE_DOMAIN = os.environ.get("COOKIE_DOMAIN", None)
-SESSION_SAVE_EVERY_REQUEST = (
- os.environ.get("SESSION_SAVE_EVERY_REQUEST", "0") == "1"
-)
+SESSION_SAVE_EVERY_REQUEST = os.environ.get("SESSION_SAVE_EVERY_REQUEST", "0") == "1"
# Admin Cookie
ADMIN_SESSION_COOKIE_NAME = "admin-session-id"
diff --git a/apiserver/plane/settings/local.py b/apiserver/plane/settings/local.py
index b175e4c83..d33115e2b 100644
--- a/apiserver/plane/settings/local.py
+++ b/apiserver/plane/settings/local.py
@@ -21,9 +21,7 @@ CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": REDIS_URL, # noqa
- "OPTIONS": {
- "CLIENT_CLASS": "django_redis.client.DefaultClient",
- },
+ "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
}
}
@@ -44,14 +42,14 @@ LOGGING = {
"verbose": {
"format": "{levelname} {asctime} {module} {process:d} {thread:d} {message}",
"style": "{",
- },
+ }
},
"handlers": {
"console": {
"level": "DEBUG",
"class": "logging.StreamHandler",
"formatter": "verbose",
- },
+ }
},
"loggers": {
"django.request": {
@@ -59,10 +57,6 @@ LOGGING = {
"level": "DEBUG",
"propagate": False,
},
- "plane": {
- "handlers": ["console"],
- "level": "DEBUG",
- "propagate": False,
- },
+ "plane": {"handlers": ["console"], "level": "DEBUG", "propagate": False},
},
}
diff --git a/apiserver/plane/settings/production.py b/apiserver/plane/settings/production.py
index 806f83aca..9390a2847 100644
--- a/apiserver/plane/settings/production.py
+++ b/apiserver/plane/settings/production.py
@@ -59,11 +59,7 @@ LOGGING = {
},
},
"loggers": {
- "django": {
- "handlers": ["console", "file"],
- "level": "INFO",
- "propagate": True,
- },
+ "django": {"handlers": ["console", "file"], "level": "INFO", "propagate": True},
"django.request": {
"handlers": ["console", "file"],
"level": "INFO",
diff --git a/apiserver/plane/settings/storage.py b/apiserver/plane/settings/storage.py
index ac99077f3..d82d1c912 100644
--- a/apiserver/plane/settings/storage.py
+++ b/apiserver/plane/settings/storage.py
@@ -12,7 +12,6 @@ from storages.backends.s3boto3 import S3Boto3Storage
class S3Storage(S3Boto3Storage):
-
def url(self, name, parameters=None, expire=None, http_method=None):
return name
@@ -61,9 +60,7 @@ class S3Storage(S3Boto3Storage):
self, object_name, file_type, file_size, expiration=3600
):
"""Generate a presigned URL to upload an S3 object"""
- fields = {
- "Content-Type": file_type,
- }
+ fields = {"Content-Type": file_type}
conditions = [
{"bucket": self.aws_storage_bucket_name},
@@ -113,9 +110,7 @@ class S3Storage(S3Boto3Storage):
disposition="inline",
filename=None,
):
- content_disposition = self._get_content_disposition(
- disposition, filename
- )
+ content_disposition = self._get_content_disposition(disposition, filename)
"""Generate a presigned URL to share an S3 object"""
try:
response = self.s3_client.generate_presigned_url(
diff --git a/apiserver/plane/settings/test.py b/apiserver/plane/settings/test.py
index a86b044a3..6a75f7904 100644
--- a/apiserver/plane/settings/test.py
+++ b/apiserver/plane/settings/test.py
@@ -8,5 +8,5 @@ DEBUG = True
EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
INSTALLED_APPS.append( # noqa
- "plane.tests",
+ "plane.tests"
)
diff --git a/apiserver/plane/space/serializer/__init__.py b/apiserver/plane/space/serializer/__init__.py
index 63dfe9262..ad4e9897d 100644
--- a/apiserver/plane/space/serializer/__init__.py
+++ b/apiserver/plane/space/serializer/__init__.py
@@ -1,9 +1,5 @@
from .user import UserLiteSerializer
-from .issue import (
- LabelLiteSerializer,
- StateLiteSerializer,
- IssuePublicSerializer,
-)
+from .issue import LabelLiteSerializer, StateLiteSerializer, IssuePublicSerializer
from .state import StateSerializer, StateLiteSerializer
diff --git a/apiserver/plane/space/serializer/cycle.py b/apiserver/plane/space/serializer/cycle.py
index d4f5d86e0..afa760a59 100644
--- a/apiserver/plane/space/serializer/cycle.py
+++ b/apiserver/plane/space/serializer/cycle.py
@@ -1,8 +1,6 @@
# Module imports
from .base import BaseSerializer
-from plane.db.models import (
- Cycle,
-)
+from plane.db.models import Cycle
class CycleBaseSerializer(BaseSerializer):
diff --git a/apiserver/plane/space/serializer/intake.py b/apiserver/plane/space/serializer/intake.py
index b1e536b6d..444c20d42 100644
--- a/apiserver/plane/space/serializer/intake.py
+++ b/apiserver/plane/space/serializer/intake.py
@@ -7,10 +7,7 @@ from .user import UserLiteSerializer
from .state import StateLiteSerializer
from .project import ProjectLiteSerializer
from .issue import IssueFlatSerializer, LabelLiteSerializer
-from plane.db.models import (
- Issue,
- IntakeIssue,
-)
+from plane.db.models import Issue, IntakeIssue
class IntakeIssueSerializer(BaseSerializer):
@@ -20,10 +17,7 @@ class IntakeIssueSerializer(BaseSerializer):
class Meta:
model = IntakeIssue
fields = "__all__"
- read_only_fields = [
- "project",
- "workspace",
- ]
+ read_only_fields = ["project", "workspace"]
class IntakeIssueLiteSerializer(BaseSerializer):
@@ -36,12 +30,8 @@ class IntakeIssueLiteSerializer(BaseSerializer):
class IssueStateIntakeSerializer(BaseSerializer):
state_detail = StateLiteSerializer(read_only=True, source="state")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
- label_details = LabelLiteSerializer(
- read_only=True, source="labels", many=True
- )
- assignee_details = UserLiteSerializer(
- read_only=True, source="assignees", many=True
- )
+ label_details = LabelLiteSerializer(read_only=True, source="labels", many=True)
+ assignee_details = UserLiteSerializer(read_only=True, source="assignees", many=True)
sub_issues_count = serializers.IntegerField(read_only=True)
bridge_id = serializers.UUIDField(read_only=True)
issue_intake = IntakeIssueLiteSerializer(read_only=True, many=True)
diff --git a/apiserver/plane/space/serializer/issue.py b/apiserver/plane/space/serializer/issue.py
index d7447681f..e1445b4e6 100644
--- a/apiserver/plane/space/serializer/issue.py
+++ b/apiserver/plane/space/serializer/issue.py
@@ -36,28 +36,17 @@ class IssueStateFlatSerializer(BaseSerializer):
class Meta:
model = Issue
- fields = [
- "id",
- "sequence_id",
- "name",
- "state_detail",
- "project_detail",
- ]
+ fields = ["id", "sequence_id", "name", "state_detail", "project_detail"]
class LabelSerializer(BaseSerializer):
- workspace_detail = WorkspaceLiteSerializer(
- source="workspace", read_only=True
- )
+ workspace_detail = WorkspaceLiteSerializer(source="workspace", read_only=True)
project_detail = ProjectLiteSerializer(source="project", read_only=True)
class Meta:
model = Label
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- ]
+ read_only_fields = ["workspace", "project"]
class IssueProjectLiteSerializer(BaseSerializer):
@@ -65,33 +54,17 @@ class IssueProjectLiteSerializer(BaseSerializer):
class Meta:
model = Issue
- fields = [
- "id",
- "project_detail",
- "name",
- "sequence_id",
- ]
+ fields = ["id", "project_detail", "name", "sequence_id"]
read_only_fields = fields
class IssueRelationSerializer(BaseSerializer):
- issue_detail = IssueProjectLiteSerializer(
- read_only=True, source="related_issue"
- )
+ issue_detail = IssueProjectLiteSerializer(read_only=True, source="related_issue")
class Meta:
model = IssueRelation
- fields = [
- "issue_detail",
- "relation_type",
- "related_issue",
- "issue",
- "id",
- ]
- read_only_fields = [
- "workspace",
- "project",
- ]
+ fields = ["issue_detail", "relation_type", "related_issue", "issue", "id"]
+ read_only_fields = ["workspace", "project"]
class RelatedIssueSerializer(BaseSerializer):
@@ -99,17 +72,8 @@ class RelatedIssueSerializer(BaseSerializer):
class Meta:
model = IssueRelation
- fields = [
- "issue_detail",
- "relation_type",
- "related_issue",
- "issue",
- "id",
- ]
- read_only_fields = [
- "workspace",
- "project",
- ]
+ fields = ["issue_detail", "relation_type", "related_issue", "issue", "id"]
+ read_only_fields = ["workspace", "project"]
class IssueCycleDetailSerializer(BaseSerializer):
@@ -163,8 +127,7 @@ class IssueLinkSerializer(BaseSerializer):
# Validation if url already exists
def create(self, validated_data):
if IssueLink.objects.filter(
- url=validated_data.get("url"),
- issue_id=validated_data.get("issue_id"),
+ url=validated_data.get("url"), issue_id=validated_data.get("issue_id")
).exists():
raise serializers.ValidationError(
{"error": "URL already exists for this Issue"}
@@ -188,22 +151,10 @@ class IssueAttachmentSerializer(BaseSerializer):
class IssueReactionSerializer(BaseSerializer):
-
class Meta:
model = IssueReaction
- fields = [
- "issue",
- "reaction",
- "workspace",
- "project",
- "actor",
- ]
- read_only_fields = [
- "workspace",
- "project",
- "issue",
- "actor",
- ]
+ fields = ["issue", "reaction", "workspace", "project", "actor"]
+ read_only_fields = ["workspace", "project", "issue", "actor"]
class IssueSerializer(BaseSerializer):
@@ -211,9 +162,7 @@ class IssueSerializer(BaseSerializer):
state_detail = StateSerializer(read_only=True, source="state")
parent_detail = IssueStateFlatSerializer(read_only=True, source="parent")
label_details = LabelSerializer(read_only=True, source="labels", many=True)
- assignee_details = UserLiteSerializer(
- read_only=True, source="assignees", many=True
- )
+ assignee_details = UserLiteSerializer(read_only=True, source="assignees", many=True)
related_issues = IssueRelationSerializer(
read_only=True, source="issue_relation", many=True
)
@@ -264,24 +213,15 @@ class CommentReactionLiteSerializer(BaseSerializer):
class Meta:
model = CommentReaction
- fields = [
- "id",
- "reaction",
- "comment",
- "actor_detail",
- ]
+ fields = ["id", "reaction", "comment", "actor_detail"]
class IssueCommentSerializer(BaseSerializer):
actor_detail = UserLiteSerializer(read_only=True, source="actor")
issue_detail = IssueFlatSerializer(read_only=True, source="issue")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
- workspace_detail = WorkspaceLiteSerializer(
- read_only=True, source="workspace"
- )
- comment_reactions = CommentReactionLiteSerializer(
- read_only=True, many=True
- )
+ workspace_detail = WorkspaceLiteSerializer(read_only=True, source="workspace")
+ comment_reactions = CommentReactionLiteSerializer(read_only=True, many=True)
is_member = serializers.BooleanField(read_only=True)
class Meta:
@@ -304,9 +244,7 @@ class IssueCreateSerializer(BaseSerializer):
state_detail = StateSerializer(read_only=True, source="state")
created_by_detail = UserLiteSerializer(read_only=True, source="created_by")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
- workspace_detail = WorkspaceLiteSerializer(
- read_only=True, source="workspace"
- )
+ workspace_detail = WorkspaceLiteSerializer(read_only=True, source="workspace")
assignees = serializers.ListField(
child=serializers.PrimaryKeyRelatedField(queryset=User.objects.all()),
@@ -334,9 +272,7 @@ class IssueCreateSerializer(BaseSerializer):
def to_representation(self, instance):
data = super().to_representation(instance)
- data["assignees"] = [
- str(assignee.id) for assignee in instance.assignees.all()
- ]
+ data["assignees"] = [str(assignee.id) for assignee in instance.assignees.all()]
data["labels"] = [str(label.id) for label in instance.labels.all()]
return data
@@ -346,9 +282,7 @@ class IssueCreateSerializer(BaseSerializer):
and data.get("target_date", None) is not None
and data.get("start_date", None) > data.get("target_date", None)
):
- raise serializers.ValidationError(
- "Start date cannot exceed target date"
- )
+ raise serializers.ValidationError("Start date cannot exceed target date")
return data
def create(self, validated_data):
@@ -467,16 +401,9 @@ class CommentReactionSerializer(BaseSerializer):
class IssueVoteSerializer(BaseSerializer):
-
class Meta:
model = IssueVote
- fields = [
- "issue",
- "vote",
- "workspace",
- "project",
- "actor",
- ]
+ fields = ["issue", "vote", "workspace", "project", "actor"]
read_only_fields = fields
@@ -485,18 +412,9 @@ class IssuePublicSerializer(BaseSerializer):
read_only=True, many=True, source="issue_reactions"
)
votes = IssueVoteSerializer(read_only=True, many=True)
- module_ids = serializers.ListField(
- child=serializers.UUIDField(),
- required=False,
- )
- label_ids = serializers.ListField(
- child=serializers.UUIDField(),
- required=False,
- )
- assignee_ids = serializers.ListField(
- child=serializers.UUIDField(),
- required=False,
- )
+ module_ids = serializers.ListField(child=serializers.UUIDField(), required=False)
+ label_ids = serializers.ListField(child=serializers.UUIDField(), required=False)
+ assignee_ids = serializers.ListField(child=serializers.UUIDField(), required=False)
class Meta:
model = Issue
@@ -522,8 +440,4 @@ class IssuePublicSerializer(BaseSerializer):
class LabelLiteSerializer(BaseSerializer):
class Meta:
model = Label
- fields = [
- "id",
- "name",
- "color",
- ]
+ fields = ["id", "name", "color"]
diff --git a/apiserver/plane/space/serializer/module.py b/apiserver/plane/space/serializer/module.py
index dda1861d1..53840f078 100644
--- a/apiserver/plane/space/serializer/module.py
+++ b/apiserver/plane/space/serializer/module.py
@@ -1,8 +1,6 @@
# Module imports
from .base import BaseSerializer
-from plane.db.models import (
- Module,
-)
+from plane.db.models import Module
class ModuleBaseSerializer(BaseSerializer):
diff --git a/apiserver/plane/space/serializer/project.py b/apiserver/plane/space/serializer/project.py
index be23e0ce2..f79eef686 100644
--- a/apiserver/plane/space/serializer/project.py
+++ b/apiserver/plane/space/serializer/project.py
@@ -1,8 +1,6 @@
# Module imports
from .base import BaseSerializer
-from plane.db.models import (
- Project,
-)
+from plane.db.models import Project
class ProjectLiteSerializer(BaseSerializer):
diff --git a/apiserver/plane/space/serializer/state.py b/apiserver/plane/space/serializer/state.py
index 55064ed0e..184f48b40 100644
--- a/apiserver/plane/space/serializer/state.py
+++ b/apiserver/plane/space/serializer/state.py
@@ -1,27 +1,17 @@
# Module imports
from .base import BaseSerializer
-from plane.db.models import (
- State,
-)
+from plane.db.models import State
class StateSerializer(BaseSerializer):
class Meta:
model = State
fields = "__all__"
- read_only_fields = [
- "workspace",
- "project",
- ]
+ read_only_fields = ["workspace", "project"]
class StateLiteSerializer(BaseSerializer):
class Meta:
model = State
- fields = [
- "id",
- "name",
- "color",
- "group",
- ]
+ fields = ["id", "name", "color", "group"]
read_only_fields = fields
diff --git a/apiserver/plane/space/serializer/user.py b/apiserver/plane/space/serializer/user.py
index 13cd2e45e..9b707a343 100644
--- a/apiserver/plane/space/serializer/user.py
+++ b/apiserver/plane/space/serializer/user.py
@@ -1,8 +1,6 @@
# Module imports
from .base import BaseSerializer
-from plane.db.models import (
- User,
-)
+from plane.db.models import User
class UserLiteSerializer(BaseSerializer):
@@ -17,7 +15,4 @@ class UserLiteSerializer(BaseSerializer):
"is_bot",
"display_name",
]
- read_only_fields = [
- "id",
- "is_bot",
- ]
+ read_only_fields = ["id", "is_bot"]
diff --git a/apiserver/plane/space/serializer/workspace.py b/apiserver/plane/space/serializer/workspace.py
index a31bb3744..4945af96a 100644
--- a/apiserver/plane/space/serializer/workspace.py
+++ b/apiserver/plane/space/serializer/workspace.py
@@ -1,16 +1,10 @@
# Module imports
from .base import BaseSerializer
-from plane.db.models import (
- Workspace,
-)
+from plane.db.models import Workspace
class WorkspaceLiteSerializer(BaseSerializer):
class Meta:
model = Workspace
- fields = [
- "name",
- "slug",
- "id",
- ]
+ fields = ["name", "slug", "id"]
read_only_fields = fields
diff --git a/apiserver/plane/space/urls/__init__.py b/apiserver/plane/space/urls/__init__.py
index 3ef68006e..d9a1f6ec3 100644
--- a/apiserver/plane/space/urls/__init__.py
+++ b/apiserver/plane/space/urls/__init__.py
@@ -4,9 +4,4 @@ from .project import urlpatterns as project_urls
from .asset import urlpatterns as asset_urls
-urlpatterns = [
- *intake_urls,
- *issue_urls,
- *project_urls,
- *asset_urls,
-]
+urlpatterns = [*intake_urls, *issue_urls, *project_urls, *asset_urls]
diff --git a/apiserver/plane/space/urls/intake.py b/apiserver/plane/space/urls/intake.py
index 350157c95..09aca16df 100644
--- a/apiserver/plane/space/urls/intake.py
+++ b/apiserver/plane/space/urls/intake.py
@@ -10,32 +10,18 @@ from plane.space.views import (
urlpatterns = [
path(
"anchor//intakes//intake-issues/",
- IntakeIssuePublicViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IntakeIssuePublicViewSet.as_view({"get": "list", "post": "create"}),
name="intake-issue",
),
path(
"anchor//intakes//inbox-issues/",
- IntakeIssuePublicViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IntakeIssuePublicViewSet.as_view({"get": "list", "post": "create"}),
name="inbox-issue",
),
path(
"anchor//intakes//intake-issues//",
IntakeIssuePublicViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="intake-issue",
),
diff --git a/apiserver/plane/space/urls/issue.py b/apiserver/plane/space/urls/issue.py
index 8b7dce0e6..2391fd38a 100644
--- a/apiserver/plane/space/urls/issue.py
+++ b/apiserver/plane/space/urls/issue.py
@@ -17,71 +17,40 @@ urlpatterns = [
),
path(
"anchor//issues//comments/",
- IssueCommentPublicViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IssueCommentPublicViewSet.as_view({"get": "list", "post": "create"}),
name="issue-comments-project-board",
),
path(
"anchor//issues//comments//",
IssueCommentPublicViewSet.as_view(
- {
- "get": "retrieve",
- "patch": "partial_update",
- "delete": "destroy",
- }
+ {"get": "retrieve", "patch": "partial_update", "delete": "destroy"}
),
name="issue-comments-project-board",
),
path(
"anchor//issues//reactions/",
- IssueReactionPublicViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ IssueReactionPublicViewSet.as_view({"get": "list", "post": "create"}),
name="issue-reactions-project-board",
),
path(
"anchor//issues//reactions//",
- IssueReactionPublicViewSet.as_view(
- {
- "delete": "destroy",
- }
- ),
+ IssueReactionPublicViewSet.as_view({"delete": "destroy"}),
name="issue-reactions-project-board",
),
path(
"anchor//comments//reactions/",
- CommentReactionPublicViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- }
- ),
+ CommentReactionPublicViewSet.as_view({"get": "list", "post": "create"}),
name="comment-reactions-project-board",
),
path(
"anchor//comments//reactions//",
- CommentReactionPublicViewSet.as_view(
- {
- "delete": "destroy",
- }
- ),
+ CommentReactionPublicViewSet.as_view({"delete": "destroy"}),
name="comment-reactions-project-board",
),
path(
"anchor//issues//votes/",
IssueVotePublicViewSet.as_view(
- {
- "get": "list",
- "post": "create",
- "delete": "destroy",
- }
+ {"get": "list", "post": "create", "delete": "destroy"}
),
name="issue-vote-project-board",
),
diff --git a/apiserver/plane/space/utils/grouper.py b/apiserver/plane/space/utils/grouper.py
index 680359790..250b54e89 100644
--- a/apiserver/plane/space/utils/grouper.py
+++ b/apiserver/plane/space/utils/grouper.py
@@ -1,16 +1,7 @@
# Django imports
from django.contrib.postgres.aggregates import ArrayAgg
from django.contrib.postgres.fields import ArrayField
-from django.db.models import (
- Q,
- UUIDField,
- Value,
- F,
- Case,
- When,
- JSONField,
- CharField,
-)
+from django.db.models import Q, UUIDField, Value, F, Case, When, JSONField, CharField
from django.db.models.functions import Coalesce, JSONObject, Concat
# Module imports
@@ -27,7 +18,6 @@ from plane.db.models import (
def issue_queryset_grouper(queryset, group_by, sub_group_by):
-
FIELD_MAPPER = {
"label_ids": "labels__id",
"assignee_ids": "assignees__id",
@@ -37,13 +27,11 @@ def issue_queryset_grouper(queryset, group_by, sub_group_by):
annotations_map = {
"assignee_ids": (
"assignees__id",
- ~Q(assignees__id__isnull=True)
- & Q(issue_assignee__deleted_at__isnull=True),
+ ~Q(assignees__id__isnull=True) & Q(issue_assignee__deleted_at__isnull=True),
),
"label_ids": (
"labels__id",
- ~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ ~Q(labels__id__isnull=True) & Q(label_issue__deleted_at__isnull=True),
),
"module_ids": (
"issue_module__module_id",
@@ -52,23 +40,17 @@ def issue_queryset_grouper(queryset, group_by, sub_group_by):
}
default_annotations = {
key: Coalesce(
- ArrayAgg(
- field,
- distinct=True,
- filter=condition,
- ),
+ ArrayAgg(field, distinct=True, filter=condition),
Value([], output_field=ArrayField(UUIDField())),
)
for key, (field, condition) in annotations_map.items()
- if FIELD_MAPPER.get(key) != group_by
- or FIELD_MAPPER.get(key) != sub_group_by
+ if FIELD_MAPPER.get(key) != group_by or FIELD_MAPPER.get(key) != sub_group_by
}
return queryset.annotate(**default_annotations)
def issue_on_results(issues, group_by, sub_group_by):
-
FIELD_MAPPER = {
"labels__id": "label_ids",
"assignees__id": "assignee_ids",
@@ -154,18 +136,14 @@ def issue_on_results(issues, group_by, sub_group_by):
issue_reactions__actor__avatar_asset__isnull=False,
then=Concat(
Value("/api/assets/v2/static/"),
- F(
- "issue_reactions__actor__avatar_asset"
- ),
+ F("issue_reactions__actor__avatar_asset"),
Value("/"),
),
),
default=F("issue_reactions__actor__avatar"),
output_field=CharField(),
),
- display_name=F(
- "issue_reactions__actor__display_name"
- ),
+ display_name=F("issue_reactions__actor__display_name"),
),
),
),
@@ -183,8 +161,7 @@ def issue_on_results(issues, group_by, sub_group_by):
def issue_group_values(field, slug, project_id=None, filters=dict):
if field == "state_id":
queryset = State.objects.filter(
- is_triage=False,
- workspace__slug=slug,
+ is_triage=False, workspace__slug=slug
).values_list("id", flat=True)
if project_id:
return list(queryset.filter(project_id=project_id))
@@ -201,9 +178,7 @@ def issue_group_values(field, slug, project_id=None, filters=dict):
if field == "assignees__id":
if project_id:
return ProjectMember.objects.filter(
- workspace__slug=slug,
- project_id=project_id,
- is_active=True,
+ workspace__slug=slug, project_id=project_id, is_active=True
).values_list("member_id", flat=True)
else:
return list(
@@ -212,17 +187,17 @@ def issue_group_values(field, slug, project_id=None, filters=dict):
).values_list("member_id", flat=True)
)
if field == "issue_module__module_id":
- queryset = Module.objects.filter(
- workspace__slug=slug,
- ).values_list("id", flat=True)
+ queryset = Module.objects.filter(workspace__slug=slug).values_list(
+ "id", flat=True
+ )
if project_id:
return list(queryset.filter(project_id=project_id)) + ["None"]
else:
return list(queryset) + ["None"]
if field == "cycle_id":
- queryset = Cycle.objects.filter(
- workspace__slug=slug,
- ).values_list("id", flat=True)
+ queryset = Cycle.objects.filter(workspace__slug=slug).values_list(
+ "id", flat=True
+ )
if project_id:
return list(queryset.filter(project_id=project_id)) + ["None"]
else:
@@ -233,21 +208,9 @@ def issue_group_values(field, slug, project_id=None, filters=dict):
)
return list(queryset)
if field == "priority":
- return [
- "low",
- "medium",
- "high",
- "urgent",
- "none",
- ]
+ return ["low", "medium", "high", "urgent", "none"]
if field == "state__group":
- return [
- "backlog",
- "unstarted",
- "started",
- "completed",
- "cancelled",
- ]
+ return ["backlog", "unstarted", "started", "completed", "cancelled"]
if field == "target_date":
queryset = (
Issue.issue_objects.filter(workspace__slug=slug)
diff --git a/apiserver/plane/space/views/__init__.py b/apiserver/plane/space/views/__init__.py
index 4167bdaf8..afdc1d337 100644
--- a/apiserver/plane/space/views/__init__.py
+++ b/apiserver/plane/space/views/__init__.py
@@ -24,8 +24,4 @@ from .state import ProjectStatesEndpoint
from .label import ProjectLabelsEndpoint
-from .asset import (
- EntityAssetEndpoint,
- AssetRestoreEndpoint,
- EntityBulkAssetEndpoint,
-)
+from .asset import EntityAssetEndpoint, AssetRestoreEndpoint, EntityBulkAssetEndpoint
diff --git a/apiserver/plane/space/views/asset.py b/apiserver/plane/space/views/asset.py
index 4ceff9089..2c6722038 100644
--- a/apiserver/plane/space/views/asset.py
+++ b/apiserver/plane/space/views/asset.py
@@ -19,16 +19,11 @@ from plane.bgtasks.storage_metadata_task import get_asset_object_metadata
class EntityAssetEndpoint(BaseAPIView):
-
def get_permissions(self):
if self.request.method == "GET":
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
else:
- permission_classes = [
- IsAuthenticated,
- ]
+ permission_classes = [IsAuthenticated]
return [permission() for permission in permission_classes]
def get(self, request, anchor, pk):
@@ -54,18 +49,14 @@ class EntityAssetEndpoint(BaseAPIView):
# Check if the asset is uploaded
if not asset.is_uploaded:
return Response(
- {
- "error": "The requested asset could not be found.",
- },
+ {"error": "The requested asset could not be found."},
status=status.HTTP_404_NOT_FOUND,
)
# Get the presigned URL
storage = S3Storage(request=request)
# Generate a presigned URL to share an S3 object
- signed_url = storage.generate_presigned_url(
- object_name=asset.asset.name,
- )
+ signed_url = storage.generate_presigned_url(object_name=asset.asset.name)
# Redirect to the signed URL
return HttpResponseRedirect(signed_url)
@@ -77,8 +68,7 @@ class EntityAssetEndpoint(BaseAPIView):
# Check if the project is published
if not deploy_board:
return Response(
- {"error": "Project is not published"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Project is not published"}, status=status.HTTP_404_NOT_FOUND
)
# Get the asset
@@ -91,10 +81,7 @@ class EntityAssetEndpoint(BaseAPIView):
# Check if the entity type is allowed
if entity_type not in FileAsset.EntityTypeContext.values:
return Response(
- {
- "error": "Invalid entity type.",
- "status": False,
- },
+ {"error": "Invalid entity type.", "status": False},
status=status.HTTP_400_BAD_REQUEST,
)
@@ -114,11 +101,7 @@ class EntityAssetEndpoint(BaseAPIView):
# Create a File Asset
asset = FileAsset.objects.create(
- attributes={
- "name": name,
- "type": type,
- "size": size,
- },
+ attributes={"name": name, "type": type, "size": size},
asset=asset_key,
size=size,
workspace=deploy_board.workspace,
@@ -132,9 +115,7 @@ class EntityAssetEndpoint(BaseAPIView):
storage = S3Storage(request=request)
# Generate a presigned URL to share an S3 object
presigned_url = storage.generate_presigned_post(
- object_name=asset_key,
- file_type=type,
- file_size=size,
+ object_name=asset_key, file_type=type, file_size=size
)
# Return the presigned URL
return Response(
@@ -154,8 +135,7 @@ class EntityAssetEndpoint(BaseAPIView):
# Check if the project is published
if not deploy_board:
return Response(
- {"error": "Project is not published"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Project is not published"}, status=status.HTTP_404_NOT_FOUND
)
# get the asset id
@@ -180,14 +160,11 @@ class EntityAssetEndpoint(BaseAPIView):
# Check if the project is published
if not deploy_board:
return Response(
- {"error": "Project is not published"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Project is not published"}, status=status.HTTP_404_NOT_FOUND
)
# Get the asset
asset = FileAsset.objects.get(
- id=pk,
- workspace=deploy_board.workspace,
- project_id=deploy_board.project_id,
+ id=pk, workspace=deploy_board.workspace, project_id=deploy_board.project_id
)
# Check deleted assets
asset.is_deleted = True
@@ -208,14 +185,11 @@ class AssetRestoreEndpoint(BaseAPIView):
# Check if the project is published
if not deploy_board:
return Response(
- {"error": "Project is not published"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Project is not published"}, status=status.HTTP_404_NOT_FOUND
)
# Get the asset
- asset = FileAsset.all_objects.get(
- id=asset_id, workspace=deploy_board.workspace
- )
+ asset = FileAsset.all_objects.get(id=asset_id, workspace=deploy_board.workspace)
asset.is_deleted = False
asset.deleted_at = None
asset.save(update_fields=["is_deleted", "deleted_at"])
@@ -233,8 +207,7 @@ class EntityBulkAssetEndpoint(BaseAPIView):
# Check if the project is published
if not deploy_board:
return Response(
- {"error": "Project is not published"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Project is not published"}, status=status.HTTP_404_NOT_FOUND
)
asset_ids = request.data.get("asset_ids", [])
@@ -242,10 +215,7 @@ class EntityBulkAssetEndpoint(BaseAPIView):
# Check if the asset ids are provided
if not asset_ids:
return Response(
- {
- "error": "No asset ids provided.",
- },
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "No asset ids provided."}, status=status.HTTP_400_BAD_REQUEST
)
# get the asset id
@@ -260,19 +230,12 @@ class EntityBulkAssetEndpoint(BaseAPIView):
# Check if the asset is uploaded
if not asset:
return Response(
- {
- "error": "The requested asset could not be found.",
- },
+ {"error": "The requested asset could not be found."},
status=status.HTTP_404_NOT_FOUND,
)
# Check if the entity type is allowed
- if (
- asset.entity_type
- == FileAsset.EntityTypeContext.COMMENT_DESCRIPTION
- ):
+ if asset.entity_type == FileAsset.EntityTypeContext.COMMENT_DESCRIPTION:
# update the attributes
- assets.update(
- comment_id=entity_id,
- )
+ assets.update(comment_id=entity_id)
return Response(status=status.HTTP_204_NO_CONTENT)
diff --git a/apiserver/plane/space/views/base.py b/apiserver/plane/space/views/base.py
index 6b18a1546..82809f08d 100644
--- a/apiserver/plane/space/views/base.py
+++ b/apiserver/plane/space/views/base.py
@@ -41,18 +41,11 @@ class TimezoneMixin:
class BaseViewSet(TimezoneMixin, ModelViewSet, BasePaginator):
model = None
- permission_classes = [
- IsAuthenticated,
- ]
+ permission_classes = [IsAuthenticated]
- filter_backends = (
- DjangoFilterBackend,
- SearchFilter,
- )
+ filter_backends = (DjangoFilterBackend, SearchFilter)
- authentication_classes = [
- BaseSessionAuthentication,
- ]
+ authentication_classes = [BaseSessionAuthentication]
filterset_fields = []
@@ -63,9 +56,7 @@ class BaseViewSet(TimezoneMixin, ModelViewSet, BasePaginator):
return self.model.objects.all()
except Exception as e:
log_exception(e)
- raise APIException(
- "Please check the view", status.HTTP_400_BAD_REQUEST
- )
+ raise APIException("Please check the view", status.HTTP_400_BAD_REQUEST)
def handle_exception(self, exc):
"""
@@ -138,22 +129,15 @@ class BaseViewSet(TimezoneMixin, ModelViewSet, BasePaginator):
class BaseAPIView(TimezoneMixin, APIView, BasePaginator):
- permission_classes = [
- IsAuthenticated,
- ]
+ permission_classes = [IsAuthenticated]
- filter_backends = (
- DjangoFilterBackend,
- SearchFilter,
- )
+ filter_backends = (DjangoFilterBackend, SearchFilter)
filterset_fields = []
search_fields = []
- authentication_classes = [
- BaseSessionAuthentication,
- ]
+ authentication_classes = [BaseSessionAuthentication]
def filter_queryset(self, queryset):
for backend in list(self.filter_backends):
diff --git a/apiserver/plane/space/views/cycle.py b/apiserver/plane/space/views/cycle.py
index 49cc82e89..399d626a1 100644
--- a/apiserver/plane/space/views/cycle.py
+++ b/apiserver/plane/space/views/cycle.py
@@ -5,23 +5,17 @@ from rest_framework.response import Response
# Module imports
from .base import BaseAPIView
-from plane.db.models import (
- DeployBoard,
- Cycle,
-)
+from plane.db.models import DeployBoard, Cycle
class ProjectCyclesEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request, anchor):
deploy_board = DeployBoard.objects.filter(anchor=anchor).first()
if not deploy_board:
return Response(
- {"error": "Invalid anchor"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Invalid anchor"}, status=status.HTTP_404_NOT_FOUND
)
cycles = Cycle.objects.filter(
@@ -29,7 +23,4 @@ class ProjectCyclesEndpoint(BaseAPIView):
project_id=deploy_board.project_id,
).values("id", "name")
- return Response(
- cycles,
- status=status.HTTP_200_OK,
- )
+ return Response(cycles, status=status.HTTP_200_OK)
diff --git a/apiserver/plane/space/views/intake.py b/apiserver/plane/space/views/intake.py
index d9b12b022..0d39dd276 100644
--- a/apiserver/plane/space/views/intake.py
+++ b/apiserver/plane/space/views/intake.py
@@ -12,14 +12,7 @@ from rest_framework.response import Response
# Module imports
from .base import BaseViewSet
-from plane.db.models import (
- IntakeIssue,
- Issue,
- State,
- IssueLink,
- FileAsset,
- DeployBoard,
-)
+from plane.db.models import IntakeIssue, Issue, State, IssueLink, FileAsset, DeployBoard
from plane.app.serializers import (
IssueSerializer,
IntakeIssueSerializer,
@@ -34,9 +27,7 @@ class IntakeIssuePublicViewSet(BaseViewSet):
serializer_class = IntakeIssueSerializer
model = IntakeIssue
- filterset_fields = [
- "status",
- ]
+ filterset_fields = ["status"]
def get_queryset(self):
project_deploy_board = DeployBoard.objects.get(
@@ -48,8 +39,7 @@ class IntakeIssuePublicViewSet(BaseViewSet):
super()
.get_queryset()
.filter(
- Q(snoozed_till__gte=timezone.now())
- | Q(snoozed_till__isnull=True),
+ Q(snoozed_till__gte=timezone.now()) | Q(snoozed_till__isnull=True),
project_id=self.kwargs.get("project_id"),
workspace__slug=self.kwargs.get("slug"),
intake_id=self.kwargs.get("intake_id"),
@@ -81,9 +71,7 @@ class IntakeIssuePublicViewSet(BaseViewSet):
.prefetch_related("assignees", "labels")
.order_by("issue_intake__snoozed_till", "issue_intake__status")
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -113,10 +101,7 @@ class IntakeIssuePublicViewSet(BaseViewSet):
)
)
issues_data = IssueStateIntakeSerializer(issues, many=True).data
- return Response(
- issues_data,
- status=status.HTTP_200_OK,
- )
+ return Response(issues_data, status=status.HTTP_200_OK)
def create(self, request, anchor, intake_id):
project_deploy_board = DeployBoard.objects.get(
@@ -130,8 +115,7 @@ class IntakeIssuePublicViewSet(BaseViewSet):
if not request.data.get("issue", {}).get("name", False):
return Response(
- {"error": "Name is required"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Name is required"}, status=status.HTTP_400_BAD_REQUEST
)
# Check for valid priority
@@ -143,8 +127,7 @@ class IntakeIssuePublicViewSet(BaseViewSet):
"none",
]:
return Response(
- {"error": "Invalid priority"},
- status=status.HTTP_400_BAD_REQUEST,
+ {"error": "Invalid priority"}, status=status.HTTP_400_BAD_REQUEST
)
# Create or get state
@@ -229,9 +212,7 @@ class IntakeIssuePublicViewSet(BaseViewSet):
"description": issue_data.get("description", issue.description),
}
- issue_serializer = IssueCreateSerializer(
- issue, data=issue_data, partial=True
- )
+ issue_serializer = IssueCreateSerializer(issue, data=issue_data, partial=True)
if issue_serializer.is_valid():
current_instance = issue
@@ -245,16 +226,13 @@ class IntakeIssuePublicViewSet(BaseViewSet):
issue_id=str(issue.id),
project_id=str(project_deploy_board.project_id),
current_instance=json.dumps(
- IssueSerializer(current_instance).data,
- cls=DjangoJSONEncoder,
+ IssueSerializer(current_instance).data, cls=DjangoJSONEncoder
),
epoch=int(timezone.now().timestamp()),
)
issue_serializer.save()
return Response(issue_serializer.data, status=status.HTTP_200_OK)
- return Response(
- issue_serializer.errors, status=status.HTTP_400_BAD_REQUEST
- )
+ return Response(issue_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def retrieve(self, request, anchor, intake_id, pk):
project_deploy_board = DeployBoard.objects.get(
diff --git a/apiserver/plane/space/views/issue.py b/apiserver/plane/space/views/issue.py
index f67b8ebf7..a1ab332f9 100644
--- a/apiserver/plane/space/views/issue.py
+++ b/apiserver/plane/space/views/issue.py
@@ -42,10 +42,7 @@ from plane.space.utils.grouper import (
from plane.utils.order_queryset import order_issue_queryset
-from plane.utils.paginator import (
- GroupedOffsetPaginator,
- SubGroupedOffsetPaginator,
-)
+from plane.utils.paginator import GroupedOffsetPaginator, SubGroupedOffsetPaginator
from plane.app.serializers import (
CommentReactionSerializer,
IssueCommentSerializer,
@@ -70,9 +67,7 @@ from plane.utils.issue_filters import issue_filters
class ProjectIssuesPublicEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request, anchor):
filters = issue_filters(request.query_params, "GET")
@@ -83,17 +78,14 @@ class ProjectIssuesPublicEndpoint(BaseAPIView):
).first()
if not deploy_board:
return Response(
- {"error": "Project is not published"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Project is not published"}, status=status.HTTP_404_NOT_FOUND
)
project_id = deploy_board.entity_identifier
slug = deploy_board.workspace.slug
issue_queryset = (
- Issue.issue_objects.filter(
- workspace__slug=slug, project_id=project_id
- )
+ Issue.issue_objects.filter(workspace__slug=slug, project_id=project_id)
.select_related("workspace", "project", "state", "parent")
.prefetch_related("assignees", "labels", "issue_module__module")
.prefetch_related(
@@ -103,10 +95,7 @@ class ProjectIssuesPublicEndpoint(BaseAPIView):
)
)
.prefetch_related(
- Prefetch(
- "votes",
- queryset=IssueVote.objects.select_related("actor"),
- )
+ Prefetch("votes", queryset=IssueVote.objects.select_related("actor"))
)
.annotate(
cycle_id=Subquery(
@@ -131,9 +120,7 @@ class ProjectIssuesPublicEndpoint(BaseAPIView):
.values("count")
)
.annotate(
- sub_issues_count=Issue.issue_objects.filter(
- parent=OuterRef("id")
- )
+ sub_issues_count=Issue.issue_objects.filter(parent=OuterRef("id"))
.order_by()
.annotate(count=Func(F("id"), function="Count"))
.values("count")
@@ -144,8 +131,7 @@ class ProjectIssuesPublicEndpoint(BaseAPIView):
# Issue queryset
issue_queryset, order_by_param = order_issue_queryset(
- issue_queryset=issue_queryset,
- order_by_param=order_by_param,
+ issue_queryset=issue_queryset, order_by_param=order_by_param
)
# Group by
@@ -154,9 +140,7 @@ class ProjectIssuesPublicEndpoint(BaseAPIView):
# issue queryset
issue_queryset = issue_queryset_grouper(
- queryset=issue_queryset,
- group_by=group_by,
- sub_group_by=sub_group_by,
+ queryset=issue_queryset, group_by=group_by, sub_group_by=sub_group_by
)
if group_by:
@@ -174,9 +158,7 @@ class ProjectIssuesPublicEndpoint(BaseAPIView):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=SubGroupedOffsetPaginator,
group_by_fields=issue_group_values(
@@ -209,9 +191,7 @@ class ProjectIssuesPublicEndpoint(BaseAPIView):
order_by=order_by_param,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
paginator_cls=GroupedOffsetPaginator,
group_by_fields=issue_group_values(
@@ -236,9 +216,7 @@ class ProjectIssuesPublicEndpoint(BaseAPIView):
request=request,
queryset=issue_queryset,
on_results=lambda issues: issue_on_results(
- group_by=group_by,
- issues=issues,
- sub_group_by=sub_group_by,
+ group_by=group_by, issues=issues, sub_group_by=sub_group_by
),
)
@@ -247,28 +225,20 @@ class IssueCommentPublicViewSet(BaseViewSet):
serializer_class = IssueCommentSerializer
model = IssueComment
- filterset_fields = [
- "issue__id",
- "workspace__id",
- ]
+ filterset_fields = ["issue__id", "workspace__id"]
def get_permissions(self):
if self.action in ["list", "retrieve"]:
- self.permission_classes = [
- AllowAny,
- ]
+ self.permission_classes = [AllowAny]
else:
- self.permission_classes = [
- IsAuthenticated,
- ]
+ self.permission_classes = [IsAuthenticated]
return super(IssueCommentPublicViewSet, self).get_permissions()
def get_queryset(self):
try:
project_deploy_board = DeployBoard.objects.get(
- anchor=self.kwargs.get("anchor"),
- entity_name="project",
+ anchor=self.kwargs.get("anchor"), entity_name="project"
)
if project_deploy_board.is_comments_enabled:
return self.filter_queryset(
@@ -317,9 +287,7 @@ class IssueCommentPublicViewSet(BaseViewSet):
)
issue_activity.delay(
type="comment.activity.created",
- requested_data=json.dumps(
- serializer.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(serializer.data, cls=DjangoJSONEncoder),
actor_id=str(request.user.id),
issue_id=str(issue_id),
project_id=str(project_deploy_board.project_id),
@@ -333,8 +301,7 @@ class IssueCommentPublicViewSet(BaseViewSet):
).exists():
# Add the user for workspace tracking
_ = ProjectPublicMember.objects.get_or_create(
- project_id=project_deploy_board.project_id,
- member=request.user,
+ project_id=project_deploy_board.project_id, member=request.user
)
return Response(serializer.data, status=status.HTTP_201_CREATED)
@@ -351,9 +318,7 @@ class IssueCommentPublicViewSet(BaseViewSet):
status=status.HTTP_400_BAD_REQUEST,
)
comment = IssueComment.objects.get(pk=pk, actor=request.user)
- serializer = IssueCommentSerializer(
- comment, data=request.data, partial=True
- )
+ serializer = IssueCommentSerializer(comment, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
issue_activity.delay(
@@ -363,8 +328,7 @@ class IssueCommentPublicViewSet(BaseViewSet):
issue_id=str(issue_id),
project_id=str(project_deploy_board.project_id),
current_instance=json.dumps(
- IssueCommentSerializer(comment).data,
- cls=DjangoJSONEncoder,
+ IssueCommentSerializer(comment).data, cls=DjangoJSONEncoder
),
epoch=int(timezone.now().timestamp()),
)
@@ -381,10 +345,7 @@ class IssueCommentPublicViewSet(BaseViewSet):
{"error": "Comments are not enabled for this project"},
status=status.HTTP_400_BAD_REQUEST,
)
- comment = IssueComment.objects.get(
- pk=pk,
- actor=request.user,
- )
+ comment = IssueComment.objects.get(pk=pk, actor=request.user)
issue_activity.delay(
type="comment.activity.deleted",
requested_data=json.dumps({"comment_id": str(pk)}),
@@ -392,8 +353,7 @@ class IssueCommentPublicViewSet(BaseViewSet):
issue_id=str(issue_id),
project_id=str(project_deploy_board.project_id),
current_instance=json.dumps(
- IssueCommentSerializer(comment).data,
- cls=DjangoJSONEncoder,
+ IssueCommentSerializer(comment).data, cls=DjangoJSONEncoder
),
epoch=int(timezone.now().timestamp()),
)
@@ -450,14 +410,11 @@ class IssueReactionPublicViewSet(BaseViewSet):
).exists():
# Add the user for workspace tracking
_ = ProjectPublicMember.objects.get_or_create(
- project_id=project_deploy_board.project_id,
- member=request.user,
+ project_id=project_deploy_board.project_id, member=request.user
)
issue_activity.delay(
type="issue_reaction.activity.created",
- requested_data=json.dumps(
- self.request.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(self.request.data, cls=DjangoJSONEncoder),
actor_id=str(self.request.user.id),
issue_id=str(self.kwargs.get("issue_id", None)),
project_id=str(project_deploy_board.project_id),
@@ -490,10 +447,7 @@ class IssueReactionPublicViewSet(BaseViewSet):
issue_id=str(self.kwargs.get("issue_id", None)),
project_id=str(project_deploy_board.project_id),
current_instance=json.dumps(
- {
- "reaction": str(reaction_code),
- "identifier": str(issue_reaction.id),
- }
+ {"reaction": str(reaction_code), "identifier": str(issue_reaction.id)}
),
epoch=int(timezone.now().timestamp()),
)
@@ -549,14 +503,11 @@ class CommentReactionPublicViewSet(BaseViewSet):
).exists():
# Add the user for workspace tracking
_ = ProjectPublicMember.objects.get_or_create(
- project_id=project_deploy_board.project_id,
- member=request.user,
+ project_id=project_deploy_board.project_id, member=request.user
)
issue_activity.delay(
type="comment_reaction.activity.created",
- requested_data=json.dumps(
- self.request.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(self.request.data, cls=DjangoJSONEncoder),
actor_id=str(self.request.user.id),
issue_id=None,
project_id=str(self.kwargs.get("project_id", None)),
@@ -609,8 +560,7 @@ class IssueVotePublicViewSet(BaseViewSet):
def get_queryset(self):
try:
project_deploy_board = DeployBoard.objects.get(
- workspace__slug=self.kwargs.get("anchor"),
- entity_name="project",
+ workspace__slug=self.kwargs.get("anchor"), entity_name="project"
)
if project_deploy_board.is_votes_enabled:
return (
@@ -640,16 +590,13 @@ class IssueVotePublicViewSet(BaseViewSet):
is_active=True,
).exists():
_ = ProjectPublicMember.objects.get_or_create(
- project_id=project_deploy_board.project_id,
- member=request.user,
+ project_id=project_deploy_board.project_id, member=request.user
)
issue_vote.vote = request.data.get("vote", 1)
issue_vote.save()
issue_activity.delay(
type="issue_vote.activity.created",
- requested_data=json.dumps(
- self.request.data, cls=DjangoJSONEncoder
- ),
+ requested_data=json.dumps(self.request.data, cls=DjangoJSONEncoder),
actor_id=str(self.request.user.id),
issue_id=str(self.kwargs.get("issue_id", None)),
project_id=str(project_deploy_board.project_id),
@@ -676,10 +623,7 @@ class IssueVotePublicViewSet(BaseViewSet):
issue_id=str(self.kwargs.get("issue_id", None)),
project_id=str(project_deploy_board.project_id),
current_instance=json.dumps(
- {
- "vote": str(issue_vote.vote),
- "identifier": str(issue_vote.id),
- }
+ {"vote": str(issue_vote.vote), "identifier": str(issue_vote.id)}
),
epoch=int(timezone.now().timestamp()),
)
@@ -688,9 +632,7 @@ class IssueVotePublicViewSet(BaseViewSet):
class IssueRetrievePublicEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request, anchor, issue_id):
deploy_board = DeployBoard.objects.get(anchor=anchor)
@@ -717,7 +659,7 @@ class IssueRetrievePublicEndpoint(BaseAPIView):
distinct=True,
filter=Q(
~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ & Q(label_issue__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
@@ -748,16 +690,11 @@ class IssueRetrievePublicEndpoint(BaseAPIView):
.prefetch_related(
Prefetch(
"issue_reactions",
- queryset=IssueReaction.objects.select_related(
- "issue", "actor"
- ),
+ queryset=IssueReaction.objects.select_related("issue", "actor"),
)
)
.prefetch_related(
- Prefetch(
- "votes",
- queryset=IssueVote.objects.select_related("actor"),
- )
+ Prefetch("votes", queryset=IssueVote.objects.select_related("actor"))
)
.annotate(
vote_items=ArrayAgg(
@@ -775,12 +712,8 @@ class IssueRetrievePublicEndpoint(BaseAPIView):
When(
votes__actor__avatar_asset__isnull=False,
then=Concat(
- Value(
- "/api/assets/v2/static/"
- ),
- F(
- "votes__actor__avatar_asset"
- ),
+ Value("/api/assets/v2/static/"),
+ F("votes__actor__avatar_asset"),
Value("/"),
),
),
@@ -791,9 +724,7 @@ class IssueRetrievePublicEndpoint(BaseAPIView):
default=Value(None),
output_field=CharField(),
),
- display_name=F(
- "votes__actor__display_name"
- ),
+ display_name=F("votes__actor__display_name"),
),
),
),
@@ -815,23 +746,15 @@ class IssueRetrievePublicEndpoint(BaseAPIView):
reaction=F("issue_reactions__reaction"),
actor_details=JSONObject(
id=F("issue_reactions__actor__id"),
- first_name=F(
- "issue_reactions__actor__first_name"
- ),
- last_name=F(
- "issue_reactions__actor__last_name"
- ),
+ first_name=F("issue_reactions__actor__first_name"),
+ last_name=F("issue_reactions__actor__last_name"),
avatar=F("issue_reactions__actor__avatar"),
avatar_url=Case(
When(
votes__actor__avatar_asset__isnull=False,
then=Concat(
- Value(
- "/api/assets/v2/static/"
- ),
- F(
- "votes__actor__avatar_asset"
- ),
+ Value("/api/assets/v2/static/"),
+ F("votes__actor__avatar_asset"),
Value("/"),
),
),
diff --git a/apiserver/plane/space/views/label.py b/apiserver/plane/space/views/label.py
index 2e0f99b7c..ad0c8f0ca 100644
--- a/apiserver/plane/space/views/label.py
+++ b/apiserver/plane/space/views/label.py
@@ -5,23 +5,17 @@ from rest_framework.permissions import AllowAny
# Module imports
from .base import BaseAPIView
-from plane.db.models import (
- DeployBoard,
- Label,
-)
+from plane.db.models import DeployBoard, Label
class ProjectLabelsEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request, anchor):
deploy_board = DeployBoard.objects.filter(anchor=anchor).first()
if not deploy_board:
return Response(
- {"error": "Invalid anchor"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Invalid anchor"}, status=status.HTTP_404_NOT_FOUND
)
labels = Label.objects.filter(
@@ -29,7 +23,4 @@ class ProjectLabelsEndpoint(BaseAPIView):
project_id=deploy_board.project_id,
).values("id", "name", "color", "parent")
- return Response(
- labels,
- status=status.HTTP_200_OK,
- )
+ return Response(labels, status=status.HTTP_200_OK)
diff --git a/apiserver/plane/space/views/module.py b/apiserver/plane/space/views/module.py
index f52f42331..7db676537 100644
--- a/apiserver/plane/space/views/module.py
+++ b/apiserver/plane/space/views/module.py
@@ -5,23 +5,17 @@ from rest_framework.response import Response
# Module imports
from .base import BaseAPIView
-from plane.db.models import (
- DeployBoard,
- Module,
-)
+from plane.db.models import DeployBoard, Module
class ProjectModulesEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request, anchor):
deploy_board = DeployBoard.objects.filter(anchor=anchor).first()
if not deploy_board:
return Response(
- {"error": "Invalid anchor"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Invalid anchor"}, status=status.HTTP_404_NOT_FOUND
)
modules = Module.objects.filter(
@@ -29,7 +23,4 @@ class ProjectModulesEndpoint(BaseAPIView):
project_id=deploy_board.project_id,
).values("id", "name")
- return Response(
- modules,
- status=status.HTTP_200_OK,
- )
+ return Response(modules, status=status.HTTP_200_OK)
diff --git a/apiserver/plane/space/views/project.py b/apiserver/plane/space/views/project.py
index f1606a798..1574871ef 100644
--- a/apiserver/plane/space/views/project.py
+++ b/apiserver/plane/space/views/project.py
@@ -1,8 +1,5 @@
# Django imports
-from django.db.models import (
- Exists,
- OuterRef,
-)
+from django.db.models import Exists, OuterRef
# Third Party imports
from rest_framework.response import Response
@@ -16,9 +13,7 @@ from plane.db.models import Project, DeployBoard, ProjectMember
class ProjectDeployBoardPublicSettingsEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request, anchor):
project_deploy_board = DeployBoard.objects.get(
@@ -29,9 +24,7 @@ class ProjectDeployBoardPublicSettingsEndpoint(BaseAPIView):
class WorkspaceProjectDeployBoardEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request, anchor):
deploy_board = DeployBoard.objects.filter(
@@ -42,9 +35,7 @@ class WorkspaceProjectDeployBoardEndpoint(BaseAPIView):
.annotate(
is_public=Exists(
DeployBoard.objects.filter(
- anchor=anchor,
- project_id=OuterRef("pk"),
- entity_name="project",
+ anchor=anchor, project_id=OuterRef("pk"), entity_name="project"
)
)
)
@@ -63,9 +54,7 @@ class WorkspaceProjectDeployBoardEndpoint(BaseAPIView):
class WorkspaceProjectAnchorEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request, slug, project_id):
project_deploy_board = DeployBoard.objects.get(
@@ -76,9 +65,7 @@ class WorkspaceProjectAnchorEndpoint(BaseAPIView):
class ProjectMembersEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request, anchor):
deploy_board = DeployBoard.objects.filter(anchor=anchor).first()
diff --git a/apiserver/plane/space/views/state.py b/apiserver/plane/space/views/state.py
index 7ffcef5b9..39f2b1bfd 100644
--- a/apiserver/plane/space/views/state.py
+++ b/apiserver/plane/space/views/state.py
@@ -8,23 +8,17 @@ from rest_framework.response import Response
# Module imports
from .base import BaseAPIView
-from plane.db.models import (
- DeployBoard,
- State,
-)
+from plane.db.models import DeployBoard, State
class ProjectStatesEndpoint(BaseAPIView):
- permission_classes = [
- AllowAny,
- ]
+ permission_classes = [AllowAny]
def get(self, request, anchor):
deploy_board = DeployBoard.objects.filter(anchor=anchor).first()
if not deploy_board:
return Response(
- {"error": "Invalid anchor"},
- status=status.HTTP_404_NOT_FOUND,
+ {"error": "Invalid anchor"}, status=status.HTTP_404_NOT_FOUND
)
states = State.objects.filter(
@@ -33,7 +27,4 @@ class ProjectStatesEndpoint(BaseAPIView):
project_id=deploy_board.project_id,
).values("name", "group", "color", "id", "sequence")
- return Response(
- states,
- status=status.HTTP_200_OK,
- )
+ return Response(states, status=status.HTTP_200_OK)
diff --git a/apiserver/plane/tests/api/base.py b/apiserver/plane/tests/api/base.py
index f6843c1b6..e3209a281 100644
--- a/apiserver/plane/tests/api/base.py
+++ b/apiserver/plane/tests/api/base.py
@@ -8,9 +8,7 @@ from plane.app.views.authentication import get_tokens_for_user
class BaseAPITest(APITestCase):
def setUp(self):
- self.client = APIClient(
- HTTP_USER_AGENT="plane/test", REMOTE_ADDR="10.10.10.10"
- )
+ self.client = APIClient(HTTP_USER_AGENT="plane/test", REMOTE_ADDR="10.10.10.10")
class AuthenticatedAPITest(BaseAPITest):
diff --git a/apiserver/plane/tests/api/test_authentication.py b/apiserver/plane/tests/api/test_authentication.py
index 36a0f7a24..5d7beabdf 100644
--- a/apiserver/plane/tests/api/test_authentication.py
+++ b/apiserver/plane/tests/api/test_authentication.py
@@ -28,9 +28,7 @@ class SignInEndpointTests(BaseAPITest):
def test_email_validity(self):
url = reverse("sign-in")
response = self.client.post(
- url,
- {"email": "useremail.com", "password": "user@123"},
- format="json",
+ url, {"email": "useremail.com", "password": "user@123"}, format="json"
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
@@ -40,9 +38,7 @@ class SignInEndpointTests(BaseAPITest):
def test_password_validity(self):
url = reverse("sign-in")
response = self.client.post(
- url,
- {"email": "user@plane.so", "password": "user123"},
- format="json",
+ url, {"email": "user@plane.so", "password": "user123"}, format="json"
)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(
@@ -55,9 +51,7 @@ class SignInEndpointTests(BaseAPITest):
def test_user_exists(self):
url = reverse("sign-in")
response = self.client.post(
- url,
- {"email": "user@email.so", "password": "user123"},
- format="json",
+ url, {"email": "user@email.so", "password": "user123"}, format="json"
)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(
@@ -71,16 +65,11 @@ class SignInEndpointTests(BaseAPITest):
url = reverse("sign-in")
response = self.client.post(
- url,
- {"email": "user@plane.so", "password": "user@123"},
- format="json",
+ url, {"email": "user@plane.so", "password": "user@123"}, format="json"
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(
- response.data.get("user").get("email"),
- "user@plane.so",
- )
+ self.assertEqual(response.data.get("user").get("email"), "user@plane.so")
class MagicLinkGenerateEndpointTests(BaseAPITest):
@@ -97,9 +86,7 @@ class MagicLinkGenerateEndpointTests(BaseAPITest):
def test_email_validity(self):
url = reverse("magic-generate")
- response = self.client.post(
- url, {"email": "useremail.com"}, format="json"
- )
+ response = self.client.post(url, {"email": "useremail.com"}, format="json")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
response.data, {"error": "Please provide a valid email address."}
@@ -111,9 +98,7 @@ class MagicLinkGenerateEndpointTests(BaseAPITest):
ri = redis_instance()
ri.delete("magic_user@plane.so")
- response = self.client.post(
- url, {"email": "user@plane.so"}, format="json"
- )
+ response = self.client.post(url, {"email": "user@plane.so"}, format="json")
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_max_generate_attempt(self):
@@ -123,22 +108,13 @@ class MagicLinkGenerateEndpointTests(BaseAPITest):
ri.delete("magic_user@plane.so")
for _ in range(4):
- response = self.client.post(
- url,
- {"email": "user@plane.so"},
- format="json",
- )
+ response = self.client.post(url, {"email": "user@plane.so"}, format="json")
- response = self.client.post(
- url,
- {"email": "user@plane.so"},
- format="json",
- )
+ response = self.client.post(url, {"email": "user@plane.so"}, format="json")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
- response.data,
- {"error": "Max attempts exhausted. Please try again later."},
+ response.data, {"error": "Max attempts exhausted. Please try again later."}
)
@@ -153,9 +129,7 @@ class MagicSignInEndpointTests(BaseAPITest):
url = reverse("magic-sign-in")
response = self.client.post(url, {}, format="json")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
- self.assertEqual(
- response.data, {"error": "User token and key are required"}
- )
+ self.assertEqual(response.data, {"error": "User token and key are required"})
def test_expired_invalid_magic_link(self):
ri = redis_instance()
@@ -169,8 +143,7 @@ class MagicSignInEndpointTests(BaseAPITest):
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
- response.data,
- {"error": "The magic code/link has expired please try again"},
+ response.data, {"error": "The magic code/link has expired please try again"}
)
def test_invalid_magic_code(self):
@@ -188,8 +161,7 @@ class MagicSignInEndpointTests(BaseAPITest):
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
- response.data,
- {"error": "Your login code was incorrect. Please try again."},
+ response.data, {"error": "Your login code was incorrect. Please try again."}
)
def test_magic_code_sign_in(self):
@@ -205,12 +177,7 @@ class MagicSignInEndpointTests(BaseAPITest):
url = reverse("magic-sign-in")
response = self.client.post(
- url,
- {"key": "magic_user@plane.so", "token": token},
- format="json",
+ url, {"key": "magic_user@plane.so", "token": token}, format="json"
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
- self.assertEqual(
- response.data.get("user").get("email"),
- "user@plane.so",
- )
+ self.assertEqual(response.data.get("user").get("email"), "user@plane.so")
diff --git a/apiserver/plane/urls.py b/apiserver/plane/urls.py
index aac6459b3..e3870a393 100644
--- a/apiserver/plane/urls.py
+++ b/apiserver/plane/urls.py
@@ -1,6 +1,4 @@
-"""plane URL Configuration
-
-"""
+"""plane URL Configuration"""
from django.conf import settings
from django.urls import include, path, re_path
@@ -24,7 +22,7 @@ if settings.DEBUG:
import debug_toolbar
urlpatterns = [
- re_path(r"^__debug__/", include(debug_toolbar.urls)),
+ re_path(r"^__debug__/", include(debug_toolbar.urls))
] + urlpatterns
except ImportError:
pass
diff --git a/apiserver/plane/utils/analytics_plot.py b/apiserver/plane/utils/analytics_plot.py
index 2bf2210ec..7527a3524 100644
--- a/apiserver/plane/utils/analytics_plot.py
+++ b/apiserver/plane/utils/analytics_plot.py
@@ -4,16 +4,7 @@ from itertools import groupby
# Django import
from django.db import models
-from django.db.models import (
- Case,
- CharField,
- Count,
- F,
- Sum,
- Value,
- When,
- FloatField,
-)
+from django.db.models import Case, CharField, Count, F, Sum, Value, When, FloatField
from django.db.models.functions import (
Coalesce,
Concat,
@@ -41,9 +32,7 @@ def annotate_with_monthly_dimension(queryset, field_name, attribute):
def extract_axis(queryset, x_axis):
# Format the dimension when the axis is in date
if x_axis in ["created_at", "start_date", "target_date", "completed_at"]:
- queryset = annotate_with_monthly_dimension(
- queryset, x_axis, "dimension"
- )
+ queryset = annotate_with_monthly_dimension(queryset, x_axis, "dimension")
return queryset, "dimension"
else:
return queryset.annotate(dimension=F(x_axis)), "dimension"
@@ -68,9 +57,7 @@ def build_graph_plot(queryset, x_axis, y_axis, segment=None):
#
if segment in ["created_at", "start_date", "target_date", "completed_at"]:
- queryset = annotate_with_monthly_dimension(
- queryset, segment, "segmented"
- )
+ queryset = annotate_with_monthly_dimension(queryset, segment, "segmented")
segment = "segmented"
queryset = queryset.values(x_axis)
@@ -85,9 +72,7 @@ def build_graph_plot(queryset, x_axis, y_axis, segment=None):
),
dimension_ex=Coalesce("dimension", Value("null")),
).values("dimension")
- queryset = (
- queryset.annotate(segment=F(segment)) if segment else queryset
- )
+ queryset = queryset.annotate(segment=F(segment)) if segment else queryset
queryset = (
queryset.values("dimension", "segment")
if segment
@@ -100,9 +85,7 @@ def build_graph_plot(queryset, x_axis, y_axis, segment=None):
queryset = queryset.annotate(
estimate=Sum(Cast("estimate_point__value", FloatField()))
).order_by(x_axis)
- queryset = (
- queryset.annotate(segment=F(segment)) if segment else queryset
- )
+ queryset = queryset.annotate(segment=F(segment)) if segment else queryset
queryset = (
queryset.values("dimension", "segment", "estimate")
if segment
@@ -112,22 +95,13 @@ def build_graph_plot(queryset, x_axis, y_axis, segment=None):
result_values = list(queryset)
grouped_data = {
str(key): list(items)
- for key, items in groupby(
- result_values, key=lambda x: x[str("dimension")]
- )
+ for key, items in groupby(result_values, key=lambda x: x[str("dimension")])
}
return sort_data(grouped_data, temp_axis)
-def burndown_plot(
- queryset,
- slug,
- project_id,
- plot_type,
- cycle_id=None,
- module_id=None,
-):
+def burndown_plot(queryset, slug, project_id, plot_type, cycle_id=None, module_id=None):
# Total Issues in Cycle or Module
total_issues = queryset.total_issues
# check whether the estimate is a point or not
@@ -166,9 +140,7 @@ def burndown_plot(
# Get all dates between the two dates
date_range = [
(queryset.start_date + timedelta(days=x)).date()
- for x in range(
- (queryset.end_date - queryset.start_date).days + 1
- )
+ for x in range((queryset.end_date - queryset.start_date).days + 1)
]
else:
date_range = []
@@ -208,9 +180,7 @@ def burndown_plot(
# Get all dates between the two dates
date_range = [
(queryset.start_date + timedelta(days=x))
- for x in range(
- (queryset.target_date - queryset.start_date).days + 1
- )
+ for x in range((queryset.target_date - queryset.start_date).days + 1)
]
chart_data = {str(date): 0 for date in date_range}
diff --git a/apiserver/plane/utils/cache.py b/apiserver/plane/utils/cache.py
index bda942899..1b3e2cb1c 100644
--- a/apiserver/plane/utils/cache.py
+++ b/apiserver/plane/utils/cache.py
@@ -28,16 +28,16 @@ def cache_response(timeout=60 * 60, path=None, user=True):
auth_header = (
None
if request.user.is_anonymous
- else str(request.user.id) if user else None
+ else str(request.user.id)
+ if user
+ else None
)
custom_path = path if path is not None else request.get_full_path()
key = generate_cache_key(custom_path, auth_header)
cached_result = cache.get(key)
if cached_result is not None:
- return Response(
- cached_result["data"], status=cached_result["status"]
- )
+ return Response(cached_result["data"], status=cached_result["status"])
response = view_func(instance, request, *args, **kwargs)
if response.status_code == 200 and not settings.DEBUG:
cache.set(
@@ -67,7 +67,9 @@ def invalidate_cache_directly(
auth_header = (
None
if request and request.user.is_anonymous
- else str(request.user.id) if user else None
+ else str(request.user.id)
+ if user
+ else None
)
key = generate_cache_key(custom_path, auth_header)
diff --git a/apiserver/plane/utils/global_paginator.py b/apiserver/plane/utils/global_paginator.py
index e9ed735d5..338d86117 100644
--- a/apiserver/plane/utils/global_paginator.py
+++ b/apiserver/plane/utils/global_paginator.py
@@ -20,9 +20,7 @@ class PaginateCursor:
try:
bits = value.split(":")
if len(bits) != 3:
- raise ValueError(
- "Cursor must be in the format 'value:offset:is_prev'"
- )
+ raise ValueError("Cursor must be in the format 'value:offset:is_prev'")
return self(int(bits[0]), int(bits[1]), int(bits[2]))
except (TypeError, ValueError) as e:
raise ValueError(f"Invalid cursor format: {e}")
diff --git a/apiserver/plane/utils/grouper.py b/apiserver/plane/utils/grouper.py
index 38ac74a16..e139cdcc5 100644
--- a/apiserver/plane/utils/grouper.py
+++ b/apiserver/plane/utils/grouper.py
@@ -27,13 +27,11 @@ def issue_queryset_grouper(queryset, group_by, sub_group_by):
annotations_map = {
"assignee_ids": (
"assignees__id",
- ~Q(assignees__id__isnull=True)
- & Q(issue_assignee__deleted_at__isnull=True),
+ ~Q(assignees__id__isnull=True) & Q(issue_assignee__deleted_at__isnull=True),
),
"label_ids": (
"labels__id",
- ~Q(labels__id__isnull=True)
- & Q(label_issue__deleted_at__isnull=True),
+ ~Q(labels__id__isnull=True) & Q(label_issue__deleted_at__isnull=True),
),
"module_ids": (
"issue_module__module_id",
@@ -46,16 +44,11 @@ def issue_queryset_grouper(queryset, group_by, sub_group_by):
}
default_annotations = {
key: Coalesce(
- ArrayAgg(
- field,
- distinct=True,
- filter=condition,
- ),
+ ArrayAgg(field, distinct=True, filter=condition),
Value([], output_field=ArrayField(UUIDField())),
)
for key, (field, condition) in annotations_map.items()
- if FIELD_MAPPER.get(key) != group_by
- or FIELD_MAPPER.get(key) != sub_group_by
+ if FIELD_MAPPER.get(key) != group_by or FIELD_MAPPER.get(key) != sub_group_by
}
return queryset.annotate(**default_annotations)
@@ -111,8 +104,7 @@ def issue_on_results(issues, group_by, sub_group_by):
def issue_group_values(field, slug, project_id=None, filters=dict):
if field == "state_id":
queryset = State.objects.filter(
- is_triage=False,
- workspace__slug=slug,
+ is_triage=False, workspace__slug=slug
).values_list("id", flat=True)
if project_id:
return list(queryset.filter(project_id=project_id))
@@ -129,9 +121,7 @@ def issue_group_values(field, slug, project_id=None, filters=dict):
if field == "assignees__id":
if project_id:
return ProjectMember.objects.filter(
- workspace__slug=slug,
- project_id=project_id,
- is_active=True,
+ workspace__slug=slug, project_id=project_id, is_active=True
).values_list("member_id", flat=True)
else:
return list(
@@ -140,17 +130,17 @@ def issue_group_values(field, slug, project_id=None, filters=dict):
).values_list("member_id", flat=True)
)
if field == "issue_module__module_id":
- queryset = Module.objects.filter(
- workspace__slug=slug,
- ).values_list("id", flat=True)
+ queryset = Module.objects.filter(workspace__slug=slug).values_list(
+ "id", flat=True
+ )
if project_id:
return list(queryset.filter(project_id=project_id)) + ["None"]
else:
return list(queryset) + ["None"]
if field == "cycle_id":
- queryset = Cycle.objects.filter(
- workspace__slug=slug,
- ).values_list("id", flat=True)
+ queryset = Cycle.objects.filter(workspace__slug=slug).values_list(
+ "id", flat=True
+ )
if project_id:
return list(queryset.filter(project_id=project_id)) + ["None"]
else:
@@ -161,21 +151,9 @@ def issue_group_values(field, slug, project_id=None, filters=dict):
)
return list(queryset)
if field == "priority":
- return [
- "low",
- "medium",
- "high",
- "urgent",
- "none",
- ]
+ return ["low", "medium", "high", "urgent", "none"]
if field == "state__group":
- return [
- "backlog",
- "unstarted",
- "started",
- "completed",
- "cancelled",
- ]
+ return ["backlog", "unstarted", "started", "completed", "cancelled"]
if field == "target_date":
queryset = (
Issue.issue_objects.filter(workspace__slug=slug)
diff --git a/apiserver/plane/utils/imports.py b/apiserver/plane/utils/imports.py
index 89753ef1d..81de0203b 100644
--- a/apiserver/plane/utils/imports.py
+++ b/apiserver/plane/utils/imports.py
@@ -7,9 +7,7 @@ def import_submodules(context, root_module, path):
Import all submodules and register them in the ``context`` namespace.
>>> import_submodules(locals(), __name__, __path__)
"""
- for loader, module_name, is_pkg in pkgutil.walk_packages(
- path, root_module + "."
- ):
+ for loader, module_name, is_pkg in pkgutil.walk_packages(path, root_module + "."):
# this causes a Runtime error with model conflicts
# module = loader.find_module(module_name).load_module(module_name)
module = __import__(module_name, globals(), locals(), ["__name__"])
diff --git a/apiserver/plane/utils/issue_filters.py b/apiserver/plane/utils/issue_filters.py
index 5b1e70e44..01b2024e4 100644
--- a/apiserver/plane/utils/issue_filters.py
+++ b/apiserver/plane/utils/issue_filters.py
@@ -22,9 +22,7 @@ def filter_valid_uuids(uuid_list):
# Get the 2_weeks, 3_months
-def string_date_filter(
- issue_filter, duration, subsequent, term, date_filter, offset
-):
+def string_date_filter(issue_filter, duration, subsequent, term, date_filter, offset):
now = timezone.now().date()
if term == "months":
if subsequent == "after":
@@ -48,22 +46,14 @@ def string_date_filter(
if term == "weeks":
if subsequent == "after":
if offset == "fromnow":
- issue_filter[f"{date_filter}__gte"] = now + timedelta(
- weeks=duration
- )
+ issue_filter[f"{date_filter}__gte"] = now + timedelta(weeks=duration)
else:
- issue_filter[f"{date_filter}__gte"] = now - timedelta(
- weeks=duration
- )
+ issue_filter[f"{date_filter}__gte"] = now - timedelta(weeks=duration)
else:
if offset == "fromnow":
- issue_filter[f"{date_filter}__lte"] = now + timedelta(
- weeks=duration
- )
+ issue_filter[f"{date_filter}__lte"] = now + timedelta(weeks=duration)
else:
- issue_filter[f"{date_filter}__lte"] = now - timedelta(
- weeks=duration
- )
+ issue_filter[f"{date_filter}__lte"] = now - timedelta(weeks=duration)
def date_filter(issue_filter, date_term, queries):
@@ -97,9 +87,7 @@ def date_filter(issue_filter, date_term, queries):
def filter_state(params, issue_filter, method, prefix=""):
if method == "GET":
- states = [
- item for item in params.get("state").split(",") if item != "null"
- ]
+ states = [item for item in params.get("state").split(",") if item != "null"]
states = filter_valid_uuids(states)
if len(states) and "" not in states:
issue_filter[f"{prefix}state__in"] = states
@@ -116,9 +104,7 @@ def filter_state(params, issue_filter, method, prefix=""):
def filter_state_group(params, issue_filter, method, prefix=""):
if method == "GET":
state_group = [
- item
- for item in params.get("state_group").split(",")
- if item != "null"
+ item for item in params.get("state_group").split(",") if item != "null"
]
if len(state_group) and "" not in state_group:
issue_filter[f"{prefix}state__group__in"] = state_group
@@ -128,18 +114,14 @@ def filter_state_group(params, issue_filter, method, prefix=""):
and len(params.get("state_group"))
and params.get("state_group") != "null"
):
- issue_filter[f"{prefix}state__group__in"] = params.get(
- "state_group"
- )
+ issue_filter[f"{prefix}state__group__in"] = params.get("state_group")
return issue_filter
def filter_estimate_point(params, issue_filter, method, prefix=""):
if method == "GET":
estimate_points = [
- item
- for item in params.get("estimate_point").split(",")
- if item != "null"
+ item for item in params.get("estimate_point").split(",") if item != "null"
]
if len(estimate_points) and "" not in estimate_points:
issue_filter[f"{prefix}estimate_point__in"] = estimate_points
@@ -149,18 +131,14 @@ def filter_estimate_point(params, issue_filter, method, prefix=""):
and len(params.get("estimate_point"))
and params.get("estimate_point") != "null"
):
- issue_filter[f"{prefix}estimate_point__in"] = params.get(
- "estimate_point"
- )
+ issue_filter[f"{prefix}estimate_point__in"] = params.get("estimate_point")
return issue_filter
def filter_priority(params, issue_filter, method, prefix=""):
if method == "GET":
priorities = [
- item
- for item in params.get("priority").split(",")
- if item != "null"
+ item for item in params.get("priority").split(",") if item != "null"
]
if len(priorities) and "" not in priorities:
issue_filter[f"{prefix}priority__in"] = priorities
@@ -176,9 +154,7 @@ def filter_priority(params, issue_filter, method, prefix=""):
def filter_parent(params, issue_filter, method, prefix=""):
if method == "GET":
- parents = [
- item for item in params.get("parent").split(",") if item != "null"
- ]
+ parents = [item for item in params.get("parent").split(",") if item != "null"]
if "None" in parents:
issue_filter[f"{prefix}parent__isnull"] = True
parents = filter_valid_uuids(parents)
@@ -196,9 +172,7 @@ def filter_parent(params, issue_filter, method, prefix=""):
def filter_labels(params, issue_filter, method, prefix=""):
if method == "GET":
- labels = [
- item for item in params.get("labels").split(",") if item != "null"
- ]
+ labels = [item for item in params.get("labels").split(",") if item != "null"]
if "None" in labels:
issue_filter[f"{prefix}labels__isnull"] = True
labels = filter_valid_uuids(labels)
@@ -217,9 +191,7 @@ def filter_labels(params, issue_filter, method, prefix=""):
def filter_assignees(params, issue_filter, method, prefix=""):
if method == "GET":
assignees = [
- item
- for item in params.get("assignees").split(",")
- if item != "null"
+ item for item in params.get("assignees").split(",") if item != "null"
]
if "None" in assignees:
issue_filter[f"{prefix}assignees__isnull"] = True
@@ -240,9 +212,7 @@ def filter_assignees(params, issue_filter, method, prefix=""):
def filter_mentions(params, issue_filter, method, prefix=""):
if method == "GET":
mentions = [
- item
- for item in params.get("mentions").split(",")
- if item != "null"
+ item for item in params.get("mentions").split(",") if item != "null"
]
mentions = filter_valid_uuids(mentions)
if len(mentions) and "" not in mentions:
@@ -253,8 +223,8 @@ def filter_mentions(params, issue_filter, method, prefix=""):
and len(params.get("mentions"))
and params.get("mentions") != "null"
):
- issue_filter[f"{prefix}issue_mention__mention__id__in"] = (
- params.get("mentions")
+ issue_filter[f"{prefix}issue_mention__mention__id__in"] = params.get(
+ "mentions"
)
return issue_filter
@@ -262,9 +232,7 @@ def filter_mentions(params, issue_filter, method, prefix=""):
def filter_created_by(params, issue_filter, method, prefix=""):
if method == "GET":
created_bys = [
- item
- for item in params.get("created_by").split(",")
- if item != "null"
+ item for item in params.get("created_by").split(",") if item != "null"
]
if "None" in created_bys:
issue_filter[f"{prefix}created_by__isnull"] = True
@@ -365,9 +333,7 @@ def filter_completed_at(params, issue_filter, method, prefix=""):
queries=completed_ats,
)
else:
- if params.get("completed_at", None) and len(
- params.get("completed_at")
- ):
+ if params.get("completed_at", None) and len(params.get("completed_at")):
date_filter(
issue_filter=issue_filter,
date_term=f"{prefix}completed_at__date",
@@ -390,9 +356,7 @@ def filter_issue_state_type(params, issue_filter, method, prefix=""):
def filter_project(params, issue_filter, method, prefix=""):
if method == "GET":
- projects = [
- item for item in params.get("project").split(",") if item != "null"
- ]
+ projects = [item for item in params.get("project").split(",") if item != "null"]
projects = filter_valid_uuids(projects)
if len(projects) and "" not in projects:
issue_filter[f"{prefix}project__in"] = projects
@@ -408,9 +372,7 @@ def filter_project(params, issue_filter, method, prefix=""):
def filter_cycle(params, issue_filter, method, prefix=""):
if method == "GET":
- cycles = [
- item for item in params.get("cycle").split(",") if item != "null"
- ]
+ cycles = [item for item in params.get("cycle").split(",") if item != "null"]
if "None" in cycles:
issue_filter[f"{prefix}issue_cycle__cycle_id__isnull"] = True
cycles = filter_valid_uuids(cycles)
@@ -422,18 +384,14 @@ def filter_cycle(params, issue_filter, method, prefix=""):
and len(params.get("cycle"))
and params.get("cycle") != "null"
):
- issue_filter[f"{prefix}issue_cycle__cycle_id__in"] = params.get(
- "cycle"
- )
+ issue_filter[f"{prefix}issue_cycle__cycle_id__in"] = params.get("cycle")
issue_filter[f"{prefix}issue_cycle__deleted_at__isnull"] = True
return issue_filter
def filter_module(params, issue_filter, method, prefix=""):
if method == "GET":
- modules = [
- item for item in params.get("module").split(",") if item != "null"
- ]
+ modules = [item for item in params.get("module").split(",") if item != "null"]
if "None" in modules:
issue_filter[f"{prefix}issue_module__module_id__isnull"] = True
modules = filter_valid_uuids(modules)
@@ -445,9 +403,7 @@ def filter_module(params, issue_filter, method, prefix=""):
and len(params.get("module"))
and params.get("module") != "null"
):
- issue_filter[f"{prefix}issue_module__module_id__in"] = params.get(
- "module"
- )
+ issue_filter[f"{prefix}issue_module__module_id__in"] = params.get("module")
issue_filter[f"{prefix}issue_module__deleted_at__isnull"] = True
return issue_filter
@@ -455,9 +411,7 @@ def filter_module(params, issue_filter, method, prefix=""):
def filter_intake_status(params, issue_filter, method, prefix=""):
if method == "GET":
status = [
- item
- for item in params.get("intake_status").split(",")
- if item != "null"
+ item for item in params.get("intake_status").split(",") if item != "null"
]
if len(status) and "" not in status:
issue_filter[f"{prefix}issue_intake__status__in"] = status
@@ -476,9 +430,7 @@ def filter_intake_status(params, issue_filter, method, prefix=""):
def filter_inbox_status(params, issue_filter, method, prefix=""):
if method == "GET":
status = [
- item
- for item in params.get("inbox_status").split(",")
- if item != "null"
+ item for item in params.get("inbox_status").split(",") if item != "null"
]
if len(status) and "" not in status:
issue_filter[f"{prefix}issue_intake__status__in"] = status
@@ -509,23 +461,19 @@ def filter_sub_issue_toggle(params, issue_filter, method, prefix=""):
def filter_subscribed_issues(params, issue_filter, method, prefix=""):
if method == "GET":
subscribers = [
- item
- for item in params.get("subscriber").split(",")
- if item != "null"
+ item for item in params.get("subscriber").split(",") if item != "null"
]
subscribers = filter_valid_uuids(subscribers)
if len(subscribers) and "" not in subscribers:
- issue_filter[f"{prefix}issue_subscribers__subscriber_id__in"] = (
- subscribers
- )
+ issue_filter[f"{prefix}issue_subscribers__subscriber_id__in"] = subscribers
else:
if (
params.get("subscriber", None)
and len(params.get("subscriber"))
and params.get("subscriber") != "null"
):
- issue_filter[f"{prefix}issue_subscribers__subscriber_id__in"] = (
- params.get("subscriber")
+ issue_filter[f"{prefix}issue_subscribers__subscriber_id__in"] = params.get(
+ "subscriber"
)
return issue_filter
@@ -541,9 +489,7 @@ def filter_start_target_date_issues(params, issue_filter, method, prefix=""):
def filter_logged_by(params, issue_filter, method, prefix=""):
if method == "GET":
logged_bys = [
- item
- for item in params.get("logged_by").split(",")
- if item != "null"
+ item for item in params.get("logged_by").split(",") if item != "null"
]
if "None" in logged_bys:
issue_filter[f"{prefix}logged_by__isnull"] = True
diff --git a/apiserver/plane/utils/issue_search.py b/apiserver/plane/utils/issue_search.py
index 74d1e8019..1e7543d88 100644
--- a/apiserver/plane/utils/issue_search.py
+++ b/apiserver/plane/utils/issue_search.py
@@ -17,6 +17,4 @@ def search_issues(query, queryset):
q |= Q(**{"sequence_id": sequence_id})
else:
q |= Q(**{f"{field}__icontains": query})
- return queryset.filter(
- q,
- ).distinct()
+ return queryset.filter(q).distinct()
diff --git a/apiserver/plane/utils/order_queryset.py b/apiserver/plane/utils/order_queryset.py
index 920e5b1e0..174637b74 100644
--- a/apiserver/plane/utils/order_queryset.py
+++ b/apiserver/plane/utils/order_queryset.py
@@ -1,20 +1,8 @@
-from django.db.models import (
- Case,
- CharField,
- Min,
- Value,
- When,
-)
+from django.db.models import Case, CharField, Min, Value, When
# Custom ordering for priority and state
PRIORITY_ORDER = ["urgent", "high", "medium", "low", "none"]
-STATE_ORDER = [
- "backlog",
- "unstarted",
- "started",
- "completed",
- "cancelled",
-]
+STATE_ORDER = ["backlog", "unstarted", "started", "completed", "cancelled"]
def order_issue_queryset(issue_queryset, order_by_param="-created_at"):
@@ -30,15 +18,10 @@ def order_issue_queryset(issue_queryset, order_by_param="-created_at"):
)
).order_by("priority_order")
order_by_param = (
- "priority_order"
- if order_by_param.startswith("-")
- else "-priority_order"
+ "priority_order" if order_by_param.startswith("-") else "-priority_order"
)
# State Ordering
- elif order_by_param in [
- "state__group",
- "-state__group",
- ]:
+ elif order_by_param in ["state__group", "-state__group"]:
state_order = (
STATE_ORDER
if order_by_param in ["state__name", "state__group"]
@@ -72,9 +55,7 @@ def order_issue_queryset(issue_queryset, order_by_param="-created_at"):
if order_by_param.startswith("-")
else order_by_param
)
- ).order_by(
- "-min_values" if order_by_param.startswith("-") else "min_values"
- )
+ ).order_by("-min_values" if order_by_param.startswith("-") else "min_values")
order_by_param = (
"-min_values" if order_by_param.startswith("-") else "min_values"
)
diff --git a/apiserver/plane/utils/paginator.py b/apiserver/plane/utils/paginator.py
index c6712cacb..6bec093e7 100644
--- a/apiserver/plane/utils/paginator.py
+++ b/apiserver/plane/utils/paginator.py
@@ -47,9 +47,7 @@ class Cursor:
try:
bits = value.split(":")
if len(bits) != 3:
- raise ValueError(
- "Cursor must be in the format 'value:offset:is_prev'"
- )
+ raise ValueError("Cursor must be in the format 'value:offset:is_prev'")
value = float(bits[0]) if "." in bits[0] else int(bits[0])
return cls(value, int(bits[1]), bool(int(bits[2])))
@@ -185,7 +183,6 @@ class OffsetPaginator:
class GroupedOffsetPaginator(OffsetPaginator):
-
# Field mappers - list m2m fields here
FIELD_MAPPER = {
"labels__id": "label_ids",
@@ -248,18 +245,14 @@ class GroupedOffsetPaginator(OffsetPaginator):
nulls_last=True
) # order by desc if desc is set
if self.desc
- else F(*self.key).asc(
- nulls_last=True
- ) # Order by asc if set
+ else F(*self.key).asc(nulls_last=True) # Order by asc if set
),
F("created_at").desc(),
),
)
)
# Filter the results by row number
- results = queryset.filter(
- row_number__gt=offset, row_number__lt=stop
- ).order_by(
+ results = queryset.filter(row_number__gt=offset, row_number__lt=stop).order_by(
(
F(*self.key).desc(nulls_last=True)
if self.desc
@@ -270,19 +263,11 @@ class GroupedOffsetPaginator(OffsetPaginator):
# Adjust cursors based on the grouped results for pagination
next_cursor = Cursor(
- limit,
- page + 1,
- False,
- queryset.filter(row_number__gte=stop).exists(),
+ limit, page + 1, False, queryset.filter(row_number__gte=stop).exists()
)
# Add previous cursors
- prev_cursor = Cursor(
- limit,
- page - 1,
- True,
- page > 0,
- )
+ prev_cursor = Cursor(limit, page - 1, True, page > 0)
# Count the queryset
count = queryset.count()
@@ -292,13 +277,7 @@ class GroupedOffsetPaginator(OffsetPaginator):
if results:
max_hits = math.ceil(
queryset.values(self.group_by_field_name)
- .annotate(
- count=Count(
- "id",
- filter=self.count_filter,
- distinct=True,
- )
- )
+ .annotate(count=Count("id", filter=self.count_filter, distinct=True))
.order_by("-count")[0]["count"]
/ limit
)
@@ -316,13 +295,7 @@ class GroupedOffsetPaginator(OffsetPaginator):
# Get total items for each group
return (
self.queryset.values(self.group_by_field_name)
- .annotate(
- count=Count(
- "id",
- filter=self.count_filter,
- distinct=True,
- )
- )
+ .annotate(count=Count("id", filter=self.count_filter, distinct=True))
.order_by()
)
@@ -331,9 +304,7 @@ class GroupedOffsetPaginator(OffsetPaginator):
total_group_dict = {}
for group in self.__get_total_queryset():
total_group_dict[str(group.get(self.group_by_field_name))] = (
- total_group_dict.get(
- str(group.get(self.group_by_field_name)), 0
- )
+ total_group_dict.get(str(group.get(self.group_by_field_name)), 0)
+ (1 if group.get("count") == 0 else group.get("count"))
)
return total_group_dict
@@ -499,9 +470,7 @@ class SubGroupedOffsetPaginator(OffsetPaginator):
)
# Filter the results
- results = queryset.filter(
- row_number__gt=offset, row_number__lt=stop
- ).order_by(
+ results = queryset.filter(row_number__gt=offset, row_number__lt=stop).order_by(
(
F(*self.key).desc(nulls_last=True)
if self.desc
@@ -512,19 +481,11 @@ class SubGroupedOffsetPaginator(OffsetPaginator):
# Adjust cursors based on the grouped results for pagination
next_cursor = Cursor(
- limit,
- page + 1,
- False,
- queryset.filter(row_number__gte=stop).exists(),
+ limit, page + 1, False, queryset.filter(row_number__gte=stop).exists()
)
# Add previous cursors
- prev_cursor = Cursor(
- limit,
- page - 1,
- True,
- page > 0,
- )
+ prev_cursor = Cursor(limit, page - 1, True, page > 0)
# Count the queryset
count = queryset.count()
@@ -534,13 +495,7 @@ class SubGroupedOffsetPaginator(OffsetPaginator):
if results:
max_hits = math.ceil(
queryset.values(self.group_by_field_name)
- .annotate(
- count=Count(
- "id",
- filter=self.count_filter,
- distinct=True,
- )
- )
+ .annotate(count=Count("id", filter=self.count_filter, distinct=True))
.order_by("-count")[0]["count"]
/ limit
)
@@ -559,29 +514,17 @@ class SubGroupedOffsetPaginator(OffsetPaginator):
return (
self.queryset.order_by(self.group_by_field_name)
.values(self.group_by_field_name)
- .annotate(
- count=Count(
- "id",
- filter=self.count_filter,
- distinct=True,
- )
- )
+ .annotate(count=Count("id", filter=self.count_filter, distinct=True))
.distinct()
)
def __get_subgroup_total_queryset(self):
# Get subgroup totals
return (
- self.queryset.values(
- self.group_by_field_name, self.sub_group_by_field_name
- )
- .annotate(
- count=Count("id", filter=self.count_filter, distinct=True)
- )
+ self.queryset.values(self.group_by_field_name, self.sub_group_by_field_name)
+ .annotate(count=Count("id", filter=self.count_filter, distinct=True))
.order_by()
- .values(
- self.group_by_field_name, self.sub_group_by_field_name, "count"
- )
+ .values(self.group_by_field_name, self.sub_group_by_field_name, "count")
)
def __get_total_dict(self):
@@ -590,9 +533,7 @@ class SubGroupedOffsetPaginator(OffsetPaginator):
total_sub_group_dict = {}
for group in self.__get_group_total_queryset():
total_group_dict[str(group.get(self.group_by_field_name))] = (
- total_group_dict.get(
- str(group.get(self.group_by_field_name)), 0
- )
+ total_group_dict.get(str(group.get(self.group_by_field_name)), 0)
+ (1 if group.get("count") == 0 else group.get("count"))
)
@@ -625,9 +566,9 @@ class SubGroupedOffsetPaginator(OffsetPaginator):
"results": {
str(sub_group): {
"results": [],
- "total_results": total_sub_group_dict.get(
- str(group)
- ).get(str(sub_group), 0),
+ "total_results": total_sub_group_dict.get(str(group)).get(
+ str(sub_group), 0
+ ),
}
for sub_group in total_sub_group_dict.get(str(group), [])
},
@@ -667,8 +608,7 @@ class SubGroupedOffsetPaginator(OffsetPaginator):
if (
group_value in processed_results
- and sub_group_value
- in processed_results[str(group_value)]["results"]
+ and sub_group_value in processed_results[str(group_value)]["results"]
):
if self.group_by_field_name in self.FIELD_MAPPER:
# for multi grouper
@@ -677,17 +617,15 @@ class SubGroupedOffsetPaginator(OffsetPaginator):
[] if "None" in group_ids else group_ids
)
if self.sub_group_by_field_name in self.FIELD_MAPPER:
- sub_group_ids = list(
- result_sub_group_mapping[str(result_id)]
- )
+ sub_group_ids = list(result_sub_group_mapping[str(result_id)])
# for multi groups
- result[
- self.FIELD_MAPPER.get(self.sub_group_by_field_name)
- ] = ([] if "None" in sub_group_ids else sub_group_ids)
+ result[self.FIELD_MAPPER.get(self.sub_group_by_field_name)] = (
+ [] if "None" in sub_group_ids else sub_group_ids
+ )
# If a result belongs to multiple groups, add it to each group
- processed_results[str(group_value)]["results"][
- str(sub_group_value)
- ]["results"].append(result)
+ processed_results[str(group_value)]["results"][str(sub_group_value)][
+ "results"
+ ].append(result)
return processed_results
@@ -764,7 +702,7 @@ class BasePaginator:
input_cursor = None
try:
input_cursor = cursor_cls.from_string(
- request.GET.get(self.cursor_name, f"{per_page}:0:0"),
+ request.GET.get(self.cursor_name, f"{per_page}:0:0")
)
except ValueError:
raise ParseError(detail="Invalid cursor parameter.")
@@ -779,16 +717,12 @@ class BasePaginator:
paginator_kwargs["sub_group_by_field_name"] = (
sub_group_by_field_name
)
- paginator_kwargs["sub_group_by_fields"] = (
- sub_group_by_fields
- )
+ paginator_kwargs["sub_group_by_fields"] = sub_group_by_fields
paginator = paginator_cls(**paginator_kwargs)
try:
- cursor_result = paginator.get_result(
- limit=per_page, cursor=input_cursor
- )
+ cursor_result = paginator.get_result(limit=per_page, cursor=input_cursor)
except BadPaginationError:
raise ParseError(detail="Error in parsing")
diff --git a/apiserver/plane/utils/user_timezone_converter.py b/apiserver/plane/utils/user_timezone_converter.py
index c946cfb27..550abfe99 100644
--- a/apiserver/plane/utils/user_timezone_converter.py
+++ b/apiserver/plane/utils/user_timezone_converter.py
@@ -1,5 +1,6 @@
import pytz
+
def user_timezone_converter(queryset, datetime_fields, user_timezone):
# Create a timezone object for the user's timezone
user_tz = pytz.timezone(user_timezone)
diff --git a/apiserver/plane/web/urls.py b/apiserver/plane/web/urls.py
index 24a3e7b57..512d4a258 100644
--- a/apiserver/plane/web/urls.py
+++ b/apiserver/plane/web/urls.py
@@ -1,6 +1,4 @@
from django.urls import path
from django.views.generic import TemplateView
-urlpatterns = [
- path("about/", TemplateView.as_view(template_name="about.html"))
-]
+urlpatterns = [path("about/", TemplateView.as_view(template_name="about.html"))]
diff --git a/apiserver/pyproject.toml b/apiserver/pyproject.toml
index a6c07b855..15df2d996 100644
--- a/apiserver/pyproject.toml
+++ b/apiserver/pyproject.toml
@@ -1,25 +1,97 @@
-[tool.black]
-line-length = 79
-target-version = ['py36']
-include = '\.pyi?$'
-exclude = '''
- /(
- \.git
- | \.hg
- | \.mypy_cache
- | \.tox
- | \.venv
- | _build
- | buck-out
- | build
- | dist
- | venv
- )/
-'''
+[project]
+name = "your-project-name"
+version = "0.1.0"
+description = "Your project description"
+requires-python = ">=3.8"
[tool.ruff]
-line-length = 79
+# Exclude a variety of commonly ignored directories.
exclude = [
- "**/__init__.py",
+ ".bzr",
+ ".direnv",
+ ".eggs",
+ ".git",
+ ".git-rewrite",
+ ".hg",
+ ".mypy_cache",
+ ".nox",
+ ".pants.d",
+ ".pytype",
+ ".ruff_cache",
+ ".svn",
+ ".tox",
+ ".venv",
+ "__pypackages__",
+ "_build",
+ "buck-out",
+ "build",
+ "dist",
+ "node_modules",
+ "venv",
+ "**/migrations/*",
]
+# Same as Black.
+line-length = 88
+indent-width = 4
+
+[tool.ruff.format]
+# Use double quotes for strings.
+quote-style = "double"
+
+# Indent with spaces, rather than tabs.
+indent-style = "space"
+
+# Respect magic trailing commas.
+skip-magic-trailing-comma = true
+
+# Automatically detect the appropriate line ending.
+line-ending = "auto"
+
+[tool.ruff.lint]
+# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
+select = ["E", "F"]
+ignore = []
+
+# Allow autofix for all enabled rules (when `--fix`) is provided.
+fixable = ["ALL"]
+unfixable = []
+
+# Allow unused variables when underscore-prefixed.
+dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
+
+[tool.ruff.lint.pep8-naming]
+# Allow lowercase variables like "id"
+classmethod-decorators = ["classmethod", "validator", "root_validator"]
+
+[tool.ruff.lint.per-file-ignores]
+# Ignore specific rules for tests
+"tests/*" = ["E402", "F401", "F811"]
+# Ignore imported but unused in __init__.py files
+"__init__.py" = ["F401"]
+
+[tool.ruff.lint.mccabe]
+# Unlike Flake8, default to a complexity level of 10.
+max-complexity = 10
+
+[tool.ruff.lint.isort]
+combine-as-imports = true
+detect-same-package = true
+force-wrap-aliases = true
+known-first-party = ["plane"]
+known-third-party = ["rest_framework"]
+relative-imports-order = "closest-to-furthest"
+
+[tool.ruff.lint.flake8-tidy-imports]
+ban-relative-imports = "parents"
+
+[tool.ruff.lint.pycodestyle]
+ignore-overlong-task-comments = true
+max-doc-length = 88
+
+[tool.ruff.lint.pydocstyle]
+convention = "google"
+
+[tool.ruff.lint.pylint]
+max-args = 8
+max-statements = 50