Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions web/libs/editor/src/components/Comments/Comment/CommentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { LINK_COMMENT_MODE } from "../../../stores/Annotation/LinkingModes";
import { CommentBase } from "../../../stores/Comment/Comment";
import { TextArea } from "../../../common/TextArea/TextArea";
import type { ActionRefValue } from "../../../common/TextArea/TextArea";
import { Block, Elem } from "../../../utils/bem";
import { cn } from "../../../utils/bem";
import { FF_DEV_3873, isFF } from "../../../utils/feature-flags";

import { LinkState } from "./LinkState";
Expand Down Expand Up @@ -148,8 +148,12 @@ export const CommentForm: FC<CommentFormProps> = observer(({ commentStore, annot
);

return (
<Block ref={formRef} tag="form" name="comment-form-new" mod={{ inline, linked: !!region }} onSubmit={onSubmit}>
<Elem name="text-row">
<form
ref={formRef as any}
className={cn("comment-form-new").mod({ inline, linked: !!region }).toClassName()}
onSubmit={onSubmit}
>
<div className={cn("comment-form-new").elem("text-row").toClassName()}>
<TextArea
actionRef={actionRef}
name="comment"
Expand All @@ -164,27 +168,29 @@ export const CommentForm: FC<CommentFormProps> = observer(({ commentStore, annot
{classificationsItems.length === 0 && (
<CommentFormButtons region={region} linking={linking} onLinkTo={linkToHandler} />
)}
</Elem>
</div>
{classificationsItems.length > 0 && (
<Elem name="classifications-row">
<Elem name="category-selector">
<div className={cn("comment-form-new").elem("classifications-row").toClassName()}>
<div className={cn("comment-form-new").elem("category-selector").toClassName()}>
<Taxonomy
selected={selections}
items={classificationsItems}
onChange={taxonomyOnChange}
options={COMMENT_TAXONOMY_OPTIONS}
defaultSearch={false}
/>
</Elem>
</div>
<CommentFormButtons region={region} linking={linking} onLinkTo={linkToHandler} />
</Elem>
</div>
)}
{hasLinkState && (
<Elem name="link-state">
<div className={cn("comment-form-new").elem("link-state").toClassName()}>
<LinkState linking={linking} region={region} result={result} onUnlink={currentComment?.unsetLink} />
</Elem>
</div>
)}
{commentStore.tooltipMessage && <Elem name="tooltipMessage">{commentStore.tooltipMessage}</Elem>}
</Block>
{commentStore.tooltipMessage && (
<div className={cn("comment-form-new").elem("tooltipMessage").toClassName()}>{commentStore.tooltipMessage}</div>
)}
</form>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,30 @@ import type { MouseEventHandler } from "react";

import { IconCommentLinkTo, IconSend } from "@humansignal/icons";
import { Tooltip } from "@humansignal/ui";
import { Block, Elem } from "../../../utils/bem";
import { cn } from "../../../utils/bem";
import "./CommentFormButtons.scss";

export const CommentFormButtons = ({
region,
linking,
onLinkTo,
}: { region: any; linking: boolean; onLinkTo?: MouseEventHandler<HTMLElement> }) => (
<Block name="comment-form-buttons">
<Elem name="buttons">
<div className={cn("comment-form-buttons").toClassName()}>
<div className={cn("comment-form-buttons").elem("buttons").toClassName()}>
{onLinkTo && !region && (
<Tooltip title="Link to...">
<Elem name="action" tag="button" mod={{ highlight: linking }} onClick={onLinkTo}>
<button
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Funny that we missed these buttons when we were refactoring Button component. cc @nick-skriabin

type="button"
className={cn("comment-form-buttons").elem("action").mod({ highlight: linking }).toClassName()}
onClick={onLinkTo}
>
<IconCommentLinkTo />
</Elem>
</button>
</Tooltip>
)}
<Elem name="action" tag="button" type="submit">
<button type="submit" className={cn("comment-form-buttons").elem("action").toClassName()}>
<IconSend />
</Elem>
</Elem>
</Block>
</button>
</div>
</div>
);
70 changes: 34 additions & 36 deletions web/libs/editor/src/components/Comments/Comment/CommentItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Button } from "@humansignal/ui";
import { Dropdown } from "../../../common/Dropdown/Dropdown";
import { Menu } from "../../../common/Menu/Menu";
import { Space } from "../../../common/Space/Space";
import { Block, Elem } from "../../../utils/bem";
import { cn } from "../../../utils/bem";
import { humanDateDiff, userDisplayName } from "../../../utils/utilities";
import { CommentFormBase } from "../CommentFormBase";
import { CommentsContext } from "./CommentsList";
Expand Down Expand Up @@ -144,71 +144,69 @@ export const CommentItem: FC<CommentItemProps> = observer(

if (isPersisted && time)
return (
<Elem name="date">
<div className={cn("comment-item").elem("date").toClassName()}>
<Tooltip alignment="top-right" title={new Date(time).toLocaleString()}>
<span>{`${isEdited ? "updated" : ""} ${humanDateDiff(time)}`}</span>
</Tooltip>
</Elem>
</div>
);
return null;
};

return (
<Block
name="comment-item"
mod={{ resolved, highlighted: isHighlighted }}
<div
className={cn("comment-item").mod({ resolved, highlighted: isHighlighted }).toClassName()}
onMouseEnter={() => {
setHighlighted(true);
}}
onMouseLeave={() => {
setHighlighted(false);
}}
ref={_commentRef}
ref={_commentRef as any}
>
<Space spread size="medium" truncated>
<Space size="small" truncated>
<Elem
tag={Userpic}
<Userpic
className={cn("comment-item").elem("userpic").toClassName()}
user={hiddenUser ?? createdBy}
name="userpic"
showUsernameTooltip
showUsername
username={createdBy}
/>
<Elem name="name" tag="span">
<span className={cn("comment-item").elem("name").toClassName()}>
{userDisplayName(hiddenUser ?? createdBy)}
</Elem>
</span>
</Space>

<Space size="small">
<Elem name="resolved" component={IconCheck} />
<Elem name="saving" mod={{ hide: isPersisted }}>
<Elem name="dot" />
</Elem>
<IconCheck className={cn("comment-item").elem("resolved").toClassName()} />
<div className={cn("comment-item").elem("saving").mod({ hide: isPersisted }).toClassName()}>
<div className={cn("comment-item").elem("dot").toClassName()} />
</div>
{!infoIsHidden && <TimeTracker />}
</Space>
</Space>

<Elem name="content">
<Elem name="text">
<div className={cn("comment-item").elem("content").toClassName()}>
<div className={cn("comment-item").elem("text").toClassName()}>
{isEditMode ? (
<>
<CommentFormBase value={text} onSubmit={commentFormBaseOnSubmit} classifications={classifications} />
{classificationsItems.length > 0 && (
<Elem name="classifications-row">
<div className={cn("comment-item").elem("classifications-row").toClassName()}>
<Taxonomy
selected={taxonomySelectedItems}
items={classificationsItems}
onChange={taxonomyOnChange}
options={COMMENT_TAXONOMY_OPTIONS}
defaultSearch={false}
/>
</Elem>
</div>
)}
</>
) : isConfirmDelete ? (
<Elem name="confirmForm">
<Elem name="question">Are you sure?</Elem>
<Elem name="controls">
<div className={cn("comment-item").elem("confirmForm").toClassName()}>
<div className={cn("comment-item").elem("question").toClassName()}>Are you sure?</div>
<div className={cn("comment-item").elem("controls").toClassName()}>
<Button
onClick={() => deleteComment()}
size="small"
Expand All @@ -221,29 +219,29 @@ export const CommentItem: FC<CommentItemProps> = observer(
<Button onClick={() => setConfirmMode(false)} size="small" aria-label="Cancel delete">
No
</Button>
</Elem>
</Elem>
</div>
</div>
) : (
<>
{classifications?.default?.values?.length > 0 && (
<Elem name="classifications" tag="ul">
<ul className={cn("comment-item").elem("classifications").toClassName()}>
{classifications?.default?.values?.map((valueArray: string[], index: number) => (
<li key={index}>{valueArray.join("/")}</li>
))}
</Elem>
</ul>
)}
{text}
{hasLinkState && (
<Elem name="linkState">
<div className={cn("comment-item").elem("linkState").toClassName()}>
<LinkState linking={linking} region={region} result={result} interactive />
</Elem>
</div>
)}
</>
)}
</Elem>
</div>

<Elem
name="actions"
<div
className={cn("comment-item").elem("actions").toClassName()}
onClick={(e: any) => {
e.stopPropagation();
e.preventDefault();
Expand Down Expand Up @@ -286,9 +284,9 @@ export const CommentItem: FC<CommentItemProps> = observer(
<Button size="small" look="string" icon={<IconEllipsis />} aria-label="Comment options" />
</Dropdown.Trigger>
)}
</Elem>
</Elem>
</Block>
</div>
</div>
</div>
);
},
);
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createContext, type FC, useCallback, useMemo } from "react";
import { observer } from "mobx-react";

import { LINK_COMMENT_MODE } from "../../../stores/Annotation/LinkingModes";
import { Block } from "../../../utils/bem";
import { cn } from "../../../utils/bem";
import { CommentItem } from "./CommentItem";

export type CommentContextType = {
Expand Down Expand Up @@ -39,7 +39,7 @@ export const CommentsList: FC<{ commentStore: any }> = observer(({ commentStore

export const CommentsListInner: FC<{ commentStore: any }> = observer(({ commentStore }) => {
return (
<Block name="comments-list">
<div className={cn("comments-list").toClassName()}>
{commentStore.comments.map((comment: any) => (
<CommentItem
key={comment.id}
Expand All @@ -48,6 +48,6 @@ export const CommentsListInner: FC<{ commentStore: any }> = observer(({ commentS
classificationsItems={commentStore.commentClassificationsItems}
/>
))}
</Block>
</div>
);
});
47 changes: 25 additions & 22 deletions web/libs/editor/src/components/Comments/Comment/LinkState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { observer } from "mobx-react";
import chroma from "chroma-js";
import { Button } from "@humansignal/ui";
import { IconCommentLinkTo, IconClose } from "@humansignal/icons";
import { Block, Elem } from "../../../utils/bem";
import { cn } from "../../../utils/bem";
import { NodeIcon } from "../../Node/Node";
import { RegionLabel } from "../../SidePanels/OutlinerPanel/RegionLabel";

Expand All @@ -26,13 +26,13 @@ export const LinkState: FC<LinkStateProps> = ({ linking, region, result, onUnlin
}, [linking, region]);
if (!isVisible) return null;
return (
<Block tag="div" name="link-state" mod={mod}>
<Elem tag="div" name="prefix">
<div className={cn("link-state").mod(mod).toClassName()}>
<div className={cn("link-state").elem("prefix").toClassName()}>
<IconCommentLinkTo />
</Elem>
</div>
{mod?.action && "Select an object to link it to this comment."}
{mod?.display && <LinkedRegion region={region} result={result} onUnlink={onUnlink} interactive={interactive} />}
</Block>
</div>
);
};

Expand Down Expand Up @@ -72,36 +72,39 @@ const LinkedRegion: FC<LinkedRegionProps> = observer(({ region, result, interact
}, [itemColor]);

return (
<Block
name="link-state-region"
mod={{ interactive }}
style={style}
<div
className={cn("link-state-region").mod({ interactive }).toClassName()}
style={style as any}
onMouseEnter={mouseEnterHandler}
onMouseLeave={mouseLeaveHandler}
onClick={clickHandler}
>
{!isClassification && (
<>
<Elem name="icon">
<div className={cn("link-state-region").elem("icon").toClassName()}>
<NodeIcon node={region} />
</Elem>
<Elem name="index">{region.region_index}</Elem>
</div>
<div className={cn("link-state-region").elem("index").toClassName()}>{region.region_index}</div>
</>
)}
{result ? (
<Elem name="title">
<div className={cn("link-state-region").elem("title").toClassName()}>
<ResultText result={result} />
</Elem>
</div>
) : (
<Elem name="title">
<Elem name="label">
<div className={cn("link-state-region").elem("title").toClassName()}>
<div className={cn("link-state-region").elem("label").toClassName()}>
<RegionLabel item={region} />
</Elem>
{region?.text && <Elem name="text">{region.text.replace(/\\n/g, "\n")}</Elem>}
</Elem>
</div>
{region?.text && (
<div className={cn("link-state-region").elem("text").toClassName()}>
{region.text.replace(/\\n/g, "\n")}
</div>
)}
</div>
)}
{onUnlink && (
<Elem name="close">
<div className={cn("link-state-region").elem("close").toClassName()}>
<Button
size="small"
variant="neutral"
Expand All @@ -110,9 +113,9 @@ const LinkedRegion: FC<LinkedRegionProps> = observer(({ region, result, interact
onClick={onUnlink}
aria-label="Unlink comment"
/>
</Elem>
</div>
)}
</Block>
</div>
);
});

Expand Down
Loading
Loading