import React from "react"; import { useRouter } from "next/router"; import useSWR from "swr"; // icons import { CalendarDaysIcon, ChartBarIcon, ChatBubbleBottomCenterTextIcon, LinkIcon, PaperClipIcon, PlayIcon, RectangleGroupIcon, Squares2X2Icon, UserIcon, } from "@heroicons/react/24/outline"; import { BlockedIcon, BlockerIcon, CyclesIcon, TagIcon, UserGroupIcon } from "components/icons"; // services import issuesService from "services/issues.service"; // components import { CommentCard } from "components/issues/comment"; // ui import { Loader } from "components/ui"; // helpers import { renderShortNumericDateFormat, timeAgo } from "helpers/date-time.helper"; import { addSpaceIfCamelCase } from "helpers/string.helper"; // types import { ICurrentUserResponse, IIssueComment, IIssueLabels } from "types"; import { PROJECT_ISSUES_ACTIVITY, PROJECT_ISSUE_LABELS } from "constants/fetch-keys"; import useEstimateOption from "hooks/use-estimate-option"; const activityDetails: { [key: string]: { message?: string; icon: JSX.Element; }; } = { assignee: { message: "removed the assignee", icon: , }, assignees: { message: "added a new assignee", icon: , }, blocks: { message: "marked this issue being blocked by", icon: , }, blocking: { message: "marked this issue is blocking", icon: , }, cycles: { message: "set the cycle to", icon: , }, estimate_point: { message: "set the estimate point to", icon: , }, labels: { icon: , }, modules: { message: "set the module to", icon: , }, state: { message: "set the state to", icon: , }, priority: { message: "set the priority to", icon: , }, name: { message: "set the name to", icon: ( ), }, description: { message: "updated the description.", icon: ( ), }, target_date: { message: "set the due date to", icon: , }, parent: { message: "set the parent to", icon: , }, estimate: { message: "updated the estimate", icon: , }, link: { message: "updated the link", icon: , }, attachment: { message: "updated the attachment", icon: , }, }; type Props = { user: ICurrentUserResponse | undefined; }; export const IssueActivitySection: React.FC = ({ user }) => { const router = useRouter(); const { workspaceSlug, projectId, issueId } = router.query; const { isEstimateActive, estimatePoints } = useEstimateOption(); const { data: issueActivities, mutate: mutateIssueActivities } = useSWR( workspaceSlug && projectId && issueId ? PROJECT_ISSUES_ACTIVITY(issueId as string) : null, workspaceSlug && projectId && issueId ? () => issuesService.getIssueActivities( workspaceSlug as string, projectId as string, issueId as string ) : null ); const { data: issueLabels } = useSWR( projectId ? PROJECT_ISSUE_LABELS(projectId as string) : null, workspaceSlug && projectId ? () => issuesService.getIssueLabels(workspaceSlug as string, projectId as string) : null ); const handleCommentUpdate = async (comment: IIssueComment) => { if (!workspaceSlug || !projectId || !issueId) return; await issuesService .patchIssueComment( workspaceSlug as string, projectId as string, issueId as string, comment.id, comment, user ) .then((res) => { mutateIssueActivities(); }); }; const handleCommentDelete = async (commentId: string) => { if (!workspaceSlug || !projectId || !issueId) return; mutateIssueActivities((prevData) => prevData?.filter((p) => p.id !== commentId), false); await issuesService .deleteIssueComment( workspaceSlug as string, projectId as string, issueId as string, commentId, user ) .then(() => mutateIssueActivities()); }; const getLabelColor = (labelId: string) => { if (!issueLabels) return; const label = issueLabels.find((label) => label.id === labelId); if (typeof label !== "undefined") { return label.color !== "" ? label.color : "#000000"; } return "#000000"; }; if (!issueActivities) { return ( ); } return ( {issueActivities.map((activityItem, activityItemIdx) => { // determines what type of action is performed let action = activityDetails[activityItem.field as keyof typeof activityDetails]?.message; if (activityItem.field === "labels") { action = activityItem.new_value !== "" ? "added a new label" : "removed the label"; } else if (activityItem.field === "blocking") { action = activityItem.new_value !== "" ? "marked this issue is blocking" : "removed the issue from blocking"; } else if (activityItem.field === "blocks") { action = activityItem.new_value !== "" ? "marked this issue being blocked by" : "removed blocker"; } else if (activityItem.field === "target_date") { action = activityItem.new_value && activityItem.new_value !== "" ? "set the due date to" : "removed the due date"; } else if (activityItem.field === "parent") { action = activityItem.new_value && activityItem.new_value !== "" ? "set the parent to" : "removed the parent"; } else if (activityItem.field === "priority") { action = activityItem.new_value && activityItem.new_value !== "" ? "set the priority to" : "removed the priority"; } else if (activityItem.field === "description") { action = "updated the"; } else if (activityItem.field === "attachment") { action = `${activityItem.verb} the`; } else if (activityItem.field === "link") { action = `${activityItem.verb} the`; } else if (activityItem.field === "estimate") { action = "updated the"; } else if (activityItem.field === "cycles") { action = activityItem.new_value && activityItem.new_value !== "" ? "set the cycle to" : "removed the cycle"; } else if (activityItem.field === "modules") { action = activityItem.new_value && activityItem.new_value !== "" ? "set the module to" : "removed the module"; } // for values that are after the action clause let value: any = activityItem.new_value ? activityItem.new_value : activityItem.old_value; if ( activityItem.verb === "created" && activityItem.field !== "cycles" && activityItem.field !== "modules" && activityItem.field !== "attachment" && activityItem.field !== "link" && activityItem.field !== "estimate" ) { value = created this issue.; } else if (activityItem.field === "state") { value = activityItem.new_value ? addSpaceIfCamelCase(activityItem.new_value) : "None"; } else if (activityItem.field === "labels") { let name; let id = "#000000"; if (activityItem.new_value !== "") { name = activityItem.new_value; id = activityItem.new_identifier ? activityItem.new_identifier : id; } else { name = activityItem.old_value; id = activityItem.old_identifier ? activityItem.old_identifier : id; } value = ( {name} ); } else if (activityItem.field === "assignees") { value = activityItem.new_value; } else if (activityItem.field === "target_date") { const date = activityItem.new_value && activityItem.new_value !== "" ? activityItem.new_value : activityItem.old_value; value = renderShortNumericDateFormat(date as string); } else if (activityItem.field === "description") { value = "description"; } else if (activityItem.field === "attachment") { value = "attachment"; } else if (activityItem.field === "cycles") { const cycles = activityItem.new_value && activityItem.new_value !== "" ? activityItem.new_value : activityItem.old_value; value = cycles ? addSpaceIfCamelCase(cycles) : "None"; } else if (activityItem.field === "modules") { const modules = activityItem.new_value && activityItem.new_value !== "" ? activityItem.new_value : activityItem.old_value; value = modules ? addSpaceIfCamelCase(modules) : "None"; } else if (activityItem.field === "link") { value = "link"; } else if (activityItem.field === "estimate_point") { value = activityItem.new_value ? isEstimateActive ? estimatePoints.find((e) => e.key === parseInt(activityItem.new_value ?? "", 10)) ?.value : activityItem.new_value + ` Point${parseInt(activityItem.new_value ?? "", 10) > 1 ? "s" : ""}` : "None"; } if ("field" in activityItem && activityItem.field !== "updated_by") { return ( {issueActivities.length > 1 && activityItemIdx !== issueActivities.length - 1 ? ( ) : null} <> {activityItem.field ? ( activityDetails[activityItem.field as keyof typeof activityDetails] ?.icon ) : activityItem.actor_detail.avatar && activityItem.actor_detail.avatar !== "" ? ( ) : ( {activityItem.actor_detail.first_name.charAt(0)} )} {activityItem.actor_detail.first_name} {activityItem.actor_detail.is_bot ? " Bot" : " " + activityItem.actor_detail.last_name} {action} {value} {timeAgo(activityItem.created_at)} > ); } else if ("comment_json" in activityItem) return ( ); })} ); };