mirror of
https://github.com/makeplane/plane.git
synced 2026-07-10 20:41:15 +02:00
dev: update urls to use project identifiers and issue sequence
This commit is contained in:
@@ -44,12 +44,16 @@ class ProjectSerializer(BaseSerializer):
|
||||
detail="Project Identifier is taken"
|
||||
)
|
||||
project = Project.objects.create(
|
||||
**validated_data, workspace_id=self.context["workspace_id"]
|
||||
**validated_data,
|
||||
workspace_id=self.context["workspace_id"],
|
||||
)
|
||||
_ = ProjectIdentifier.objects.create(
|
||||
name=project.identifier,
|
||||
project=project,
|
||||
workspace_id=self.context["workspace_id"],
|
||||
created_by_id=project.created_by_id,
|
||||
updated_by_id=project.updated_by_id,
|
||||
current_active=project.identifier,
|
||||
)
|
||||
return project
|
||||
|
||||
@@ -61,29 +65,38 @@ class ProjectSerializer(BaseSerializer):
|
||||
project = super().update(instance, validated_data)
|
||||
return project
|
||||
|
||||
# If no Project Identifier is found create it
|
||||
project_identifier = ProjectIdentifier.objects.filter(
|
||||
name=identifier, workspace_id=instance.workspace_id
|
||||
).first()
|
||||
if project_identifier is None:
|
||||
project = super().update(instance, validated_data)
|
||||
project_identifier = ProjectIdentifier.objects.filter(
|
||||
project=project
|
||||
).first()
|
||||
if project_identifier is not None:
|
||||
project_identifier.name = identifier
|
||||
project_identifier.save()
|
||||
return project
|
||||
# If found check if the project_id to be updated and identifier project id is same
|
||||
if project_identifier.project_id == instance.id:
|
||||
# If same pass update
|
||||
# When updating check if the project identifier is different
|
||||
if instance.identifier == identifier:
|
||||
project = super().update(instance, validated_data)
|
||||
return project
|
||||
|
||||
# If not same fail update
|
||||
raise serializers.ValidationError(
|
||||
detail="Project Identifier is already taken"
|
||||
# Check if this project identifier is already taken in the current workspace
|
||||
if ProjectIdentifier.objects.filter(
|
||||
name=identifier,
|
||||
workspace_id=instance.workspace_id,
|
||||
).exists():
|
||||
raise serializers.ValidationError(
|
||||
detail="Project Identifier is already taken"
|
||||
)
|
||||
|
||||
# Update the project identifier
|
||||
project = super().update(instance, validated_data)
|
||||
# If no Project Identifier is found create it and deactivate the old ones
|
||||
ProjectIdentifier.objects.filter(
|
||||
project_id=instance.id,
|
||||
workspace_id=instance.workspace_id,
|
||||
).update(current_active=identifier)
|
||||
# Create new project identifier
|
||||
ProjectIdentifier.objects.create(
|
||||
name=identifier,
|
||||
project=instance,
|
||||
workspace_id=instance.workspace_id,
|
||||
created_by_id=project.created_by_id,
|
||||
updated_by_id=project.updated_by_id,
|
||||
current_active=identifier,
|
||||
)
|
||||
# Return the updated project
|
||||
return project
|
||||
|
||||
|
||||
class ProjectLiteSerializer(BaseSerializer):
|
||||
|
||||
@@ -14,7 +14,7 @@ from plane.app.views import (
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/cycles/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/cycles/",
|
||||
CycleViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -24,7 +24,7 @@ urlpatterns = [
|
||||
name="project-cycle",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/cycles/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/cycles/<uuid:pk>/",
|
||||
CycleViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -36,7 +36,7 @@ urlpatterns = [
|
||||
name="project-cycle",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/cycles/<uuid:cycle_id>/cycle-issues/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/cycles/<uuid:cycle_id>/cycle-issues/",
|
||||
CycleIssueViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -46,7 +46,7 @@ urlpatterns = [
|
||||
name="project-issue-cycle",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/cycles/<uuid:cycle_id>/cycle-issues/<uuid:issue_id>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/cycles/<uuid:cycle_id>/cycle-issues/<uuid:issue_id>/",
|
||||
CycleIssueViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -58,12 +58,12 @@ urlpatterns = [
|
||||
name="project-issue-cycle",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/cycles/date-check/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/cycles/date-check/",
|
||||
CycleDateCheckEndpoint.as_view(),
|
||||
name="project-cycle-date",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-cycles/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/user-favorite-cycles/",
|
||||
CycleFavoriteViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -73,7 +73,7 @@ urlpatterns = [
|
||||
name="user-favorite-cycle",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-cycles/<uuid:cycle_id>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/user-favorite-cycles/<uuid:cycle_id>/",
|
||||
CycleFavoriteViewSet.as_view(
|
||||
{
|
||||
"delete": "destroy",
|
||||
@@ -82,27 +82,27 @@ urlpatterns = [
|
||||
name="user-favorite-cycle",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/cycles/<uuid:cycle_id>/transfer-issues/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/cycles/<uuid:cycle_id>/transfer-issues/",
|
||||
TransferCycleIssueEndpoint.as_view(),
|
||||
name="transfer-issues",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/cycles/<uuid:cycle_id>/user-properties/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/cycles/<uuid:cycle_id>/user-properties/",
|
||||
CycleUserPropertiesEndpoint.as_view(),
|
||||
name="cycle-user-filters",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/cycles/<uuid:cycle_id>/archive/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/cycles/<uuid:cycle_id>/archive/",
|
||||
CycleArchiveUnarchiveEndpoint.as_view(),
|
||||
name="cycle-archive-unarchive",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/archived-cycles/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/archived-cycles/",
|
||||
CycleArchiveUnarchiveEndpoint.as_view(),
|
||||
name="cycle-archive-unarchive",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/archived-cycles/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/archived-cycles/<uuid:pk>/",
|
||||
CycleArchiveUnarchiveEndpoint.as_view(),
|
||||
name="cycle-archive-unarchive",
|
||||
),
|
||||
|
||||
@@ -10,12 +10,12 @@ from plane.app.views import (
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/project-estimates/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/project-estimates/",
|
||||
ProjectEstimatePointEndpoint.as_view(),
|
||||
name="project-estimate-points",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/estimates/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/estimates/",
|
||||
BulkEstimatePointEndpoint.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -25,7 +25,7 @@ urlpatterns = [
|
||||
name="bulk-create-estimate-points",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/estimates/<uuid:estimate_id>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/estimates/<uuid:estimate_id>/",
|
||||
BulkEstimatePointEndpoint.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -36,7 +36,7 @@ urlpatterns = [
|
||||
name="bulk-create-estimate-points",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/estimates/<uuid:estimate_id>/estimate-points/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/estimates/<uuid:estimate_id>/estimate-points/",
|
||||
EstimatePointEndpoint.as_view(
|
||||
{
|
||||
"post": "create",
|
||||
@@ -45,7 +45,7 @@ urlpatterns = [
|
||||
name="estimate-points",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/estimates/<uuid:estimate_id>/estimate-points/<estimate_point_id>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/estimates/<uuid:estimate_id>/estimate-points/<estimate_point_id>/",
|
||||
EstimatePointEndpoint.as_view(
|
||||
{
|
||||
"patch": "partial_update",
|
||||
|
||||
@@ -2,7 +2,10 @@ from django.urls import path
|
||||
|
||||
|
||||
from plane.app.views import UnsplashEndpoint
|
||||
from plane.app.views import GPTIntegrationEndpoint, WorkspaceGPTIntegrationEndpoint
|
||||
from plane.app.views import (
|
||||
GPTIntegrationEndpoint,
|
||||
WorkspaceGPTIntegrationEndpoint,
|
||||
)
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
@@ -12,11 +15,11 @@ urlpatterns = [
|
||||
name="unsplash",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/ai-assistant/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/ai-assistant/",
|
||||
GPTIntegrationEndpoint.as_view(),
|
||||
name="importer",
|
||||
),
|
||||
path(
|
||||
path(
|
||||
"workspaces/<str:slug>/ai-assistant/",
|
||||
WorkspaceGPTIntegrationEndpoint.as_view(),
|
||||
name="importer",
|
||||
|
||||
@@ -9,7 +9,7 @@ from plane.app.views import (
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/inboxes/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/inboxes/",
|
||||
InboxViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -19,7 +19,7 @@ urlpatterns = [
|
||||
name="inbox",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/inboxes/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/inboxes/<uuid:pk>/",
|
||||
InboxViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -30,7 +30,7 @@ urlpatterns = [
|
||||
name="inbox",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/inbox-issues/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/inbox-issues/",
|
||||
InboxIssueViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -40,7 +40,7 @@ urlpatterns = [
|
||||
name="inbox-issue",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/inbox-issues/<uuid:issue_id>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/inbox-issues/<uuid:issue_id>/",
|
||||
InboxIssueViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
|
||||
@@ -25,12 +25,12 @@ from plane.app.views import (
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/list/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/list/",
|
||||
IssueListEndpoint.as_view(),
|
||||
name="project-issue",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/",
|
||||
IssueViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -40,7 +40,7 @@ urlpatterns = [
|
||||
name="project-issue",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<str:pk>/",
|
||||
IssueViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -52,7 +52,7 @@ urlpatterns = [
|
||||
name="project-issue",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-labels/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issue-labels/",
|
||||
LabelViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -62,7 +62,7 @@ urlpatterns = [
|
||||
name="project-issue-labels",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-labels/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issue-labels/<uuid:pk>/",
|
||||
LabelViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -74,28 +74,28 @@ urlpatterns = [
|
||||
name="project-issue-labels",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/bulk-create-labels/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/bulk-create-labels/",
|
||||
BulkCreateIssueLabelsEndpoint.as_view(),
|
||||
name="project-bulk-labels",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/bulk-delete-issues/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/bulk-delete-issues/",
|
||||
BulkDeleteIssuesEndpoint.as_view(),
|
||||
name="project-issues-bulk",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/bulk-archive-issues/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/bulk-archive-issues/",
|
||||
BulkArchiveIssuesEndpoint.as_view(),
|
||||
name="bulk-archive-issues",
|
||||
),
|
||||
##
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/sub-issues/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/sub-issues/",
|
||||
SubIssuesEndpoint.as_view(),
|
||||
name="sub-issues",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/issue-links/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/issue-links/",
|
||||
IssueLinkViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -105,7 +105,7 @@ urlpatterns = [
|
||||
name="project-issue-links",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/issue-links/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/issue-links/<uuid:pk>/",
|
||||
IssueLinkViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -117,12 +117,12 @@ urlpatterns = [
|
||||
name="project-issue-links",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/issue-attachments/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/issue-attachments/",
|
||||
IssueAttachmentEndpoint.as_view(),
|
||||
name="project-issue-attachments",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/issue-attachments/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/issue-attachments/<uuid:pk>/",
|
||||
IssueAttachmentEndpoint.as_view(),
|
||||
name="project-issue-attachments",
|
||||
),
|
||||
@@ -134,14 +134,14 @@ urlpatterns = [
|
||||
## End Issues
|
||||
## Issue Activity
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/history/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/history/",
|
||||
IssueActivityEndpoint.as_view(),
|
||||
name="project-issue-history",
|
||||
),
|
||||
## Issue Activity
|
||||
## IssueComments
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/comments/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/comments/",
|
||||
IssueCommentViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -151,7 +151,7 @@ urlpatterns = [
|
||||
name="project-issue-comment",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/comments/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/comments/<uuid:pk>/",
|
||||
IssueCommentViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -165,7 +165,7 @@ urlpatterns = [
|
||||
## End IssueComments
|
||||
# Issue Subscribers
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/issue-subscribers/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/issue-subscribers/",
|
||||
IssueSubscriberViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -175,12 +175,12 @@ urlpatterns = [
|
||||
name="project-issue-subscribers",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/issue-subscribers/<uuid:subscriber_id>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/issue-subscribers/<uuid:subscriber_id>/",
|
||||
IssueSubscriberViewSet.as_view({"delete": "destroy"}),
|
||||
name="project-issue-subscribers",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/subscribe/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/subscribe/",
|
||||
IssueSubscriberViewSet.as_view(
|
||||
{
|
||||
"get": "subscription_status",
|
||||
@@ -193,7 +193,7 @@ urlpatterns = [
|
||||
## End Issue Subscribers
|
||||
# Issue Reactions
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/reactions/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/reactions/",
|
||||
IssueReactionViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -203,7 +203,7 @@ urlpatterns = [
|
||||
name="project-issue-reactions",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/reactions/<str:reaction_code>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/reactions/<str:reaction_code>/",
|
||||
IssueReactionViewSet.as_view(
|
||||
{
|
||||
"delete": "destroy",
|
||||
@@ -214,7 +214,7 @@ urlpatterns = [
|
||||
## End Issue Reactions
|
||||
# Comment Reactions
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/comments/<uuid:comment_id>/reactions/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/comments/<uuid:comment_id>/reactions/",
|
||||
CommentReactionViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -224,7 +224,7 @@ urlpatterns = [
|
||||
name="project-issue-comment-reactions",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/comments/<uuid:comment_id>/reactions/<str:reaction_code>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/comments/<uuid:comment_id>/reactions/<str:reaction_code>/",
|
||||
CommentReactionViewSet.as_view(
|
||||
{
|
||||
"delete": "destroy",
|
||||
@@ -235,14 +235,14 @@ urlpatterns = [
|
||||
## End Comment Reactions
|
||||
## IssueProperty
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/user-properties/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/user-properties/",
|
||||
IssueUserDisplayPropertyEndpoint.as_view(),
|
||||
name="project-issue-display-properties",
|
||||
),
|
||||
## IssueProperty End
|
||||
## Issue Archives
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/archived-issues/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/archived-issues/",
|
||||
IssueArchiveViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -251,7 +251,7 @@ urlpatterns = [
|
||||
name="project-issue-archive",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:pk>/archive/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:pk>/archive/",
|
||||
IssueArchiveViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -264,7 +264,7 @@ urlpatterns = [
|
||||
## End Issue Archives
|
||||
## Issue Relation
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/issue-relation/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/issue-relation/",
|
||||
IssueRelationViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -274,7 +274,7 @@ urlpatterns = [
|
||||
name="issue-relation",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/remove-relation/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/remove-relation/",
|
||||
IssueRelationViewSet.as_view(
|
||||
{
|
||||
"post": "remove_relation",
|
||||
@@ -285,7 +285,7 @@ urlpatterns = [
|
||||
## End Issue Relation
|
||||
## Issue Drafts
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-drafts/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issue-drafts/",
|
||||
IssueDraftViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -295,7 +295,7 @@ urlpatterns = [
|
||||
name="project-issue-draft",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issue-drafts/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issue-drafts/<uuid:pk>/",
|
||||
IssueDraftViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -306,7 +306,7 @@ urlpatterns = [
|
||||
name="project-issue-draft",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/bulk-operation-issues/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/bulk-operation-issues/",
|
||||
BulkIssueOperationsEndpoint.as_view(),
|
||||
name="bulk-operations-issues",
|
||||
),
|
||||
|
||||
@@ -13,7 +13,7 @@ from plane.app.views import (
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/modules/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/modules/",
|
||||
ModuleViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -23,7 +23,7 @@ urlpatterns = [
|
||||
name="project-modules",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/modules/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/modules/<uuid:pk>/",
|
||||
ModuleViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -35,7 +35,7 @@ urlpatterns = [
|
||||
name="project-modules",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/issues/<uuid:issue_id>/modules/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/issues/<uuid:issue_id>/modules/",
|
||||
ModuleIssueViewSet.as_view(
|
||||
{
|
||||
"post": "create_issue_modules",
|
||||
@@ -44,7 +44,7 @@ urlpatterns = [
|
||||
name="issue-module",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/modules/<uuid:module_id>/issues/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/modules/<uuid:module_id>/issues/",
|
||||
ModuleIssueViewSet.as_view(
|
||||
{
|
||||
"post": "create_module_issues",
|
||||
@@ -54,7 +54,7 @@ urlpatterns = [
|
||||
name="project-module-issues",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/modules/<uuid:module_id>/issues/<uuid:issue_id>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/modules/<uuid:module_id>/issues/<uuid:issue_id>/",
|
||||
ModuleIssueViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -66,7 +66,7 @@ urlpatterns = [
|
||||
name="project-module-issues",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/modules/<uuid:module_id>/module-links/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/modules/<uuid:module_id>/module-links/",
|
||||
ModuleLinkViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -76,7 +76,7 @@ urlpatterns = [
|
||||
name="project-issue-module-links",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/modules/<uuid:module_id>/module-links/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/modules/<uuid:module_id>/module-links/<uuid:pk>/",
|
||||
ModuleLinkViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -88,7 +88,7 @@ urlpatterns = [
|
||||
name="project-issue-module-links",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-modules/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/user-favorite-modules/",
|
||||
ModuleFavoriteViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -98,7 +98,7 @@ urlpatterns = [
|
||||
name="user-favorite-module",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-modules/<uuid:module_id>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/user-favorite-modules/<uuid:module_id>/",
|
||||
ModuleFavoriteViewSet.as_view(
|
||||
{
|
||||
"delete": "destroy",
|
||||
@@ -107,22 +107,22 @@ urlpatterns = [
|
||||
name="user-favorite-module",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/modules/<uuid:module_id>/user-properties/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/modules/<uuid:module_id>/user-properties/",
|
||||
ModuleUserPropertiesEndpoint.as_view(),
|
||||
name="cycle-user-filters",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/modules/<uuid:module_id>/archive/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/modules/<uuid:module_id>/archive/",
|
||||
ModuleArchiveUnarchiveEndpoint.as_view(),
|
||||
name="module-archive-unarchive",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/archived-modules/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/archived-modules/",
|
||||
ModuleArchiveUnarchiveEndpoint.as_view(),
|
||||
name="module-archive-unarchive",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/archived-modules/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/archived-modules/<uuid:pk>/",
|
||||
ModuleArchiveUnarchiveEndpoint.as_view(),
|
||||
name="module-archive-unarchive",
|
||||
),
|
||||
|
||||
@@ -12,7 +12,7 @@ from plane.app.views import (
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/pages/",
|
||||
PageViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -22,7 +22,7 @@ urlpatterns = [
|
||||
name="project-pages",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/pages/<uuid:pk>/",
|
||||
PageViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -34,7 +34,7 @@ urlpatterns = [
|
||||
),
|
||||
# favorite pages
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/favorite-pages/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/favorite-pages/<uuid:pk>/",
|
||||
PageFavoriteViewSet.as_view(
|
||||
{
|
||||
"post": "create",
|
||||
@@ -45,7 +45,7 @@ urlpatterns = [
|
||||
),
|
||||
# archived pages
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:pk>/archive/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/pages/<uuid:pk>/archive/",
|
||||
PageViewSet.as_view(
|
||||
{
|
||||
"post": "archive",
|
||||
@@ -56,7 +56,7 @@ urlpatterns = [
|
||||
),
|
||||
# lock and unlock
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:pk>/lock/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/pages/<uuid:pk>/lock/",
|
||||
PageViewSet.as_view(
|
||||
{
|
||||
"post": "lock",
|
||||
@@ -66,22 +66,22 @@ urlpatterns = [
|
||||
name="project-pages-lock-unlock",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:pk>/transactions/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/pages/<uuid:pk>/transactions/",
|
||||
PageLogEndpoint.as_view(),
|
||||
name="page-transactions",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:pk>/transactions/<uuid:transaction>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/pages/<uuid:pk>/transactions/<uuid:transaction>/",
|
||||
PageLogEndpoint.as_view(),
|
||||
name="page-transactions",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:pk>/sub-pages/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/pages/<uuid:pk>/sub-pages/",
|
||||
SubPagesEndpoint.as_view(),
|
||||
name="sub-page",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/pages/<uuid:pk>/description/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/pages/<uuid:pk>/description/",
|
||||
PagesDescriptionViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
|
||||
@@ -30,7 +30,7 @@ urlpatterns = [
|
||||
name="project",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:pk>/",
|
||||
ProjectViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -47,7 +47,7 @@ urlpatterns = [
|
||||
name="project-identifiers",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/invitations/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/invitations/",
|
||||
ProjectInvitationsViewset.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -57,7 +57,7 @@ urlpatterns = [
|
||||
name="project-member-invite",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/invitations/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/invitations/<uuid:pk>/",
|
||||
ProjectInvitationsViewset.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -82,12 +82,12 @@ urlpatterns = [
|
||||
name="user-project-roles",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/join/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/join/<uuid:pk>/",
|
||||
ProjectJoinEndpoint.as_view(),
|
||||
name="project-join",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/members/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/members/",
|
||||
ProjectMemberViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -97,7 +97,7 @@ urlpatterns = [
|
||||
name="project-member",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/members/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/members/<uuid:pk>/",
|
||||
ProjectMemberViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -108,7 +108,7 @@ urlpatterns = [
|
||||
name="project-member",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/members/leave/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/members/leave/",
|
||||
ProjectMemberViewSet.as_view(
|
||||
{
|
||||
"post": "leave",
|
||||
@@ -117,17 +117,17 @@ urlpatterns = [
|
||||
name="project-member",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/team-invite/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/team-invite/",
|
||||
AddTeamToProjectEndpoint.as_view(),
|
||||
name="projects",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/project-views/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/project-views/",
|
||||
ProjectUserViewsEndpoint.as_view(),
|
||||
name="project-view",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/project-members/me/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/project-members/me/",
|
||||
ProjectMemberUserEndpoint.as_view(),
|
||||
name="project-member-view",
|
||||
),
|
||||
@@ -142,7 +142,7 @@ urlpatterns = [
|
||||
name="project-favorite",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/user-favorite-projects/<uuid:project_id>/",
|
||||
"workspaces/<str:slug>/user-favorite-projects/<str:project_id>/",
|
||||
ProjectFavoritesViewSet.as_view(
|
||||
{
|
||||
"delete": "destroy",
|
||||
@@ -156,7 +156,7 @@ urlpatterns = [
|
||||
name="project-covers",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/project-deploy-boards/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/project-deploy-boards/",
|
||||
DeployBoardViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -166,7 +166,7 @@ urlpatterns = [
|
||||
name="project-deploy-board",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/project-deploy-boards/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/project-deploy-boards/<uuid:pk>/",
|
||||
DeployBoardViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -177,7 +177,7 @@ urlpatterns = [
|
||||
name="project-deploy-board",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/archive/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/archive/",
|
||||
ProjectArchiveUnarchiveEndpoint.as_view(),
|
||||
name="project-archive-unarchive",
|
||||
),
|
||||
|
||||
@@ -14,7 +14,7 @@ urlpatterns = [
|
||||
name="global-search",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/search-issues/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/search-issues/",
|
||||
IssueSearchEndpoint.as_view(),
|
||||
name="project-issue-search",
|
||||
),
|
||||
|
||||
@@ -6,7 +6,7 @@ from plane.app.views import StateViewSet
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/states/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/states/",
|
||||
StateViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -16,7 +16,7 @@ urlpatterns = [
|
||||
name="project-states",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/states/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/states/<uuid:pk>/",
|
||||
StateViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -27,7 +27,7 @@ urlpatterns = [
|
||||
name="project-state",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/states/<uuid:pk>/mark-default/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/states/<uuid:pk>/mark-default/",
|
||||
StateViewSet.as_view(
|
||||
{
|
||||
"post": "mark_as_default",
|
||||
|
||||
@@ -11,7 +11,7 @@ from plane.app.views import (
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/views/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/views/",
|
||||
IssueViewViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -21,7 +21,7 @@ urlpatterns = [
|
||||
name="project-view",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/views/<uuid:pk>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/views/<uuid:pk>/",
|
||||
IssueViewViewSet.as_view(
|
||||
{
|
||||
"get": "retrieve",
|
||||
@@ -64,7 +64,7 @@ urlpatterns = [
|
||||
name="global-view-issues",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-views/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/user-favorite-views/",
|
||||
IssueViewFavoriteViewSet.as_view(
|
||||
{
|
||||
"get": "list",
|
||||
@@ -74,7 +74,7 @@ urlpatterns = [
|
||||
name="user-favorite-view",
|
||||
),
|
||||
path(
|
||||
"workspaces/<str:slug>/projects/<uuid:project_id>/user-favorite-views/<uuid:view_id>/",
|
||||
"workspaces/<str:slug>/projects/<str:project_id>/user-favorite-views/<uuid:view_id>/",
|
||||
IssueViewFavoriteViewSet.as_view(
|
||||
{
|
||||
"delete": "destroy",
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Python imports
|
||||
import traceback
|
||||
|
||||
import uuid
|
||||
import zoneinfo
|
||||
|
||||
# Django imports
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
||||
from django.db import IntegrityError
|
||||
|
||||
# Django imports
|
||||
from django.urls import resolve
|
||||
from django.utils import timezone
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
@@ -24,6 +24,7 @@ from rest_framework.viewsets import ModelViewSet
|
||||
from plane.authentication.session import BaseSessionAuthentication
|
||||
from plane.utils.exception_logger import log_exception
|
||||
from plane.utils.paginator import BasePaginator
|
||||
from plane.db.models import ProjectIdentifier
|
||||
|
||||
|
||||
class TimezoneMixin:
|
||||
@@ -60,6 +61,38 @@ class BaseViewSet(TimezoneMixin, ModelViewSet, BasePaginator):
|
||||
|
||||
search_fields = []
|
||||
|
||||
def is_uuid(self, value):
|
||||
try:
|
||||
# Check if the value is a valid UUID
|
||||
uuid.UUID(str(value))
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
def get_project_id(self, project_id):
|
||||
# If the project_id is present and is not a UUID then get the project_id from the project_identifier
|
||||
if project_id and not self.is_uuid(project_id):
|
||||
project_identifier = (
|
||||
ProjectIdentifier.objects.filter(
|
||||
workspace__slug=self.workspace_slug, name=project_id
|
||||
)
|
||||
.values("project_id")
|
||||
.first()
|
||||
)
|
||||
# If the project_identifier is not present then raise ObjectDoesNotExist
|
||||
if not project_identifier:
|
||||
raise ObjectDoesNotExist
|
||||
|
||||
# Update the project_id in the kwargs
|
||||
return project_identifier.get("project_id")
|
||||
return project_id
|
||||
|
||||
def get_issue_id(self, issue_id):
|
||||
# If the issue_id is present and is not a UUID then get the issue_id from the issue_identifier
|
||||
if issue_id and not self.is_uuid(issue_id):
|
||||
pass
|
||||
return issue_id
|
||||
|
||||
def get_queryset(self):
|
||||
try:
|
||||
return self.model.objects.all()
|
||||
@@ -116,8 +149,18 @@ class BaseViewSet(TimezoneMixin, ModelViewSet, BasePaginator):
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
try:
|
||||
# Write identifier to the uuid
|
||||
project_id = self.kwargs.get("project_id", None)
|
||||
if project_id:
|
||||
self.kwargs["project_id"] = self.get_project_id(project_id)
|
||||
# Check issue_id is present in the kwargs
|
||||
issue_id = self.kwargs.get("issue_id", None)
|
||||
if issue_id:
|
||||
self.kwargs["issue_id"] = self.get_issue_id(issue_id)
|
||||
# If the project_id is not present then get the project_id from the project_identifier
|
||||
response = super().dispatch(request, *args, **kwargs)
|
||||
|
||||
# Print the number of queries if the debug is enabled
|
||||
if settings.DEBUG:
|
||||
from django.db import connection
|
||||
|
||||
@@ -125,6 +168,7 @@ class BaseViewSet(TimezoneMixin, ModelViewSet, BasePaginator):
|
||||
f"{request.method} - {request.get_full_path()} of Queries: {len(connection.queries)}"
|
||||
)
|
||||
|
||||
# Return the response
|
||||
return response
|
||||
except Exception as exc:
|
||||
response = self.handle_exception(exc)
|
||||
|
||||
@@ -58,8 +58,7 @@ from plane.utils.paginator import (
|
||||
)
|
||||
from .. import BaseAPIView, BaseViewSet
|
||||
from plane.utils.user_timezone_converter import user_timezone_converter
|
||||
|
||||
# Module imports
|
||||
from plane.utils.valid_int_uuid import is_int_or_uuid
|
||||
|
||||
|
||||
class IssueListEndpoint(BaseAPIView):
|
||||
@@ -410,9 +409,10 @@ class IssueViewSet(BaseViewSet):
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def retrieve(self, request, slug, project_id, pk=None):
|
||||
type, value = is_int_or_uuid(pk)
|
||||
|
||||
issue = (
|
||||
self.get_queryset()
|
||||
.filter(pk=pk)
|
||||
.annotate(
|
||||
label_ids=Coalesce(
|
||||
ArrayAgg(
|
||||
@@ -470,7 +470,18 @@ class IssueViewSet(BaseViewSet):
|
||||
)
|
||||
)
|
||||
)
|
||||
).first()
|
||||
)
|
||||
if type == "int":
|
||||
issue = issue.filter(sequence_id=pk)
|
||||
elif type == "uuid":
|
||||
issue = issue.filter(pk=pk)
|
||||
else:
|
||||
return Response(
|
||||
{"error": "Invalid issue id"},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
issue = issue.first()
|
||||
if not issue:
|
||||
return Response(
|
||||
{"error": "The required object does not exist."},
|
||||
|
||||
@@ -61,6 +61,21 @@ class ProjectViewSet(BaseViewSet):
|
||||
ProjectBasePermission,
|
||||
]
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
pk = kwargs.get("pk")
|
||||
if pk and not self.is_uuid(pk):
|
||||
project = (
|
||||
ProjectIdentifier.objects.filter(
|
||||
name=pk, workspace__slug=kwargs.get("slug")
|
||||
)
|
||||
.values("project")
|
||||
.first()
|
||||
)
|
||||
if project:
|
||||
kwargs["pk"] = project["project"]
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self):
|
||||
sort_order = ProjectMember.objects.filter(
|
||||
member=self.request.user,
|
||||
@@ -484,32 +499,39 @@ class ProjectIdentifierEndpoint(BaseAPIView):
|
||||
]
|
||||
|
||||
def get(self, request, slug):
|
||||
# Get the identifier name
|
||||
name = request.GET.get("name", "").strip().upper()
|
||||
|
||||
# Check if the name is passed
|
||||
if name == "":
|
||||
return Response(
|
||||
{"error": "Name is required"},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
# Check if the identifier exists
|
||||
exists = ProjectIdentifier.objects.filter(
|
||||
name=name, workspace__slug=slug
|
||||
).values("id", "name", "project")
|
||||
|
||||
# Return the response
|
||||
return Response(
|
||||
{"exists": len(exists), "identifiers": exists},
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
def delete(self, request, slug):
|
||||
# Get the identifier name
|
||||
name = request.data.get("name", "").strip().upper()
|
||||
|
||||
# Check if the name is passed
|
||||
if name == "":
|
||||
return Response(
|
||||
{"error": "Name is required"},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
# Check if the identifier is used in any project
|
||||
if Project.objects.filter(
|
||||
identifier=name, workspace__slug=slug
|
||||
).exists():
|
||||
@@ -520,10 +542,12 @@ class ProjectIdentifierEndpoint(BaseAPIView):
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
# Delete the identifier
|
||||
ProjectIdentifier.objects.filter(
|
||||
name=name, workspace__slug=slug
|
||||
).delete()
|
||||
|
||||
# Return success
|
||||
return Response(
|
||||
status=status.HTTP_204_NO_CONTENT,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# Generated by Django 4.2.11 on 2024-06-25 07:32
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
def migrate_current_active(apps, schema_editor):
|
||||
ProjectIdentifier = apps.get_model("db", "ProjectIdentifier")
|
||||
|
||||
# Update current_active field with name field
|
||||
ProjectIdentifier.objects.update(current_active=models.F("name"))
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("db", "0069_alter_account_provider_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="projectidentifier",
|
||||
name="current_active",
|
||||
field=models.CharField(db_index=True, max_length=12, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="projectidentifier",
|
||||
name="name",
|
||||
field=models.CharField(db_index=True, max_length=12),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="projectidentifier",
|
||||
name="project",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="project_identifier",
|
||||
to="db.project",
|
||||
),
|
||||
),
|
||||
migrations.RunPython(migrate_current_active),
|
||||
]
|
||||
@@ -206,7 +206,6 @@ class ProjectMember(ProjectBaseModel):
|
||||
return f"{self.member.email} <{self.project.name}>"
|
||||
|
||||
|
||||
# TODO: Remove workspace relation later
|
||||
class ProjectIdentifier(AuditModel):
|
||||
workspace = models.ForeignKey(
|
||||
"db.Workspace",
|
||||
@@ -214,10 +213,11 @@ class ProjectIdentifier(AuditModel):
|
||||
related_name="project_identifiers",
|
||||
null=True,
|
||||
)
|
||||
project = models.OneToOneField(
|
||||
project = models.ForeignKey(
|
||||
Project, on_delete=models.CASCADE, related_name="project_identifier"
|
||||
)
|
||||
name = models.CharField(max_length=12)
|
||||
name = models.CharField(max_length=12, db_index=True)
|
||||
current_active = models.CharField(max_length=12, db_index=True, null=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = ["name", "workspace"]
|
||||
|
||||
@@ -8,7 +8,10 @@ DEBUG = True
|
||||
|
||||
# Debug Toolbar settings
|
||||
INSTALLED_APPS += ("debug_toolbar",) # noqa
|
||||
MIDDLEWARE += ("debug_toolbar.middleware.DebugToolbarMiddleware",) # noqa
|
||||
MIDDLEWARE += ( # noqa
|
||||
"debug_toolbar.middleware.DebugToolbarMiddleware",
|
||||
"kolo.middleware.KoloMiddleware",
|
||||
)
|
||||
|
||||
DEBUG_TOOLBAR_PATCH_SETTINGS = False
|
||||
|
||||
|
||||
20
apiserver/plane/utils/valid_int_uuid.py
Normal file
20
apiserver/plane/utils/valid_int_uuid.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# Python imports
|
||||
import uuid
|
||||
|
||||
|
||||
def is_int_or_uuid(value):
|
||||
# Check if the value can be converted to an integer
|
||||
try:
|
||||
int_value = int(value)
|
||||
return "int", int_value
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Check if the value can be converted to a UUID
|
||||
try:
|
||||
uuid_value = uuid.UUID(str(value))
|
||||
return "uuid", uuid_value
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return "", None
|
||||
Reference in New Issue
Block a user