Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: user issue display properties #2258

Merged
merged 7 commits into from
Oct 27, 2023
Merged
27 changes: 5 additions & 22 deletions apiserver/plane/api/urls/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
IssueSubscriberViewSet,
IssueReactionViewSet,
CommentReactionViewSet,
IssuePropertyViewSet,
IssueUserDisplayPropertyEndpoint,
IssueArchiveViewSet,
IssueRelationViewSet,
IssueDraftViewSet,
Expand Down Expand Up @@ -235,28 +235,11 @@
## End Comment Reactions
## IssueProperty
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-properties/",
IssuePropertyViewSet.as_view(
{
"get": "list",
"post": "create",
}
),
name="project-issue-roadmap",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-properties/<uuid:pk>/",
IssuePropertyViewSet.as_view(
{
"get": "retrieve",
"put": "update",
"patch": "partial_update",
"delete": "destroy",
}
),
name="project-issue-roadmap",
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-display-properties/",
IssueUserDisplayPropertyEndpoint.as_view(),
name="project-issue-display-properties",
),
## IssueProperty Ebd
## IssueProperty End
## Issue Archives
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/archived-issues/",
Expand Down
25 changes: 4 additions & 21 deletions apiserver/plane/api/urls_deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
BulkDeleteIssuesEndpoint,
BulkImportIssuesEndpoint,
ProjectUserViewsEndpoint,
IssuePropertyViewSet,
IssueUserDisplayPropertyEndpoint,
LabelViewSet,
SubIssuesEndpoint,
IssueLinkViewSet,
Expand Down Expand Up @@ -1008,26 +1008,9 @@
## End Comment Reactions
## IssueProperty
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-properties/",
IssuePropertyViewSet.as_view(
{
"get": "list",
"post": "create",
}
),
name="project-issue-roadmap",
),
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-properties/<uuid:pk>/",
IssuePropertyViewSet.as_view(
{
"get": "retrieve",
"put": "update",
"patch": "partial_update",
"delete": "destroy",
}
),
name="project-issue-roadmap",
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-display-properties/",
IssueUserDisplayPropertyEndpoint.as_view(),
name="project-issue-display-properties",
),
## IssueProperty Ebd
## Issue Archives
Expand Down
2 changes: 1 addition & 1 deletion apiserver/plane/api/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
WorkSpaceIssuesEndpoint,
IssueActivityEndpoint,
IssueCommentViewSet,
IssuePropertyViewSet,
IssueUserDisplayPropertyEndpoint,
LabelViewSet,
BulkDeleteIssuesEndpoint,
UserWorkSpaceIssues,
Expand Down
51 changes: 13 additions & 38 deletions apiserver/plane/api/views/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -597,41 +597,12 @@ def destroy(self, request, slug, project_id, issue_id, pk):
return Response(status=status.HTTP_204_NO_CONTENT)


class IssuePropertyViewSet(BaseViewSet):
serializer_class = IssuePropertySerializer
model = IssueProperty
class IssueUserDisplayPropertyEndpoint(BaseAPIView):
permission_classes = [
ProjectEntityPermission,
ProjectLitePermission,
]

filterset_fields = []

def perform_create(self, serializer):
serializer.save(
project_id=self.kwargs.get("project_id"), user=self.request.user
)

def get_queryset(self):
return self.filter_queryset(
super()
.get_queryset()
.filter(workspace__slug=self.kwargs.get("slug"))
.filter(project_id=self.kwargs.get("project_id"))
.filter(user=self.request.user)
.filter(project__project_projectmember__member=self.request.user)
.select_related("project")
.select_related("workspace")
)

def list(self, request, slug, project_id):
queryset = self.get_queryset()
serializer = IssuePropertySerializer(queryset, many=True)
return Response(
serializer.data[0] if len(serializer.data) > 0 else [],
status=status.HTTP_200_OK,
)

def create(self, request, slug, project_id):
def post(self, request, slug, project_id):
issue_property, created = IssueProperty.objects.get_or_create(
user=request.user,
project_id=project_id,
Expand All @@ -640,16 +611,20 @@ def create(self, request, slug, project_id):
if not created:
issue_property.properties = request.data.get("properties", {})
issue_property.save()

serializer = IssuePropertySerializer(issue_property)
return Response(serializer.data, status=status.HTTP_200_OK)

issue_property.properties = request.data.get("properties", {})
issue_property.save()
serializer = IssuePropertySerializer(issue_property)
return Response(serializer.data, status=status.HTTP_201_CREATED)


def get(self, request, slug, project_id):
issue_property, _ = IssueProperty.objects.get_or_create(
user=request.user, project_id=project_id
)
serializer = IssuePropertySerializer(issue_property)
return Response(serializer.data, status=status.HTTP_200_OK)


class LabelViewSet(BaseViewSet):
serializer_class = LabelSerializer
model = Label
Expand Down Expand Up @@ -963,8 +938,8 @@ def get(self, request, slug, project_id, issue_id):
issue_attachments = IssueAttachment.objects.filter(
issue_id=issue_id, workspace__slug=slug, project_id=project_id
)
serilaizer = IssueAttachmentSerializer(issue_attachments, many=True)
return Response(serilaizer.data, status=status.HTTP_200_OK)
serializer = IssueAttachmentSerializer(issue_attachments, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)


class IssueArchiveViewSet(BaseViewSet):
Expand Down
67 changes: 66 additions & 1 deletion apiserver/plane/api/views/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
ModuleMember,
Inbox,
ProjectDeployBoard,
IssueProperty,
)

