diff --git a/web/libs/editor/src/components/Comments/Comment/CommentForm.tsx b/web/libs/editor/src/components/Comments/Comment/CommentForm.tsx index d2ce06b40a9..f60ada02251 100644 --- a/web/libs/editor/src/components/Comments/Comment/CommentForm.tsx +++ b/web/libs/editor/src/components/Comments/Comment/CommentForm.tsx @@ -12,9 +12,7 @@ import { LinkState } from "./LinkState"; import "./CommentForm.scss"; import { NewTaxonomy as Taxonomy, type TaxonomyPath } from "../../../components/NewTaxonomy/NewTaxonomy"; import { CommentFormButtons } from "./CommentFormButtons"; -import { taxonomyPathsToSelectedItems } from "../../../utils/commentClassification"; - -const TAXONOMY_OPTIONS = { pathSeparator: "/", showFullPath: true }; +import { taxonomyPathsToSelectedItems, COMMENT_TAXONOMY_OPTIONS } from "../../../utils/commentClassification"; export type CommentFormProps = { commentStore: any; @@ -174,7 +172,7 @@ export const CommentForm: FC = observer(({ commentStore, annot selected={selections} items={classificationsItems} onChange={taxonomyOnChange} - options={TAXONOMY_OPTIONS} + options={COMMENT_TAXONOMY_OPTIONS} defaultSearch={false} /> diff --git a/web/libs/editor/src/components/Comments/Comment/CommentItem.scss b/web/libs/editor/src/components/Comments/Comment/CommentItem.scss index c643d8d997b..ec73d36d224 100644 --- a/web/libs/editor/src/components/Comments/Comment/CommentItem.scss +++ b/web/libs/editor/src/components/Comments/Comment/CommentItem.scss @@ -115,6 +115,10 @@ overflow: hidden; } + &__classifications-row > div { + width: 100%; + } + &__linkState { padding: 4px 0 0; margin-left: -5px; diff --git a/web/libs/editor/src/components/Comments/Comment/CommentItem.tsx b/web/libs/editor/src/components/Comments/Comment/CommentItem.tsx index 2a604401284..bcb6bf1e359 100644 --- a/web/libs/editor/src/components/Comments/Comment/CommentItem.tsx +++ b/web/libs/editor/src/components/Comments/Comment/CommentItem.tsx @@ -1,7 +1,7 @@ import { Tooltip } from "antd"; import { observer } from "mobx-react"; import type React from "react"; -import { type FC, useCallback, useContext, useState } from "react"; +import { type FC, useCallback, useContext, useMemo, useState } from "react"; import { IconCheck, IconEllipsis } from "../../../assets/icons"; import { Button } from "../../../common/Button/Button"; @@ -13,6 +13,8 @@ import { Block, Elem } from "../../../utils/bem"; import { humanDateDiff, userDisplayName } from "../../../utils/utilities"; import { CommentFormBase } from "../CommentFormBase"; import { CommentsContext } from "./CommentsList"; +import { NewTaxonomy as Taxonomy, type TaxonomyPath } from "../../../components/NewTaxonomy/NewTaxonomy"; +import { taxonomyPathsToSelectedItems, COMMENT_TAXONOMY_OPTIONS } from "../../../utils/commentClassification"; import "./CommentItem.scss"; import { LinkState } from "./LinkState"; @@ -33,6 +35,7 @@ interface CommentItemProps { updateComment: (comment: string, classifications?: any) => void; deleteComment: () => void; setConfirmMode: (confirmMode: boolean) => void; + setClassifications: (classifications: any) => void; setEditMode: (isGoingIntoEditMode: boolean) => void; toggleResolve: () => void; canResolveAny: boolean; @@ -42,198 +45,238 @@ interface CommentItemProps { _commentRef: React.Ref; }; listComments: ({ suppressClearComments }: { suppressClearComments: boolean }) => void; + classificationsItems: any; } -export const CommentItem: FC = observer(({ comment, listComments }: CommentItemProps) => { - const { - classifications, - updatedAt, - isEditMode, - isConfirmDelete, - createdAt, - isPersisted, - isDeleted, - createdBy, - text: initialText, - regionRef, - isResolved: resolved, - updateComment, - deleteComment, - setConfirmMode, - setEditMode, - toggleResolve, - canResolveAny, - isHighlighted, - setHighlighted, - _commentRef, - } = comment; - const { startLinkingMode: _startLinkingMode, currentComment, globalLinking } = useContext(CommentsContext); - const currentUser = window.APP_SETTINGS?.user; - const isCreator = currentUser?.id === createdBy.id; - const [text, setText] = useState(initialText); - - const [linkingComment, setLinkingComment] = useState(); - const region = regionRef?.region; - const result = regionRef?.result; - const linking = !!(linkingComment && currentComment === linkingComment && globalLinking); - const hasLinkState = linking || region; - - const startLinkingMode = useCallback( - (comment: any) => { - setLinkingComment(comment); - _startLinkingMode(comment); - }, - [_startLinkingMode], - ); - - const toggleLink = useCallback(() => { - if (regionRef?.region) { - comment.unsetLink(); - } else { - startLinkingMode(comment); - } - }, [comment, startLinkingMode, regionRef?.region]); - - if (isDeleted) return null; - - const TimeTracker = () => { - const editedTimeAchondritic = new Date(updatedAt); - const createdTimeAchondritic = new Date(createdAt); - - editedTimeAchondritic.setMilliseconds(0); - createdTimeAchondritic.setMilliseconds(0); - - const isEdited = editedTimeAchondritic > createdTimeAchondritic; - const time = isEdited ? updatedAt : createdAt; - - if (isPersisted && time) - return ( - - - {`${isEdited ? "updated" : ""} ${humanDateDiff(time)}`} - - - ); - return null; - }; +export const CommentItem: FC = observer( + ({ comment, listComments, classificationsItems }: CommentItemProps) => { + const { + classifications, + updatedAt, + isEditMode, + isConfirmDelete, + createdAt, + isPersisted, + isDeleted, + createdBy, + text: initialText, + regionRef, + isResolved: resolved, + updateComment, + deleteComment, + setConfirmMode, + setClassifications, + setEditMode, + toggleResolve, + canResolveAny, + isHighlighted, + setHighlighted, + _commentRef, + } = comment; + const { startLinkingMode: _startLinkingMode, currentComment, globalLinking } = useContext(CommentsContext); + const currentUser = window.APP_SETTINGS?.user; + const isCreator = currentUser?.id === createdBy.id; + const [text, setText] = useState(initialText); - return ( - { - setHighlighted(true); - }} - onMouseLeave={() => { - setHighlighted(false); - }} - ref={_commentRef} - > - - - - - {userDisplayName(createdBy)} - - + const [linkingComment, setLinkingComment] = useState(); + const region = regionRef?.region; + const result = regionRef?.result; + const linking = !!(linkingComment && currentComment === linkingComment && globalLinking); + const hasLinkState = linking || region; + + const startLinkingMode = useCallback( + (comment: any) => { + setLinkingComment(comment); + _startLinkingMode(comment); + }, + [_startLinkingMode], + ); + + const toggleLink = useCallback(() => { + if (regionRef?.region) { + comment.unsetLink(); + } else { + startLinkingMode(comment); + } + }, [comment, startLinkingMode, regionRef?.region]); + + const taxonomyOnChange = useCallback( + async (_: Node, values: TaxonomyPath[]) => { + const newClassifications = + values.length > 0 + ? { + default: { + type: "taxonomy", + values, + }, + } + : null; + setClassifications(newClassifications); + }, + [setClassifications], + ); + + const taxonomySelectedItems = useMemo( + () => taxonomyPathsToSelectedItems(classifications?.default?.values), + [classifications], + ); + + const commentFormBaseOnSubmit = useCallback( + async (value: any) => { + await updateComment(value, classifications); + setText(value); + await listComments({ suppressClearComments: true }); + }, + [updateComment, listComments, classifications], + ); + + if (isDeleted) return null; + + const TimeTracker = () => { + const editedTimeAchondritic = new Date(updatedAt); + const createdTimeAchondritic = new Date(createdAt); + + editedTimeAchondritic.setMilliseconds(0); + createdTimeAchondritic.setMilliseconds(0); + + const isEdited = editedTimeAchondritic > createdTimeAchondritic; + const time = isEdited ? updatedAt : createdAt; - - - - + if (isPersisted && time) + return ( + + + {`${isEdited ? "updated" : ""} ${humanDateDiff(time)}`} + - - - - - - - {isEditMode ? ( - { - await updateComment(value); - setText(value); - await listComments({ suppressClearComments: true }); - }} - /> - ) : isConfirmDelete ? ( - - Are you sure? - - - - + ); + return null; + }; + + return ( + { + setHighlighted(true); + }} + onMouseLeave={() => { + setHighlighted(false); + }} + ref={_commentRef} + > + + + + + {userDisplayName(createdBy)} - ) : ( - <> - {classifications?.default?.values?.length > 0 && ( - - {classifications?.default?.values?.map((valueArray: string[], index: number) => ( -
  • {valueArray.join("/")}
  • - ))} -
    - )} - {text} - {hasLinkState && ( - - +
    + + + + + + + + +
    + + + + {isEditMode ? ( + <> + + {classificationsItems.length > 0 && ( + + + + )} + + ) : isConfirmDelete ? ( + + Are you sure? + + + - )} - - )} - + + ) : ( + <> + {classifications?.default?.values?.length > 0 && ( + + {classifications?.default?.values?.map((valueArray: string[], index: number) => ( +
  • {valueArray.join("/")}
  • + ))} +
    + )} + {text} + {hasLinkState && ( + + + + )} + + )} +
    - { - e.stopPropagation(); - e.preventDefault(); - }} - > - {isPersisted && (isCreator || canResolveAny) && ( - - {resolved ? "Unresolve" : "Resolve"} - {isCreator && ( - <> - { - const isGoingIntoEditMode = !isEditMode; - - setEditMode(isGoingIntoEditMode); - if (!isGoingIntoEditMode) { - setText(initialText); - } - }} - > - {isEditMode ? "Cancel edit" : "Edit"} - - {regionRef?.region ? "Unlink" : "Link to..."} - {!isConfirmDelete && ( + { + e.stopPropagation(); + e.preventDefault(); + }} + > + {isPersisted && (isCreator || canResolveAny) && ( + + {resolved ? "Unresolve" : "Resolve"} + {isCreator && ( + <> { - setConfirmMode(true); + const isGoingIntoEditMode = !isEditMode; + + setEditMode(isGoingIntoEditMode); + if (!isGoingIntoEditMode) { + setText(initialText); + } }} > - Delete + {isEditMode ? "Cancel edit" : "Edit"} - )} - - )} - - } - > -