[WEB-987] fix: inbox issue activity (#4208)

* chore: inbox issue activity

* chore: dummy data script

* chore: inbox issue activity implementation

---------

Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia@plane.so>
This commit is contained in:
Bavisetti Narayan 2024-04-17 19:43:22 +05:30 committed by GitHub
parent f0cb48006f
commit bf9049a7a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 127 additions and 2 deletions

View File

@ -272,6 +272,9 @@ class InboxIssueAPIEndpoint(BaseAPIView):
serializer = InboxIssueSerializer(
inbox_issue, data=request.data, partial=True
)
current_instance = json.dumps(
InboxIssueSerializer(inbox_issue).data, cls=DjangoJSONEncoder
)
if serializer.is_valid():
serializer.save()
@ -311,6 +314,21 @@ class InboxIssueAPIEndpoint(BaseAPIView):
issue.state = state
issue.save()
# create a activity for status change
issue_activity.delay(
type="inbox.activity.created",
requested_data=json.dumps(
request.data, cls=DjangoJSONEncoder
),
actor_id=str(request.user.id),
issue_id=str(issue_id),
project_id=str(project_id),
current_instance=current_instance,
epoch=int(timezone.now().timestamp()),
notification=False,
origin=request.META.get("HTTP_ORIGIN"),
)
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(
serializer.errors, status=status.HTTP_400_BAD_REQUEST

View File

@ -391,7 +391,9 @@ class InboxIssueViewSet(BaseViewSet):
serializer = InboxIssueSerializer(
inbox_issue, data=request.data, partial=True
)
current_instance = json.dumps(
InboxIssueSerializer(inbox_issue).data, cls=DjangoJSONEncoder
)
if serializer.is_valid():
serializer.save()
# Update the issue state if the issue is rejected or marked as duplicate
@ -429,6 +431,21 @@ class InboxIssueViewSet(BaseViewSet):
if state is not None:
issue.state = state
issue.save()
# create a activity for status change
issue_activity.delay(
type="inbox.activity.created",
requested_data=json.dumps(
request.data, cls=DjangoJSONEncoder
),
actor_id=str(request.user.id),
issue_id=str(issue_id),
project_id=str(project_id),
current_instance=current_instance,
epoch=int(timezone.now().timestamp()),
notification=False,
origin=request.META.get("HTTP_ORIGIN"),
)
inbox_issue = (
InboxIssue.objects.filter(
inbox_id=inbox_id.id,

View File

@ -1,4 +1,5 @@
# Python imports
import uuid
import random
from datetime import datetime, timedelta
@ -36,9 +37,11 @@ from plane.db.models import (
def create_project(workspace, user_id):
fake = Faker()
name = fake.name()
unique_id = str(uuid.uuid4())[:5]
project = Project.objects.create(
workspace=workspace,
name=name,
name=f"{name}_{unique_id}",
identifier=name[
: random.randint(2, 12 if len(name) - 1 >= 12 else len(name) - 1)
].upper(),

View File

@ -1553,6 +1553,46 @@ def delete_draft_issue_activity(
)
def create_inbox_activity(
requested_data,
current_instance,
issue_id,
project_id,
workspace_id,
actor_id,
issue_activities,
epoch,
):
requested_data = (
json.loads(requested_data) if requested_data is not None else None
)
current_instance = (
json.loads(current_instance) if current_instance is not None else None
)
status_dict = {
-2: "Pending",
-1: "Rejected",
0: "Snoozed",
1: "Accepted",
2: "Duplicate",
}
if requested_data.get("status") is not None:
issue_activities.append(
IssueActivity(
issue_id=issue_id,
project_id=project_id,
workspace_id=workspace_id,
comment="updated the inbox status",
field="inbox",
verb=requested_data.get("status"),
actor_id=actor_id,
epoch=epoch,
old_value=status_dict.get(current_instance.get("status")),
new_value=status_dict.get(requested_data.get("status")),
)
)
# Receive message from room group
@shared_task
def issue_activity(
@ -1613,6 +1653,7 @@ def issue_activity(
"issue_draft.activity.created": create_draft_issue_activity,
"issue_draft.activity.updated": update_draft_issue_activity,
"issue_draft.activity.deleted": delete_draft_issue_activity,
"inbox.activity.created": create_inbox_activity,
}
func = ACTIVITY_MAPPER.get(type)

View File

@ -0,0 +1,42 @@
import { FC } from "react";
import { observer } from "mobx-react";
// hooks
import { Inbox } from "lucide-react";
import { useIssueDetail } from "@/hooks/store";
// components
import { IssueActivityBlockComponent } from "./";
// icons
type TIssueInboxActivity = { activityId: string; ends: "top" | "bottom" | undefined };
export const IssueInboxActivity: FC<TIssueInboxActivity> = observer((props) => {
const { activityId, ends } = props;
// hooks
const {
activity: { getActivityById },
} = useIssueDetail();
const activity = getActivityById(activityId);
const getInboxActivityMessage = () => {
switch (activity?.verb) {
case "-1":
return "declined this issue from inbox.";
case "0":
return "snoozed this issue.";
case "1":
return "accepted this issue from inbox.";
case "2":
return "declined this issue from inbox by marking a duplicate issue.";
default:
return "updated inbox issue status.";
}
};
if (!activity) return <></>;
return (
<IssueActivityBlockComponent icon={<Inbox className="h-4 w-4 flex-shrink-0" />} activityId={activityId} ends={ends}>
<>{getInboxActivityMessage()}</>
</IssueActivityBlockComponent>
);
});

View File

@ -15,6 +15,7 @@ export * from "./label";
export * from "./link";
export * from "./attachment";
export * from "./archived-at";
export * from "./inbox";
// helpers
export * from "./helpers/activity-block";

View File

@ -21,6 +21,7 @@ import {
IssueLinkActivity,
IssueAttachmentActivity,
IssueArchivedAtActivity,
IssueInboxActivity,
} from "./actions";
type TIssueActivityList = {
@ -74,6 +75,8 @@ export const IssueActivityList: FC<TIssueActivityList> = observer((props) => {
return <IssueAttachmentActivity {...componentDefaultProps} showIssue={false} />;
case "archived_at":
return <IssueArchivedAtActivity {...componentDefaultProps} />;
case "inbox":
return <IssueInboxActivity {...componentDefaultProps} />;
default:
return <></>;
}