fix: state group choices (#8198)
This commit is contained in:
parent
2980836015
commit
c7bf912cf2
14 changed files with 87 additions and 142 deletions
|
|
@ -1,7 +1,7 @@
|
|||
# Module imports
|
||||
from .base import BaseSerializer
|
||||
from .issue import IssueExpandSerializer
|
||||
from plane.db.models import IntakeIssue, Issue
|
||||
from plane.db.models import IntakeIssue, Issue, State, StateGroup
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
|
|
@ -108,7 +108,6 @@ class IntakeIssueUpdateSerializer(BaseSerializer):
|
|||
Validate that if status is being changed to accepted (1),
|
||||
the project has a default state to transition to.
|
||||
"""
|
||||
from plane.db.models import State
|
||||
|
||||
# Check if status is being updated to accepted
|
||||
if attrs.get("status") == 1:
|
||||
|
|
@ -116,7 +115,7 @@ class IntakeIssueUpdateSerializer(BaseSerializer):
|
|||
issue = intake_issue.issue
|
||||
|
||||
# Check if issue is in TRIAGE state
|
||||
if issue.state and issue.state.group == State.TRIAGE:
|
||||
if issue.state and issue.state.group == StateGroup.TRIAGE.value:
|
||||
# Verify default state exists before allowing the update
|
||||
default_state = State.objects.filter(
|
||||
workspace=intake_issue.workspace, project=intake_issue.project, default=True
|
||||
|
|
@ -133,7 +132,6 @@ class IntakeIssueUpdateSerializer(BaseSerializer):
|
|||
"""
|
||||
Update intake issue and transition associated issue state if accepted.
|
||||
"""
|
||||
from plane.db.models import State
|
||||
|
||||
# Update the intake issue with validated data
|
||||
instance = super().update(instance, validated_data)
|
||||
|
|
@ -141,7 +139,7 @@ class IntakeIssueUpdateSerializer(BaseSerializer):
|
|||
# If status is accepted (1), update the associated issue state from TRIAGE to default
|
||||
if validated_data.get("status") == 1:
|
||||
issue = instance.issue
|
||||
if issue.state and issue.state.group == State.TRIAGE:
|
||||
if issue.state and issue.state.group == StateGroup.TRIAGE.value:
|
||||
# Get the default project state
|
||||
default_state = State.objects.filter(
|
||||
workspace=instance.workspace, project=instance.project, default=True
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Module imports
|
||||
from .base import BaseSerializer
|
||||
from plane.db.models import State
|
||||
from plane.db.models import State, StateGroup
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ class StateSerializer(BaseSerializer):
|
|||
if data.get("default", False):
|
||||
State.objects.filter(project_id=self.context.get("project_id")).update(default=False)
|
||||
|
||||
if data.get("group", None) == State.TRIAGE:
|
||||
if data.get("group", None) == StateGroup.TRIAGE.value:
|
||||
raise serializers.ValidationError("Cannot create triage state")
|
||||
return data
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ from plane.api.serializers import (
|
|||
)
|
||||
from plane.app.permissions import ProjectLitePermission
|
||||
from plane.bgtasks.issue_activities_task import issue_activity
|
||||
from plane.db.models import Intake, IntakeIssue, Issue, Project, ProjectMember, State
|
||||
from plane.db.models import Intake, IntakeIssue, Issue, Project, ProjectMember, State, StateGroup
|
||||
from plane.utils.host import base_host
|
||||
from .base import BaseAPIView
|
||||
from plane.db.models.intake import SourceType
|
||||
|
|
@ -170,8 +170,8 @@ class IntakeIssueListCreateAPIEndpoint(BaseAPIView):
|
|||
|
||||
if not triage_state:
|
||||
triage_state = State.objects.create(
|
||||
name="Intake Triage",
|
||||
group=State.TRIAGE,
|
||||
name="Triage",
|
||||
group=StateGroup.TRIAGE.value,
|
||||
project_id=project_id,
|
||||
workspace_id=project.workspace_id,
|
||||
color="#4E5355",
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ from plane.db.models import (
|
|||
DeployBoard,
|
||||
ProjectMember,
|
||||
State,
|
||||
DEFAULT_STATES,
|
||||
Workspace,
|
||||
UserFavorite,
|
||||
)
|
||||
|
|
@ -232,47 +233,6 @@ class ProjectListCreateAPIEndpoint(BaseAPIView):
|
|||
user_id=serializer.instance.project_lead,
|
||||
)
|
||||
|
||||
# Default states
|
||||
states = [
|
||||
{
|
||||
"name": "Backlog",
|
||||
"color": "#60646C",
|
||||
"sequence": 15000,
|
||||
"group": "backlog",
|
||||
"default": True,
|
||||
},
|
||||
{
|
||||
"name": "Todo",
|
||||
"color": "#60646C",
|
||||
"sequence": 25000,
|
||||
"group": "unstarted",
|
||||
},
|
||||
{
|
||||
"name": "In Progress",
|
||||
"color": "#F59E0B",
|
||||
"sequence": 35000,
|
||||
"group": "started",
|
||||
},
|
||||
{
|
||||
"name": "Done",
|
||||
"color": "#46A758",
|
||||
"sequence": 45000,
|
||||
"group": "completed",
|
||||
},
|
||||
{
|
||||
"name": "Cancelled",
|
||||
"color": "#9AA4BC",
|
||||
"sequence": 55000,
|
||||
"group": "cancelled",
|
||||
},
|
||||
{
|
||||
"name": "Intake Triage",
|
||||
"color": "#4E5355",
|
||||
"sequence": 65000,
|
||||
"group": State.TRIAGE,
|
||||
},
|
||||
]
|
||||
|
||||
State.objects.bulk_create(
|
||||
[
|
||||
State(
|
||||
|
|
@ -285,7 +245,7 @@ class ProjectListCreateAPIEndpoint(BaseAPIView):
|
|||
default=state.get("default", False),
|
||||
created_by=request.user,
|
||||
)
|
||||
for state in states
|
||||
for state in DEFAULT_STATES
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from .issue import IssueIntakeSerializer, LabelLiteSerializer, IssueDetailSerial
|
|||
from .project import ProjectLiteSerializer
|
||||
from .state import StateLiteSerializer
|
||||
from .user import UserLiteSerializer
|
||||
from plane.db.models import Intake, IntakeIssue, Issue
|
||||
from plane.db.models import Intake, IntakeIssue, Issue, StateGroup, State
|
||||
|
||||
|
||||
class IntakeSerializer(BaseSerializer):
|
||||
|
|
@ -41,7 +41,6 @@ class IntakeIssueSerializer(BaseSerializer):
|
|||
Validate that if status is being changed to accepted (1),
|
||||
the project has a default state to transition to.
|
||||
"""
|
||||
from plane.db.models import State
|
||||
|
||||
# Check if status is being updated to accepted
|
||||
if attrs.get("status") == 1:
|
||||
|
|
@ -49,7 +48,7 @@ class IntakeIssueSerializer(BaseSerializer):
|
|||
issue = intake_issue.issue
|
||||
|
||||
# Check if issue is in TRIAGE state
|
||||
if issue.state and issue.state.group == State.TRIAGE:
|
||||
if issue.state and issue.state.group == StateGroup.TRIAGE.value:
|
||||
# Verify default state exists before allowing the update
|
||||
default_state = State.objects.filter(
|
||||
workspace=intake_issue.workspace, project=intake_issue.project, default=True
|
||||
|
|
@ -63,20 +62,16 @@ class IntakeIssueSerializer(BaseSerializer):
|
|||
return attrs
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
from plane.db.models import State
|
||||
|
||||
# Update the intake issue
|
||||
instance = super().update(instance, validated_data)
|
||||
|
||||
# If status is accepted (1), transition the issue state from TRIAGE to default
|
||||
if validated_data.get("status") == 1:
|
||||
issue = instance.issue
|
||||
if issue.state and issue.state.group == State.TRIAGE:
|
||||
if issue.state and issue.state.group == StateGroup.TRIAGE.value:
|
||||
# Get the default project state
|
||||
default_state = State.objects.filter(
|
||||
workspace=instance.workspace,
|
||||
project=instance.project,
|
||||
default=True
|
||||
workspace=instance.workspace, project=instance.project, default=True
|
||||
).first()
|
||||
if default_state:
|
||||
issue.state = default_state
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
from .base import BaseSerializer
|
||||
from rest_framework import serializers
|
||||
|
||||
from plane.db.models import State
|
||||
from plane.db.models import State, StateGroup
|
||||
|
||||
|
||||
class StateSerializer(BaseSerializer):
|
||||
|
|
@ -25,8 +25,7 @@ class StateSerializer(BaseSerializer):
|
|||
read_only_fields = ["workspace", "project"]
|
||||
|
||||
def validate(self, attrs):
|
||||
|
||||
if attrs.get("group") == State.TRIAGE:
|
||||
if attrs.get("group") == StateGroup.TRIAGE.value:
|
||||
raise serializers.ValidationError("Cannot create triage state")
|
||||
return attrs
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ from plane.db.models import (
|
|||
IntakeIssue,
|
||||
Issue,
|
||||
State,
|
||||
StateGroup,
|
||||
IssueLink,
|
||||
FileAsset,
|
||||
Project,
|
||||
|
|
@ -234,8 +235,8 @@ class IntakeIssueViewSet(BaseViewSet):
|
|||
triage_state = State.triage_objects.filter(project_id=project_id, workspace__slug=slug).first()
|
||||
if not triage_state:
|
||||
triage_state = State.objects.create(
|
||||
name="Intake Triage",
|
||||
group=State.TRIAGE,
|
||||
name="Triage",
|
||||
group=StateGroup.TRIAGE.value,
|
||||
project_id=project_id,
|
||||
workspace_id=project.workspace_id,
|
||||
color="#4E5355",
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ from plane.db.models import (
|
|||
ProjectIdentifier,
|
||||
ProjectMember,
|
||||
State,
|
||||
DEFAULT_STATES,
|
||||
Workspace,
|
||||
WorkspaceMember,
|
||||
)
|
||||
|
|
@ -264,47 +265,6 @@ class ProjectViewSet(BaseViewSet):
|
|||
user_id=serializer.data["project_lead"],
|
||||
)
|
||||
|
||||
# Default states
|
||||
states = [
|
||||
{
|
||||
"name": "Backlog",
|
||||
"color": "#60646C",
|
||||
"sequence": 15000,
|
||||
"group": "backlog",
|
||||
"default": True,
|
||||
},
|
||||
{
|
||||
"name": "Todo",
|
||||
"color": "#60646C",
|
||||
"sequence": 25000,
|
||||
"group": "unstarted",
|
||||
},
|
||||
{
|
||||
"name": "In Progress",
|
||||
"color": "#F59E0B",
|
||||
"sequence": 35000,
|
||||
"group": "started",
|
||||
},
|
||||
{
|
||||
"name": "Done",
|
||||
"color": "#46A758",
|
||||
"sequence": 45000,
|
||||
"group": "completed",
|
||||
},
|
||||
{
|
||||
"name": "Cancelled",
|
||||
"color": "#9AA4BC",
|
||||
"sequence": 55000,
|
||||
"group": "cancelled",
|
||||
},
|
||||
{
|
||||
"name": "Intake Triage",
|
||||
"color": "#4E5355",
|
||||
"sequence": 65000,
|
||||
"group": State.TRIAGE,
|
||||
},
|
||||
]
|
||||
|
||||
State.objects.bulk_create(
|
||||
[
|
||||
State(
|
||||
|
|
@ -317,7 +277,7 @@ class ProjectViewSet(BaseViewSet):
|
|||
default=state.get("default", False),
|
||||
created_by=request.user,
|
||||
)
|
||||
for state in states
|
||||
for state in DEFAULT_STATES
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ class IntakeStateEndpoint(BaseAPIView):
|
|||
state = State.triage_objects.filter(workspace__slug=slug, project_id=project_id).first()
|
||||
if not state:
|
||||
return Response(
|
||||
{"error": "Intake triage state not found"},
|
||||
{"error": "Triage state not found"},
|
||||
status=status.HTTP_404_NOT_FOUND,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ from plane.db.models import (
|
|||
Project,
|
||||
ProjectMember,
|
||||
State,
|
||||
StateGroup,
|
||||
Label,
|
||||
Cycle,
|
||||
Module,
|
||||
|
|
@ -264,7 +265,9 @@ def create_issues(workspace, project, user_id, issue_count):
|
|||
Faker.seed(0)
|
||||
|
||||
states = (
|
||||
State.objects.filter(workspace=workspace, project=project).exclude(group=State.TRIAGE).values_list("id", flat=True)
|
||||
State.objects.filter(workspace=workspace, project=project)
|
||||
.exclude(group=StateGroup.TRIAGE.value)
|
||||
.values_list("id", flat=True)
|
||||
)
|
||||
creators = ProjectMember.objects.filter(workspace=workspace, project=project).values_list("member_id", flat=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ from .project import (
|
|||
)
|
||||
from .session import Session
|
||||
from .social_connection import SocialLoginConnection
|
||||
from .state import State
|
||||
from .state import State, StateGroup, DEFAULT_STATES
|
||||
from .user import Account, Profile, User
|
||||
from .view import IssueView
|
||||
from .webhook import Webhook, WebhookLog
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ from .project import ProjectBaseModel
|
|||
from plane.utils.uuid import convert_uuid_to_integer
|
||||
from .description import Description
|
||||
from plane.db.mixins import ChangeTrackerMixin
|
||||
from .state import State
|
||||
from .state import StateGroup
|
||||
|
||||
|
||||
def get_default_properties():
|
||||
|
|
@ -98,7 +98,7 @@ class IssueManager(SoftDeletionManager):
|
|||
)
|
||||
.filter(deleted_at__isnull=True)
|
||||
.filter(state__is_triage=False)
|
||||
.exclude(state__group=State.TRIAGE)
|
||||
.exclude(state__group=StateGroup.TRIAGE.value)
|
||||
.exclude(archived_at__isnull=False)
|
||||
.exclude(project__archived_at__isnull=False)
|
||||
.exclude(is_draft=True)
|
||||
|
|
|
|||
|
|
@ -7,51 +7,80 @@ from django.db.models import Q
|
|||
from .project import ProjectBaseModel
|
||||
|
||||
|
||||
class StateGroup(models.TextChoices):
|
||||
BACKLOG = "backlog", "Backlog"
|
||||
UNSTARTED = "unstarted", "Unstarted"
|
||||
STARTED = "started", "Started"
|
||||
COMPLETED = "completed", "Completed"
|
||||
CANCELLED = "cancelled", "Cancelled"
|
||||
TRIAGE = "triage", "Triage"
|
||||
|
||||
|
||||
# Default states
|
||||
DEFAULT_STATES = [
|
||||
{
|
||||
"name": "Backlog",
|
||||
"color": "#60646C",
|
||||
"sequence": 15000,
|
||||
"group": StateGroup.BACKLOG.value,
|
||||
"default": True,
|
||||
},
|
||||
{
|
||||
"name": "Todo",
|
||||
"color": "#60646C",
|
||||
"sequence": 25000,
|
||||
"group": StateGroup.UNSTARTED.value,
|
||||
},
|
||||
{
|
||||
"name": "In Progress",
|
||||
"color": "#F59E0B",
|
||||
"sequence": 35000,
|
||||
"group": StateGroup.STARTED.value,
|
||||
},
|
||||
{
|
||||
"name": "Done",
|
||||
"color": "#46A758",
|
||||
"sequence": 45000,
|
||||
"group": StateGroup.COMPLETED.value,
|
||||
},
|
||||
{
|
||||
"name": "Cancelled",
|
||||
"color": "#9AA4BC",
|
||||
"sequence": 55000,
|
||||
"group": StateGroup.CANCELLED.value,
|
||||
},
|
||||
{
|
||||
"name": "Triage",
|
||||
"color": "#4E5355",
|
||||
"sequence": 65000,
|
||||
"group": StateGroup.TRIAGE.value,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
class StateManager(models.Manager):
|
||||
"""Default manager - excludes triage states"""
|
||||
|
||||
def get_queryset(self):
|
||||
return super().get_queryset().exclude(group=State.TRIAGE)
|
||||
return super().get_queryset().exclude(group=StateGroup.TRIAGE.value)
|
||||
|
||||
|
||||
class TriageStateManager(models.Manager):
|
||||
"""Manager for triage states only"""
|
||||
|
||||
def get_queryset(self):
|
||||
return super().get_queryset().filter(group=State.TRIAGE)
|
||||
return super().get_queryset().filter(group=StateGroup.TRIAGE.value)
|
||||
|
||||
|
||||
class State(ProjectBaseModel):
|
||||
BACKLOG = "backlog"
|
||||
UNSTARTED = "unstarted"
|
||||
STARTED = "started"
|
||||
COMPLETED = "completed"
|
||||
CANCELLED = "cancelled"
|
||||
TRIAGE = "triage"
|
||||
|
||||
GROUP_CHOICES = (
|
||||
(BACKLOG, "Backlog"),
|
||||
(UNSTARTED, "Unstarted"),
|
||||
(STARTED, "Started"),
|
||||
(COMPLETED, "Completed"),
|
||||
(CANCELLED, "Cancelled"),
|
||||
(TRIAGE, "Triage"),
|
||||
)
|
||||
name = models.CharField(max_length=255, verbose_name="State Name")
|
||||
description = models.TextField(verbose_name="State Description", blank=True)
|
||||
color = models.CharField(max_length=255, verbose_name="State Color")
|
||||
slug = models.SlugField(max_length=100, blank=True)
|
||||
sequence = models.FloatField(default=65535)
|
||||
group = models.CharField(
|
||||
choices=(
|
||||
("backlog", "Backlog"),
|
||||
("unstarted", "Unstarted"),
|
||||
("started", "Started"),
|
||||
("completed", "Completed"),
|
||||
("cancelled", "Cancelled"),
|
||||
("triage", "Triage"),
|
||||
),
|
||||
default="backlog",
|
||||
choices=StateGroup.choices,
|
||||
default=StateGroup.BACKLOG,
|
||||
max_length=20,
|
||||
)
|
||||
is_triage = models.BooleanField(default=False)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ from rest_framework.response import Response
|
|||
|
||||
# Module imports
|
||||
from .base import BaseViewSet
|
||||
from plane.db.models import IntakeIssue, Issue, IssueLink, FileAsset, DeployBoard, State
|
||||
from plane.db.models import IntakeIssue, Issue, IssueLink, FileAsset, DeployBoard, State, StateGroup
|
||||
from plane.app.serializers import (
|
||||
IssueSerializer,
|
||||
IntakeIssueSerializer,
|
||||
|
|
@ -128,8 +128,8 @@ class IntakeIssuePublicViewSet(BaseViewSet):
|
|||
|
||||
if not triage_state:
|
||||
triage_state = State.objects.create(
|
||||
name="Intake Triage",
|
||||
group=State.TRIAGE,
|
||||
name="Triage",
|
||||
group=StateGroup.TRIAGE.value,
|
||||
project_id=project_deploy_board.project_id,
|
||||
workspace_id=project_deploy_board.workspace_id,
|
||||
color="#4E5355",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue