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 a3ec6b895e..1a9cb93d22 100644 --- a/apiserver/plane/app/views/workspace/base.py +++ b/apiserver/plane/app/views/workspace/base.py @@ -44,6 +44,7 @@ from plane.payment.bgtasks.member_sync_task import member_sync_task from django.conf import settings + class WorkSpaceViewSet(BaseViewSet): model = Workspace serializer_class = WorkSpaceSerializer diff --git a/apiserver/plane/app/views/workspace/member.py b/apiserver/plane/app/views/workspace/member.py index 409f41b2f8..1a906c46f0 100644 --- a/apiserver/plane/app/views/workspace/member.py +++ b/apiserver/plane/app/views/workspace/member.py @@ -17,12 +17,11 @@ from plane.app.serializers import ( WorkSpaceMemberSerializer, ) from plane.app.views.base import BaseAPIView -from plane.db.models import Project, ProjectMember, WorkspaceMember, DraftIssue, Cycle - from plane.utils.cache import invalidate_cache +from plane.db.models import Project, ProjectMember, WorkspaceMember, DraftIssue, Cycle from plane.payment.bgtasks.member_sync_task import member_sync_task -from .. import BaseViewSet from plane.payment.utils.member_payment_count import workspace_member_check +from .. import BaseViewSet class WorkSpaceMemberViewSet(BaseViewSet): 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 b74593c107..2b206fde0e 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/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 b95e58900f..cf76f4e1c8 100644 --- a/apiserver/plane/db/models/issue.py +++ b/apiserver/plane/db/models/issue.py @@ -662,9 +662,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"), @@ -689,9 +687,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) @@ -701,25 +697,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) @@ -742,9 +723,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, @@ -772,9 +751,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/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/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)