diff --git a/apiserver/plane/api/serializers/issue.py b/apiserver/plane/api/serializers/issue.py index 113b54d0e..57539f24c 100644 --- a/apiserver/plane/api/serializers/issue.py +++ b/apiserver/plane/api/serializers/issue.py @@ -293,12 +293,12 @@ class IssueLabelSerializer(BaseSerializer): class IssueRelationSerializer(BaseSerializer): - related_issue_detail = IssueProjectLiteSerializer(read_only=True, source="related_issue") + issue_detail = IssueProjectLiteSerializer(read_only=True, source="related_issue") class Meta: model = IssueRelation fields = [ - "related_issue_detail", + "issue_detail", "relation_type", "related_issue", "issue", diff --git a/apiserver/plane/api/views/issue.py b/apiserver/plane/api/views/issue.py index 4ba30fcdd..6ec48babf 100644 --- a/apiserver/plane/api/views/issue.py +++ b/apiserver/plane/api/views/issue.py @@ -54,6 +54,7 @@ from plane.api.serializers import ( CommentReactionSerializer, IssueVoteSerializer, IssueRelationSerializer, + RelatedIssueSerializer, IssuePublicSerializer, ) from plane.api.permissions import ( @@ -2112,9 +2113,10 @@ class IssueRelationViewSet(BaseViewSet): def create(self, request, slug, project_id, issue_id): try: related_list = request.data.get("related_list", []) + relation = request.data.get("relation", None) project = Project.objects.get(pk=project_id) - issueRelation = IssueRelation.objects.bulk_create( + issue_relation = IssueRelation.objects.bulk_create( [ IssueRelation( issue_id=related_issue["issue"], @@ -2140,11 +2142,17 @@ class IssueRelationViewSet(BaseViewSet): current_instance=None, epoch = int(timezone.now().timestamp()) ) - - return Response( - IssueRelationSerializer(issueRelation, many=True).data, - status=status.HTTP_201_CREATED, - ) + + if relation == "blocking": + return Response( + RelatedIssueSerializer(issue_relation, many=True).data, + status=status.HTTP_201_CREATED, + ) + else: + return Response( + IssueRelationSerializer(issue_relation, many=True).data, + status=status.HTTP_201_CREATED, + ) except IntegrityError as e: if "already exists" in str(e): return Response( diff --git a/apiserver/plane/bgtasks/issue_activites_task.py b/apiserver/plane/bgtasks/issue_activites_task.py index d01bd32ef..d7ff69637 100644 --- a/apiserver/plane/bgtasks/issue_activites_task.py +++ b/apiserver/plane/bgtasks/issue_activites_task.py @@ -1100,6 +1100,25 @@ def create_issue_relation_activity( ) if current_instance is None and requested_data.get("related_list") is not None: for issue_relation in requested_data.get("related_list"): + if issue_relation.get("relation_type") == "blocked_by": + relation_type = "blocking" + else: + relation_type = issue_relation.get("relation_type") + issue = Issue.objects.get(pk=issue_relation.get("issue")) + issue_activities.append( + IssueActivity( + issue_id=issue_relation.get("related_issue"), + actor=actor, + verb="created", + old_value="", + new_value=f"{project.identifier}-{issue.sequence_id}", + field=relation_type, + project=project, + workspace=project.workspace, + comment=f'added {relation_type} relation', + old_identifier=issue_relation.get("issue"), + ) + ) issue = Issue.objects.get(pk=issue_relation.get("related_issue")) issue_activities.append( IssueActivity( @@ -1112,7 +1131,7 @@ def create_issue_relation_activity( project=project, workspace=project.workspace, comment=f'added {issue_relation.get("relation_type")} relation', - old_identifier=issue_relation.get("issue"), + old_identifier=issue_relation.get("related_issue"), epoch=epoch, ) ) @@ -1126,22 +1145,42 @@ def delete_issue_relation_activity( json.loads(current_instance) if current_instance is not None else None ) if current_instance is not None and requested_data.get("related_list") is None: - issue = Issue.objects.get(pk=current_instance.get("issue")) - issue_activities.append( - IssueActivity( - issue_id=current_instance.get("issue"), - actor=actor, - verb="deleted", - old_value=f"{project.identifier}-{issue.sequence_id}", - new_value="", - field=f'{current_instance.get("relation_type")}', - project=project, - workspace=project.workspace, - comment=f'deleted the {current_instance.get("relation_type")} relation', - old_identifier=current_instance.get("issue"), - epoch=epoch, + if current_instance.get("relation_type") == "blocked_by": + relation_type = "blocking" + else: + relation_type = current_instance.get("relation_type") + issue = Issue.objects.get(pk=current_instance.get("issue")) + issue_activities.append( + IssueActivity( + issue_id=current_instance.get("related_issue"), + actor=actor, + verb="deleted", + old_value=f"{project.identifier}-{issue.sequence_id}", + new_value="", + field=relation_type, + project=project, + workspace=project.workspace, + comment=f'deleted {relation_type} relation', + old_identifier=current_instance.get("issue"), + epoch=epoch, + ) + ) + issue = Issue.objects.get(pk=current_instance.get("related_issue")) + issue_activities.append( + IssueActivity( + issue_id=current_instance.get("issue"), + actor=actor, + verb="deleted", + old_value=f"{project.identifier}-{issue.sequence_id}", + new_value="", + field=f'{current_instance.get("relation_type")}', + project=project, + workspace=project.workspace, + comment=f'deleted {current_instance.get("relation_type")} relation', + old_identifier=current_instance.get("related_issue"), + epoch=epoch, + ) ) - ) def create_draft_issue_activity( diff --git a/apiserver/plane/db/migrations/0045_auto_20230915_0655.py b/apiserver/plane/db/migrations/0045_auto_20230915_0655.py new file mode 100644 index 000000000..7bd907e29 --- /dev/null +++ b/apiserver/plane/db/migrations/0045_auto_20230915_0655.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.3 on 2023-09-15 06:55 + +from django.db import migrations + +def update_issue_activity(apps, schema_editor): + IssueActivityModel = apps.get_model("db", "IssueActivity") + updated_issue_activity = [] + for obj in IssueActivityModel.objects.all(): + if obj.field == "blocks": + obj.field = "blocked_by" + updated_issue_activity.append(obj) + IssueActivityModel.objects.bulk_update(updated_issue_activity, ["field"], batch_size=100) + + +class Migration(migrations.Migration): + + dependencies = [ + ('db', '0044_auto_20230913_0709'), + ] + + operations = [ + migrations.RunPython(update_issue_activity), + ] diff --git a/web/components/automation/auto-close-automation.tsx b/web/components/automation/auto-close-automation.tsx index 8235c8063..868d64557 100644 --- a/web/components/automation/auto-close-automation.tsx +++ b/web/components/automation/auto-close-automation.tsx @@ -103,8 +103,8 @@ export const AutoCloseAutomation: React.FC = ({ projectDetails, handleCha {projectDetails?.close_in !== 0 && (
-
-
+
+
Auto-close issues that are inactive for
@@ -138,7 +138,7 @@ export const AutoCloseAutomation: React.FC = ({ projectDetails, handleCha
-
+
Auto-close Status
{ const [isCreateUpdatePageModalOpen, setIsCreateUpdatePageModalOpen] = useState(false); const router = useRouter(); - const { workspaceSlug, projectId, issueId, inboxId } = router.query; + const { workspaceSlug, projectId, issueId, inboxId, cycleId, moduleId } = router.query; const { user } = useUser(); @@ -183,6 +183,13 @@ export const CommandPalette: React.FC = observer(() => { isOpen={isIssueModalOpen} handleClose={() => setIsIssueModalOpen(false)} fieldsToShow={inboxId ? ["name", "description", "priority"] : ["all"]} + prePopulateData={ + cycleId + ? { cycle: cycleId.toString() } + : moduleId + ? { module: moduleId.toString() } + : undefined + } /> ); }, - icon: