forked from github/plane
[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:
parent
f0cb48006f
commit
bf9049a7a2
@ -272,6 +272,9 @@ class InboxIssueAPIEndpoint(BaseAPIView):
|
|||||||
serializer = InboxIssueSerializer(
|
serializer = InboxIssueSerializer(
|
||||||
inbox_issue, data=request.data, partial=True
|
inbox_issue, data=request.data, partial=True
|
||||||
)
|
)
|
||||||
|
current_instance = json.dumps(
|
||||||
|
InboxIssueSerializer(inbox_issue).data, cls=DjangoJSONEncoder
|
||||||
|
)
|
||||||
|
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
serializer.save()
|
serializer.save()
|
||||||
@ -311,6 +314,21 @@ class InboxIssueAPIEndpoint(BaseAPIView):
|
|||||||
issue.state = state
|
issue.state = state
|
||||||
issue.save()
|
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.data, status=status.HTTP_200_OK)
|
||||||
return Response(
|
return Response(
|
||||||
serializer.errors, status=status.HTTP_400_BAD_REQUEST
|
serializer.errors, status=status.HTTP_400_BAD_REQUEST
|
||||||
|
@ -391,7 +391,9 @@ class InboxIssueViewSet(BaseViewSet):
|
|||||||
serializer = InboxIssueSerializer(
|
serializer = InboxIssueSerializer(
|
||||||
inbox_issue, data=request.data, partial=True
|
inbox_issue, data=request.data, partial=True
|
||||||
)
|
)
|
||||||
|
current_instance = json.dumps(
|
||||||
|
InboxIssueSerializer(inbox_issue).data, cls=DjangoJSONEncoder
|
||||||
|
)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
serializer.save()
|
serializer.save()
|
||||||
# Update the issue state if the issue is rejected or marked as duplicate
|
# 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:
|
if state is not None:
|
||||||
issue.state = state
|
issue.state = state
|
||||||
issue.save()
|
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 = (
|
inbox_issue = (
|
||||||
InboxIssue.objects.filter(
|
InboxIssue.objects.filter(
|
||||||
inbox_id=inbox_id.id,
|
inbox_id=inbox_id.id,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
|
import uuid
|
||||||
import random
|
import random
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
@ -36,9 +37,11 @@ from plane.db.models import (
|
|||||||
def create_project(workspace, user_id):
|
def create_project(workspace, user_id):
|
||||||
fake = Faker()
|
fake = Faker()
|
||||||
name = fake.name()
|
name = fake.name()
|
||||||
|
unique_id = str(uuid.uuid4())[:5]
|
||||||
|
|
||||||
project = Project.objects.create(
|
project = Project.objects.create(
|
||||||
workspace=workspace,
|
workspace=workspace,
|
||||||
name=name,
|
name=f"{name}_{unique_id}",
|
||||||
identifier=name[
|
identifier=name[
|
||||||
: random.randint(2, 12 if len(name) - 1 >= 12 else len(name) - 1)
|
: random.randint(2, 12 if len(name) - 1 >= 12 else len(name) - 1)
|
||||||
].upper(),
|
].upper(),
|
||||||
|
@ -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
|
# Receive message from room group
|
||||||
@shared_task
|
@shared_task
|
||||||
def issue_activity(
|
def issue_activity(
|
||||||
@ -1613,6 +1653,7 @@ def issue_activity(
|
|||||||
"issue_draft.activity.created": create_draft_issue_activity,
|
"issue_draft.activity.created": create_draft_issue_activity,
|
||||||
"issue_draft.activity.updated": update_draft_issue_activity,
|
"issue_draft.activity.updated": update_draft_issue_activity,
|
||||||
"issue_draft.activity.deleted": delete_draft_issue_activity,
|
"issue_draft.activity.deleted": delete_draft_issue_activity,
|
||||||
|
"inbox.activity.created": create_inbox_activity,
|
||||||
}
|
}
|
||||||
|
|
||||||
func = ACTIVITY_MAPPER.get(type)
|
func = ACTIVITY_MAPPER.get(type)
|
||||||
|
@ -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>
|
||||||
|
);
|
||||||
|
});
|
@ -15,6 +15,7 @@ export * from "./label";
|
|||||||
export * from "./link";
|
export * from "./link";
|
||||||
export * from "./attachment";
|
export * from "./attachment";
|
||||||
export * from "./archived-at";
|
export * from "./archived-at";
|
||||||
|
export * from "./inbox";
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
export * from "./helpers/activity-block";
|
export * from "./helpers/activity-block";
|
||||||
|
@ -21,6 +21,7 @@ import {
|
|||||||
IssueLinkActivity,
|
IssueLinkActivity,
|
||||||
IssueAttachmentActivity,
|
IssueAttachmentActivity,
|
||||||
IssueArchivedAtActivity,
|
IssueArchivedAtActivity,
|
||||||
|
IssueInboxActivity,
|
||||||
} from "./actions";
|
} from "./actions";
|
||||||
|
|
||||||
type TIssueActivityList = {
|
type TIssueActivityList = {
|
||||||
@ -74,6 +75,8 @@ export const IssueActivityList: FC<TIssueActivityList> = observer((props) => {
|
|||||||
return <IssueAttachmentActivity {...componentDefaultProps} showIssue={false} />;
|
return <IssueAttachmentActivity {...componentDefaultProps} showIssue={false} />;
|
||||||
case "archived_at":
|
case "archived_at":
|
||||||
return <IssueArchivedAtActivity {...componentDefaultProps} />;
|
return <IssueArchivedAtActivity {...componentDefaultProps} />;
|
||||||
|
case "inbox":
|
||||||
|
return <IssueInboxActivity {...componentDefaultProps} />;
|
||||||
default:
|
default:
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user