mirror of
https://github.com/makeplane/plane.git
synced 2025-12-21 14:19:38 +01:00
* [WEB-5134] refactor: update `web` ESLint configuration and refactor imports to use type imports - Enhanced ESLint configuration by adding new rules for import consistency and type imports. - Refactored multiple files to replace regular imports with type imports for better clarity and performance. - Ensured consistent use of type imports across the application to align with TypeScript best practices. * refactor: standardize type imports across components - Updated multiple files to replace regular imports with type imports for improved clarity and consistency. - Ensured adherence to TypeScript best practices in the rich filters and issue layouts components.
83 lines
3.0 KiB
TypeScript
83 lines
3.0 KiB
TypeScript
import type { FC, ReactNode } from "react";
|
|
import { useRef } from "react";
|
|
import { observer } from "mobx-react";
|
|
// plane imports
|
|
import { useTranslation } from "@plane/i18n";
|
|
import type { TIssueComment } from "@plane/types";
|
|
import { EIssueCommentAccessSpecifier } from "@plane/types";
|
|
import { Avatar, Tooltip } from "@plane/ui";
|
|
import { calculateTimeAgo, cn, getFileURL, renderFormattedDate, renderFormattedTime } from "@plane/utils";
|
|
// hooks
|
|
import { useMember } from "@/hooks/store/use-member";
|
|
|
|
type TCommentBlock = {
|
|
comment: TIssueComment;
|
|
ends: "top" | "bottom" | undefined;
|
|
quickActions: ReactNode;
|
|
children: ReactNode;
|
|
};
|
|
|
|
export const CommentBlock: FC<TCommentBlock> = observer((props) => {
|
|
const { comment, ends, quickActions, children } = props;
|
|
// refs
|
|
const commentBlockRef = useRef<HTMLDivElement>(null);
|
|
// store hooks
|
|
const { getUserDetails } = useMember();
|
|
// derived values
|
|
const userDetails = getUserDetails(comment?.actor);
|
|
// translation
|
|
const { t } = useTranslation();
|
|
|
|
const displayName = comment?.actor_detail?.is_bot
|
|
? comment?.actor_detail?.first_name + ` ${t("bot")}`
|
|
: (userDetails?.display_name ?? comment?.actor_detail?.display_name);
|
|
|
|
const avatarUrl = userDetails?.avatar_url ?? comment?.actor_detail?.avatar_url;
|
|
|
|
if (!comment) return null;
|
|
|
|
return (
|
|
<div
|
|
className={`relative flex gap-3 ${ends === "top" ? `pb-2` : ends === "bottom" ? `pt-2` : `py-2`}`}
|
|
ref={commentBlockRef}
|
|
>
|
|
<div
|
|
className="absolute left-[13px] top-0 bottom-0 w-0.5 transition-border duration-1000 bg-custom-background-80"
|
|
aria-hidden
|
|
/>
|
|
<div
|
|
className={cn(
|
|
"flex-shrink-0 relative w-7 h-6 rounded-full transition-border duration-1000 flex justify-center items-center z-[3] uppercase font-medium"
|
|
)}
|
|
>
|
|
<Avatar size="base" name={displayName} src={getFileURL(avatarUrl)} className="flex-shrink-0" />
|
|
</div>
|
|
<div className="flex flex-col gap-3 truncate flex-grow">
|
|
<div className="flex w-full gap-2">
|
|
<div className="flex-1 flex flex-wrap items-center gap-1">
|
|
<div className="flex items-center gap-1">
|
|
<span className="text-xs font-medium">
|
|
{`${displayName}${comment.access === EIssueCommentAccessSpecifier.EXTERNAL ? " (External User)" : ""}`}
|
|
</span>
|
|
</div>
|
|
<div className="text-xs text-custom-text-300">
|
|
commented{" "}
|
|
<Tooltip
|
|
tooltipContent={`${renderFormattedDate(comment.created_at)} at ${renderFormattedTime(comment.created_at)}`}
|
|
position="bottom"
|
|
>
|
|
<span className="text-custom-text-350">
|
|
{calculateTimeAgo(comment.updated_at)}
|
|
{comment.edited_at && ` (${t("edited")})`}
|
|
</span>
|
|
</Tooltip>
|
|
</div>
|
|
</div>
|
|
<div className="flex-shrink-0 ">{quickActions}</div>
|
|
</div>
|
|
<div className="text-base mb-2">{children}</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
});
|