Skip to content
Merged
8 changes: 7 additions & 1 deletion apiserver/plane/app/views/issue/comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,13 @@ def partial_update(self, request, slug, project_id, issue_id, pk):
issue_comment, data=request.data, partial=True
)
if serializer.is_valid():
serializer.save()
if (
"comment_html" in request.data
and request.data["comment_html"] != issue_comment.comment_html
):
serializer.save(edited_at=timezone.now())
else:
serializer.save()
issue_activity.delay(
type="comment.activity.updated",
requested_data=requested_data,
Expand Down
4 changes: 3 additions & 1 deletion packages/i18n/src/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,9 @@
"re_generate_key": "Re-generate key",
"export": "Export",
"member": "{count, plural, one{# member} other{# members}}",

"edited": "Modifié",
"bot": "Bot",

"project_view": {
"sort_by": {
"created_at": "Created at",
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/locales/es/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,8 @@
"re_generate_key": "Regenerar clave",
"export": "Exportar",
"member": "{count, plural, one{# miembro} other{# miembros}}",
"edited": "Modificado",
"bot": "Bot",

"project_view": {
"sort_by": {
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/locales/fr/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,8 @@
"re_generate_key": "Régénérer la clé",
"export": "Exporter",
"member": "{count, plural, one{# membre} other{# membres}}",
"edited": "Modifié",
"bot": "Bot",

"project_view": {
"sort_by": {
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/locales/it/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,8 @@
"re_generate_key": "Rigenera chiave",
"export": "Esporta",
"member": "{count, plural, one {# membro} other {# membri}}",
"edited": "Modificato",
"bot": "Bot",

"project_view": {
"sort_by": {
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/locales/ja/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,8 @@
"re_generate_key": "キーを再生成",
"export": "エクスポート",
"member": "{count, plural, other{# メンバー}}",
"edited": "編集済み",
"bot": "ボット",

"project_view": {
"sort_by": {
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/locales/ko/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,8 @@
"re_generate_key": "키 다시 생성",
"export": "내보내기",
"member": "{count, plural, one{# 멤버} other{# 멤버}}",
"edited": "수정됨",
"bot": "봇",

"project_view": {
"sort_by": {
Expand Down
3 changes: 3 additions & 0 deletions packages/i18n/src/locales/pl/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,9 @@
"re_generate_key": "Wygeneruj klucz ponownie",
"export": "Eksportuj",
"member": "{count, plural, one{# członek} few{# członkowie} other{# członków}}",
"edited": "Edytowano",
"bot": "Bot",

"project_view": {
"sort_by": {
"created_at": "Utworzono dnia",
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/locales/ru/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,8 @@
"re_generate_key": "Перегенерировать ключ",
"export": "Экспорт",
"member": "{count, plural, one{# участник} few{# участника} other{# участников}}",
"edited": "Редактировано",
"bot": "Бот",

"project_view": {
"sort_by": {
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/locales/sk/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,8 @@
"re_generate_key": "Znova generovať kľúč",
"export": "Exportovať",
"member": "{count, plural, one{# člen} few{# členovia} other{# členov}}",
"edited": "Upravené",
"bot": "Bot",

"project_view": {
"sort_by": {
Expand Down
3 changes: 3 additions & 0 deletions packages/i18n/src/locales/ua/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,9 @@
"re_generate_key": "Повторно згенерувати ключ",
"export": "Експортувати",
"member": "{count, plural, one{# учасник} few{# учасники} other{# учасників}}",
"edited": "Редагувано",
"bot": "Бот",

"project_view": {
"sort_by": {
"created_at": "Створено",
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/locales/zh-CN/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,8 @@
"re_generate_key": "重新生成密钥",
"export": "导出",
"member": "{count, plural, other{# 成员}}",
"edited": "已编辑",
"bot": "机器人",

"project_view": {
"sort_by": {
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n/src/locales/zh-TW/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,8 @@
"re_generate_key": "重新產生金鑰",
"export": "匯出",
"member": "{count, plural, one{# 位成員} other{# 位成員}}",
"edited": "已編輯",
"bot": "機器人",

"project_view": {
"sort_by": {
Expand Down
26 changes: 26 additions & 0 deletions packages/types/src/issues/activity/issue_comment.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@ import {
TIssueActivityUserDetail,
} from "./base";
import { EIssueCommentAccessSpecifier } from "../../enums";
import { TFileSignedURLResponse } from "../../file";
import { IUserLite } from "../../users";

export type TCommentReaction = {
id: string;
reaction: string;
actor: string;
actor_detail: IUserLite;
};
export type TIssueComment = {
id: string;
workspace: string;
Expand All @@ -17,6 +25,7 @@ export type TIssueComment = {
actor: string;
actor_detail: TIssueActivityUserDetail;
created_at: string;
edited_at?: string | undefined;
updated_at: string;
created_by: string | undefined;
updated_by: string | undefined;
Expand All @@ -30,6 +39,23 @@ export type TIssueComment = {
access: EIssueCommentAccessSpecifier;
};

export type TCommentsOperations = {
createComment: (data: Partial<TIssueComment>) => Promise<void>;
updateComment: (commentId: string, data: Partial<TIssueComment>) => Promise<void>;
removeComment: (commentId: string) => Promise<void>;
uploadCommentAsset: (blockId: string, file: File, commentId?: string) => Promise<TFileSignedURLResponse>;
addCommentReaction: (commentId: string, reactionEmoji: string) => Promise<void>;
deleteCommentReaction: (commentId: string, reactionEmoji: string, userReactions: TCommentReaction[]) => Promise<void>;
react: (commentId: string, reactionEmoji: string, userReactions: string[]) => Promise<void>;
reactionIds: (commentId: string) =>
| {
[reaction: string]: string[];
}
| undefined;
userReactions: (commentId: string) => string[] | undefined;
getReactionUsers: (reaction: string, reactionIds: Record<string, string[]>) => string;
};

export type TIssueCommentMap = {
[issue_id: string]: TIssueComment;
};
Expand Down
76 changes: 76 additions & 0 deletions web/ce/components/comments/comment-block.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { FC, ReactNode, useRef } from "react";
import { observer } from "mobx-react";
// plane imports
import { useTranslation } from "@plane/i18n";
import { TIssueComment } from "@plane/types";
import { Avatar, Tooltip } from "@plane/ui";
import { calculateTimeAgo, cn, getFileURL, renderFormattedDate } from "@plane/utils";
// hooks
import { renderFormattedTime } from "@/helpers/date-time.helper";
import { useMember } from "@/hooks/store";

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;
const commentBlockRef = useRef<HTMLDivElement>(null);
// store hooks
const { getUserDetails } = useMember();
const { t } = useTranslation();
const userDetails = getUserDetails(comment?.actor);

if (!comment || !userDetails) return <></>;
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={userDetails?.display_name}
src={getFileURL(userDetails?.avatar_url)}
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="text-xs font-medium">
{comment?.actor_detail?.is_bot
? comment?.actor_detail?.first_name + ` ${t("bot")}`
: comment?.actor_detail?.display_name || userDetails.display_name}
</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>
);
});
1 change: 1 addition & 0 deletions web/ce/components/comments/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./comment-block";
Loading