diff --git a/apiserver/plane/app/urls/workspace.py b/apiserver/plane/app/urls/workspace.py index 26e623864d..d91fdb60bc 100644 --- a/apiserver/plane/app/urls/workspace.py +++ b/apiserver/plane/app/urls/workspace.py @@ -68,9 +68,7 @@ urlpatterns = [ # 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( diff --git a/apiserver/plane/app/views/project/member.py b/apiserver/plane/app/views/project/member.py index c274d87c5f..55d2d4a58b 100644 --- a/apiserver/plane/app/views/project/member.py +++ b/apiserver/plane/app/views/project/member.py @@ -16,12 +16,7 @@ from plane.app.permissions import ( WorkspaceUserPermission, ) -from plane.db.models import ( - Project, - ProjectMember, - IssueUserProperty, - WorkspaceMember, -) +from plane.db.models import Project, ProjectMember, IssueUserProperty, WorkspaceMember from plane.bgtasks.project_add_user_email_task import project_add_user_email from plane.utils.host import base_host from plane.app.permissions.base import allow_permission, ROLE @@ -83,10 +78,7 @@ class ProjectMemberViewSet(BaseViewSet): workspace_member_role = WorkspaceMember.objects.get( 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" @@ -94,10 +86,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" @@ -135,8 +124,7 @@ class ProjectMemberViewSet(BaseViewSet): 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( @@ -145,9 +133,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 @@ -238,9 +224,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, ) @@ -280,9 +264,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, ) @@ -303,10 +285,7 @@ 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 ): @@ -344,7 +323,6 @@ class UserProjectRolesEndpoint(BaseAPIView): ).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/workspace/base.py b/apiserver/plane/app/views/workspace/base.py index 515a3479bb..058f7702ab 100644 --- a/apiserver/plane/app/views/workspace/base.py +++ b/apiserver/plane/app/views/workspace/base.py @@ -41,6 +41,7 @@ from django.views.decorators.vary import vary_on_cookie from plane.utils.constants import RESTRICTED_WORKSPACE_SLUGS from plane.license.utils.instance_value import get_configuration_value + class WorkSpaceViewSet(BaseViewSet): model = Workspace serializer_class = WorkSpaceSerializer @@ -81,12 +82,12 @@ class WorkSpaceViewSet(BaseViewSet): def create(self, request): try: - DISABLE_WORKSPACE_CREATION, = get_configuration_value( + (DISABLE_WORKSPACE_CREATION,) = get_configuration_value( [ { "key": "DISABLE_WORKSPACE_CREATION", "default": os.environ.get("DISABLE_WORKSPACE_CREATION", "0"), - }, + } ] ) diff --git a/apiserver/plane/app/views/workspace/member.py b/apiserver/plane/app/views/workspace/member.py index 91a89ad072..9541f99803 100644 --- a/apiserver/plane/app/views/workspace/member.py +++ b/apiserver/plane/app/views/workspace/member.py @@ -1,22 +1,12 @@ # Django imports -from django.db.models import ( - Count, - Q, - OuterRef, - Subquery, - IntegerField, -) +from django.db.models import Count, Q, OuterRef, Subquery, IntegerField from django.db.models.functions import Coalesce # Third party modules from rest_framework import status from rest_framework.response import Response -from plane.app.permissions import ( - WorkspaceEntityPermission, - allow_permission, - ROLE, -) +from plane.app.permissions import WorkspaceEntityPermission, allow_permission, ROLE # Module imports from plane.app.serializers import ( @@ -26,12 +16,7 @@ from plane.app.serializers import ( WorkSpaceMemberSerializer, ) from plane.app.views.base import BaseAPIView -from plane.db.models import ( - Project, - ProjectMember, - WorkspaceMember, - DraftIssue, -) +from plane.db.models import Project, ProjectMember, WorkspaceMember, DraftIssue from plane.utils.cache import invalidate_cache from .. import BaseViewSet @@ -119,9 +104,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, ) @@ -148,9 +131,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 @@ -164,9 +145,7 @@ 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" ) @@ -213,9 +192,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 @@ -279,9 +256,7 @@ class WorkspaceProjectMemberEndpoint(BaseAPIView): project_members = ProjectMember.objects.filter( 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() diff --git a/apiserver/plane/bgtasks/deletion_task.py b/apiserver/plane/bgtasks/deletion_task.py index 9a9681b66c..b350c2299f 100644 --- a/apiserver/plane/bgtasks/deletion_task.py +++ b/apiserver/plane/bgtasks/deletion_task.py @@ -19,9 +19,9 @@ def soft_delete_related_objects(app_label, model_name, instance_pk, using=None): try: # Check if the field has CASCADE on delete if ( - hasattr(field, "remote_field") and - hasattr(field.remote_field, "on_delete") and - field.remote_field.on_delete == models.CASCADE + hasattr(field, "remote_field") + and hasattr(field.remote_field, "on_delete") + and field.remote_field.on_delete == models.CASCADE ): if field.one_to_many: related_objects = getattr(instance, field.name).all() diff --git a/apiserver/plane/bgtasks/export_task.py b/apiserver/plane/bgtasks/export_task.py index f7b19f00ab..33e382f441 100644 --- a/apiserver/plane/bgtasks/export_task.py +++ b/apiserver/plane/bgtasks/export_task.py @@ -162,8 +162,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 +196,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 +206,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"]), diff --git a/apiserver/plane/bgtasks/notification_task.py b/apiserver/plane/bgtasks/notification_task.py index ade2479096..f61c2e3c3b 100644 --- a/apiserver/plane/bgtasks/notification_task.py +++ b/apiserver/plane/bgtasks/notification_task.py @@ -257,7 +257,9 @@ def notifications( ) new_mentions = [ - str(mention) for mention in new_mentions if mention in set(project_members) + str(mention) + for mention in new_mentions + if mention in set(project_members) ] removed_mention = get_removed_mentions( requested_instance=requested_data, current_instance=current_instance diff --git a/apiserver/plane/db/management/commands/create_project_member.py b/apiserver/plane/db/management/commands/create_project_member.py index a2a5c669e4..927f97e9d5 100644 --- a/apiserver/plane/db/management/commands/create_project_member.py +++ b/apiserver/plane/db/management/commands/create_project_member.py @@ -13,28 +13,14 @@ from plane.db.models import ( class Command(BaseCommand): - help = "Add a member to a project. If present in the workspace" def add_arguments(self, parser): # Positional argument + parser.add_argument("--project_id", type=str, nargs="?", help="Project ID") + parser.add_argument("--user_email", type=str, nargs="?", help="User Email") parser.add_argument( - "--project_id", - type=str, - nargs="?", - help="Project ID", - ) - parser.add_argument( - "--user_email", - type=str, - nargs="?", - help="User Email", - ) - parser.add_argument( - "--role", - type=int, - nargs="?", - help="Role of the user in the project", + "--role", type=int, nargs="?", help="Role of the user in the project" ) def handle(self, *args: Any, **options: Any): @@ -67,9 +53,7 @@ class Command(BaseCommand): # Get the smallest sort order smallest_sort_order = ( - ProjectMember.objects.filter( - workspace_id=project.workspace_id, - ) + ProjectMember.objects.filter(workspace_id=project.workspace_id) .order_by("sort_order") .first() ) @@ -79,22 +63,15 @@ class Command(BaseCommand): else: sort_order = 65535 - if ProjectMember.objects.filter( - project=project, - member=user, - ).exists(): + if ProjectMember.objects.filter(project=project, member=user).exists(): # Update the project member - ProjectMember.objects.filter( - project=project, - member=user, - ).update(is_active=True, sort_order=sort_order, role=role) + ProjectMember.objects.filter(project=project, member=user).update( + is_active=True, sort_order=sort_order, role=role + ) else: # Create the project member ProjectMember.objects.create( - project=project, - member=user, - role=role, - sort_order=sort_order, + project=project, member=user, role=role, sort_order=sort_order ) # Issue Property @@ -102,9 +79,7 @@ class Command(BaseCommand): # Success message self.stdout.write( - self.style.SUCCESS( - f"User {user_email} added to project {project_id}" - ) + self.style.SUCCESS(f"User {user_email} added to project {project_id}") ) return except CommandError as e: diff --git a/apiserver/plane/db/models/asset.py b/apiserver/plane/db/models/asset.py index 9f99a8144a..9973d122f5 100644 --- a/apiserver/plane/db/models/asset.py +++ b/apiserver/plane/db/models/asset.py @@ -44,45 +44,25 @@ class FileAsset(BaseModel): "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" ) 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" ) - entity_type = models.CharField( - max_length=255, - null=True, - blank=True, - ) - entity_identifier = models.CharField( - max_length=255, - null=True, - blank=True, - ) + entity_type = models.CharField(max_length=255, null=True, blank=True) + entity_identifier = models.CharField(max_length=255, null=True, blank=True) is_deleted = models.BooleanField(default=False) is_archived = models.BooleanField(default=False) external_id = models.CharField(max_length=255, null=True, blank=True) diff --git a/apiserver/plane/db/models/issue.py b/apiserver/plane/db/models/issue.py index e50dbe7ce8..9ea1d3b264 100644 --- a/apiserver/plane/db/models/issue.py +++ b/apiserver/plane/db/models/issue.py @@ -661,9 +661,7 @@ class IssueVote(ProjectBaseModel): class IssueVersion(ProjectBaseModel): issue = models.ForeignKey( - "db.Issue", - on_delete=models.CASCADE, - related_name="versions", + "db.Issue", on_delete=models.CASCADE, related_name="versions" ) PRIORITY_CHOICES = ( ("urgent", "Urgent"), @@ -688,9 +686,7 @@ class IssueVersion(ProjectBaseModel): ) start_date = models.DateField(null=True, blank=True) target_date = models.DateField(null=True, blank=True) - sequence_id = models.IntegerField( - default=1, verbose_name="Issue Sequence ID" - ) + sequence_id = models.IntegerField(default=1, verbose_name="Issue Sequence ID") sort_order = models.FloatField(default=65535) completed_at = models.DateTimeField(null=True) archived_at = models.DateField(null=True) @@ -700,25 +696,10 @@ class IssueVersion(ProjectBaseModel): type = models.UUIDField(blank=True, null=True) last_saved_at = models.DateTimeField(default=timezone.now) owned_by = models.UUIDField() - assignees = ArrayField( - models.UUIDField(), - blank=True, - default=list, - ) - labels = ArrayField( - models.UUIDField(), - blank=True, - default=list, - ) - cycle = models.UUIDField( - null=True, - blank=True, - ) - modules = ArrayField( - models.UUIDField(), - blank=True, - default=list, - ) + assignees = ArrayField(models.UUIDField(), blank=True, default=list) + labels = ArrayField(models.UUIDField(), blank=True, default=list) + cycle = models.UUIDField(null=True, blank=True) + modules = ArrayField(models.UUIDField(), blank=True, default=list) properties = models.JSONField(default=dict) meta = models.JSONField(default=dict) @@ -741,9 +722,7 @@ class IssueVersion(ProjectBaseModel): Module = apps.get_model("db.Module") CycleIssue = apps.get_model("db.CycleIssue") - cycle_issue = CycleIssue.objects.filter( - issue=issue, - ).first() + cycle_issue = CycleIssue.objects.filter(issue=issue).first() cls.objects.create( issue=issue, @@ -771,9 +750,7 @@ class IssueVersion(ProjectBaseModel): assignees=issue.assignees, labels=issue.labels, cycle=cycle_issue.cycle if cycle_issue else None, - modules=Module.objects.filter(issue=issue).values_list( - "id", flat=True - ), + modules=Module.objects.filter(issue=issue).values_list("id", flat=True), owned_by=user, ) return True diff --git a/apiserver/plane/db/models/webhook.py b/apiserver/plane/db/models/webhook.py index 92d45a0589..ec8fcda3af 100644 --- a/apiserver/plane/db/models/webhook.py +++ b/apiserver/plane/db/models/webhook.py @@ -29,9 +29,7 @@ def validate_domain(value): class Webhook(BaseModel): workspace = models.ForeignKey( - "db.Workspace", - on_delete=models.CASCADE, - related_name="workspace_webhooks", + "db.Workspace", on_delete=models.CASCADE, related_name="workspace_webhooks" ) url = models.URLField( validators=[validate_schema, validate_domain], max_length=1024 diff --git a/apiserver/plane/db/models/workspace.py b/apiserver/plane/db/models/workspace.py index df1f26d3f5..f8082e492b 100644 --- a/apiserver/plane/db/models/workspace.py +++ b/apiserver/plane/db/models/workspace.py @@ -102,12 +102,7 @@ def get_default_display_properties(): 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): @@ -136,9 +131,7 @@ class Workspace(BaseModel): 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""" @@ -167,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: @@ -184,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, @@ -221,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) @@ -283,9 +269,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) @@ -320,9 +304,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/serializers/__init__.py b/apiserver/plane/license/api/serializers/__init__.py index 48ecd4536a..6e0a5941c4 100644 --- a/apiserver/plane/license/api/serializers/__init__.py +++ b/apiserver/plane/license/api/serializers/__init__.py @@ -2,4 +2,4 @@ from .instance import InstanceSerializer from .configuration import InstanceConfigurationSerializer from .admin import InstanceAdminSerializer, InstanceAdminMeSerializer -from .workspace import WorkspaceSerializer \ No newline at end of file +from .workspace import WorkspaceSerializer diff --git a/apiserver/plane/license/api/serializers/user.py b/apiserver/plane/license/api/serializers/user.py index 8935a882f2..c53b4a4848 100644 --- a/apiserver/plane/license/api/serializers/user.py +++ b/apiserver/plane/license/api/serializers/user.py @@ -1,6 +1,8 @@ from .base import BaseSerializer from plane.db.models import User + + class UserLiteSerializer(BaseSerializer): class Meta: model = User - fields = ["id", "email", "first_name", "last_name",] + fields = ["id", "email", "first_name", "last_name"] diff --git a/apiserver/plane/license/api/views/workspace.py b/apiserver/plane/license/api/views/workspace.py index 14118d85bc..607016cc3a 100644 --- a/apiserver/plane/license/api/views/workspace.py +++ b/apiserver/plane/license/api/views/workspace.py @@ -43,19 +43,19 @@ class InstanceWorkSpaceEndpoint(BaseAPIView): .annotate(count=Func(F("id"), function="Count")) .values("count") ) - + member_count = ( WorkspaceMember.objects.filter( workspace=OuterRef("id"), member__is_bot=False, is_active=True - ).select_related("owner") + ) + .select_related("owner") .order_by() .annotate(count=Func(F("id"), function="Count")) .values("count") ) workspaces = Workspace.objects.annotate( - total_projects=project_count, - total_members=member_count, + total_projects=project_count, total_members=member_count ) # Add search functionality @@ -66,16 +66,14 @@ class InstanceWorkSpaceEndpoint(BaseAPIView): return self.paginate( request=request, queryset=workspaces, - on_results=lambda results: WorkspaceSerializer( - results, many=True, - ).data, + on_results=lambda results: WorkspaceSerializer(results, many=True).data, max_per_page=10, default_per_page=10, ) def post(self, request): try: - serializer = WorkspaceSerializer (data=request.data) + serializer = WorkspaceSerializer(data=request.data) slug = request.data.get("slug", False) name = request.data.get("name", False)