from plane.bgtasks.project_invitation_task import project_invitation
Expand Down Expand Up @@ -201,6 +202,11 @@ def create(self, request, slug):
project_member = ProjectMember.objects.create(
project_id=serializer.data["id"], member=request.user, role=20
)
# Also create the issue property for the user
_ = IssueProperty.objects.create(
project_id=serializer.data["id"],
user=request.user,
)

if serializer.data["project_lead"] is not None and str(
serializer.data["project_lead"]
Expand All @@ -210,6 +216,11 @@ def create(self, request, slug):
member_id=serializer.data["project_lead"],
role=20,
)
# Also create the issue property for the user
IssueProperty.objects.create(
project_id=serializer.data["id"],
user_id=serializer.data["project_lead"],
)

# Default states
states = [
Expand Down Expand Up @@ -393,6 +404,8 @@ def post(self, request, slug, project_id):
member=user, project_id=project_id, role=role
)

_ = IssueProperty.objects.create(user=user, project_id=project_id)

return Response(
ProjectMemberSerializer(project_member).data, status=status.HTTP_200_OK
)
Expand Down Expand Up @@ -428,6 +441,18 @@ def create(self, request):
]
)

IssueProperty.objects.bulk_create(
[
ProjectMember(
project=invitation.project,
workspace=invitation.project.workspace,
user=request.user,
created_by=request.user,
)
for invitation in project_invitations
]
)

# Delete joined project invites
project_invitations.delete()

Expand Down Expand Up @@ -560,6 +585,7 @@ def post(self, request, slug, project_id):
status=status.HTTP_400_BAD_REQUEST,
)
bulk_project_members = []
bulk_issue_props = []

project_members = (
ProjectMember.objects.filter(
Expand All @@ -574,7 +600,8 @@ def post(self, request, slug, project_id):
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"))
]
bulk_project_members.append(
ProjectMember(
Expand All @@ -585,14 +612,26 @@ def post(self, request, slug, project_id):
sort_order=sort_order[0] - 10000 if len(sort_order) else 65535,
)
)
bulk_issue_props.append(
IssueProperty(
user_id=member.get("member_id"),
project_id=project_id,
workspace_id=project.workspace_id,
)
)

project_members = ProjectMember.objects.bulk_create(
bulk_project_members,
batch_size=10,
ignore_conflicts=True,
)

_ = IssueProperty.objects.bulk_create(
bulk_issue_props, batch_size=10, ignore_conflicts=True
)

serializer = ProjectMemberSerializer(project_members, many=True)

return Response(serializer.data, status=status.HTTP_201_CREATED)


Expand All @@ -614,6 +653,7 @@ def post(self, request, slug, project_id):
workspace = Workspace.objects.get(slug=slug)

project_members = []
issue_props = []
for member in team_members:
project_members.append(
ProjectMember(
Expand All @@ -623,11 +663,23 @@ def post(self, request, slug, project_id):
created_by=request.user,
)
)
issue_props.append(
IssueProperty(
project_id=project_id,
user_id=member,
workspace=workspace,
created_by=request.user,
)
)

ProjectMember.objects.bulk_create(
project_members, batch_size=10, ignore_conflicts=True
)

_ = IssueProperty.objects.bulk_create(
issue_props, batch_size=10, ignore_conflicts=True
)

serializer = ProjectMemberSerializer(project_members, many=True)
return Response(serializer.data, status=status.HTTP_201_CREATED)

Expand Down Expand Up @@ -743,6 +795,19 @@ def post(self, request, slug):
ignore_conflicts=True,
)

IssueProperty.objects.bulk_create(
[
IssueProperty(
project_id=project_id,
user=request.user,
workspace=workspace,
created_by=request.user,
)
for project_id in project_ids
],
ignore_conflicts=True,
)

return Response(
{"message": "Projects joined successfully"},
status=status.HTTP_201_CREATED,
Expand Down
15 changes: 15 additions & 0 deletions apiserver/plane/bgtasks/importer_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
WorkspaceIntegration,
Label,
User,
IssueProperty,
)
from .workspace_invitation_task import workspace_invitation
from plane.bgtasks.user_welcome_task import send_welcome_slack
Expand Down Expand Up @@ -103,6 +104,20 @@ def service_importer(service, importer_id):
ignore_conflicts=True,
)

IssueProperty.objects.bulk_create(
[
IssueProperty(
project_id=importer.project_id,
workspace_id=importer.workspace_id,
user=user,
created_by=importer.created_by,
)
for user in workspace_users
],
batch_size=100,
ignore_conflicts=True,
)

# Check if sync config is on for github importers
if service == "github" and importer.config.get("sync", False):
name = importer.metadata.get("name", False)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 4.2.5 on 2023-10-18 12:04

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import plane.db.models.issue


class Migration(migrations.Migration):

dependencies = [
('db', '0045_issueactivity_epoch_workspacemember_issue_props_and_more'),
]

operations = [
migrations.AlterField(
model_name='issueproperty',
name='properties',
field=models.JSONField(default=plane.db.models.issue.get_default_properties),
),
]
Loading
Loading