@ynput/ayon-frontend-shared 0.2.9 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DetailsPanel.cjs.js +1 -0
- package/dist/DetailsPanel.cjs.js.map +1 -1
- package/dist/DetailsPanel.es.js +1 -0
- package/dist/DetailsPanel.es.js.map +1 -1
- package/dist/_virtual/index.cjs10.js +3 -5
- package/dist/_virtual/index.cjs10.js.map +1 -1
- package/dist/_virtual/index.cjs4.js +4 -4
- package/dist/_virtual/index.cjs5.js +4 -4
- package/dist/_virtual/index.cjs6.js +2 -2
- package/dist/_virtual/index.cjs7.js +5 -3
- package/dist/_virtual/index.cjs7.js.map +1 -1
- package/dist/_virtual/index.cjs8.js +4 -4
- package/dist/_virtual/index.cjs9.js +4 -4
- package/dist/_virtual/index.es10.js +2 -5
- package/dist/_virtual/index.es10.js.map +1 -1
- package/dist/_virtual/index.es4.js +4 -4
- package/dist/_virtual/index.es5.js +4 -4
- package/dist/_virtual/index.es6.js +2 -2
- package/dist/_virtual/index.es7.js +5 -2
- package/dist/_virtual/index.es7.js.map +1 -1
- package/dist/_virtual/index.es8.js +4 -4
- package/dist/_virtual/index.es9.js +4 -4
- package/dist/index.cjs.js +1 -0
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +1 -0
- package/dist/index.es.js.map +1 -1
- package/dist/node_modules/match-sorter/dist/match-sorter.esm.cjs.js +1 -1
- package/dist/node_modules/match-sorter/dist/match-sorter.esm.es.js +1 -1
- package/dist/node_modules/parse-numeric-range/index.cjs.js +1 -1
- package/dist/node_modules/parse-numeric-range/index.es.js +1 -1
- package/dist/node_modules/rehype/node_modules/unified/lib/index.cjs.js +2 -2
- package/dist/node_modules/rehype/node_modules/unified/lib/index.es.js +2 -2
- package/dist/node_modules/rehype-parse/lib/index.cjs.js +1 -1
- package/dist/node_modules/rehype-parse/lib/index.es.js +1 -1
- package/dist/node_modules/rehype-prism-plus/dist/index.es.cjs.js +1 -1
- package/dist/node_modules/rehype-prism-plus/dist/index.es.es.js +1 -1
- package/dist/node_modules/remove-accents/index.cjs.js +1 -1
- package/dist/node_modules/remove-accents/index.es.js +1 -1
- package/dist/node_modules/vfile/lib/index.cjs.js +1 -1
- package/dist/node_modules/vfile/lib/index.es.js +1 -1
- package/dist/shared/src/components/DetailsPanelAttributes/DetailsPanelAttributes.cjs.js +1 -0
- package/dist/shared/src/components/DetailsPanelAttributes/DetailsPanelAttributes.cjs.js.map +1 -1
- package/dist/shared/src/components/DetailsPanelAttributes/DetailsPanelAttributes.es.js +1 -0
- package/dist/shared/src/components/DetailsPanelAttributes/DetailsPanelAttributes.es.js.map +1 -1
- package/dist/shared/src/components/EntityThumbnailUploader/EntityThumbnailUploader.cjs.js +1 -0
- package/dist/shared/src/components/EntityThumbnailUploader/EntityThumbnailUploader.cjs.js.map +1 -1
- package/dist/shared/src/components/EntityThumbnailUploader/EntityThumbnailUploader.es.js +1 -0
- package/dist/shared/src/components/EntityThumbnailUploader/EntityThumbnailUploader.es.js.map +1 -1
- package/dist/shared/src/components/ReviewablesList/ReviewablesList.cjs.js +1 -0
- package/dist/shared/src/components/ReviewablesList/ReviewablesList.cjs.js.map +1 -1
- package/dist/shared/src/components/ReviewablesList/ReviewablesList.es.js +1 -0
- package/dist/shared/src/components/ReviewablesList/ReviewablesList.es.js.map +1 -1
- package/dist/shared/src/components/ReviewablesList/ReviewablesUpload.cjs.js +1 -0
- package/dist/shared/src/components/ReviewablesList/ReviewablesUpload.cjs.js.map +1 -1
- package/dist/shared/src/components/ReviewablesList/ReviewablesUpload.es.js +1 -0
- package/dist/shared/src/components/ReviewablesList/ReviewablesUpload.es.js.map +1 -1
- package/dist/shared/src/components/ReviewablesList/SortableReviewableCard.cjs.js +1 -0
- package/dist/shared/src/components/ReviewablesList/SortableReviewableCard.cjs.js.map +1 -1
- package/dist/shared/src/components/ReviewablesList/SortableReviewableCard.es.js +1 -0
- package/dist/shared/src/components/ReviewablesList/SortableReviewableCard.es.js.map +1 -1
- package/dist/shared/src/components/SimpleFormDialog/SimpleFormDialog.cjs.js +3 -2
- package/dist/shared/src/components/SimpleFormDialog/SimpleFormDialog.cjs.js.map +1 -1
- package/dist/shared/src/components/SimpleFormDialog/SimpleFormDialog.es.js +3 -2
- package/dist/shared/src/components/SimpleFormDialog/SimpleFormDialog.es.js.map +1 -1
- package/dist/shared/src/containers/Actions/ActionConfigDialog.cjs.js +1 -0
- package/dist/shared/src/containers/Actions/ActionConfigDialog.cjs.js.map +1 -1
- package/dist/shared/src/containers/Actions/ActionConfigDialog.es.js +1 -0
- package/dist/shared/src/containers/Actions/ActionConfigDialog.es.js.map +1 -1
- package/dist/shared/src/containers/Actions/Actions.cjs.js +6 -0
- package/dist/shared/src/containers/Actions/Actions.cjs.js.map +1 -1
- package/dist/shared/src/containers/Actions/Actions.es.js +6 -0
- package/dist/shared/src/containers/Actions/Actions.es.js.map +1 -1
- package/dist/shared/src/containers/Actions/InteractiveActionDialog.cjs.js +1 -0
- package/dist/shared/src/containers/Actions/InteractiveActionDialog.cjs.js.map +1 -1
- package/dist/shared/src/containers/Actions/InteractiveActionDialog.es.js +1 -0
- package/dist/shared/src/containers/Actions/InteractiveActionDialog.es.js.map +1 -1
- package/dist/shared/src/containers/DetailsPanel/DetailsPanel.cjs.js +1 -0
- package/dist/shared/src/containers/DetailsPanel/DetailsPanel.cjs.js.map +1 -1
- package/dist/shared/src/containers/DetailsPanel/DetailsPanel.es.js +1 -0
- package/dist/shared/src/containers/DetailsPanel/DetailsPanel.es.js.map +1 -1
- package/dist/shared/src/containers/DetailsPanel/DetailsPanelFiles/DetailsPanelFiles.cjs.js +1 -0
- package/dist/shared/src/containers/DetailsPanel/DetailsPanelFiles/DetailsPanelFiles.cjs.js.map +1 -1
- package/dist/shared/src/containers/DetailsPanel/DetailsPanelFiles/DetailsPanelFiles.es.js +1 -0
- package/dist/shared/src/containers/DetailsPanel/DetailsPanelFiles/DetailsPanelFiles.es.js.map +1 -1
- package/dist/shared/src/containers/DetailsPanel/DetailsPanelFloating/DetailsPanelFloating.cjs.js +1 -0
- package/dist/shared/src/containers/DetailsPanel/DetailsPanelFloating/DetailsPanelFloating.cjs.js.map +1 -1
- package/dist/shared/src/containers/DetailsPanel/DetailsPanelFloating/DetailsPanelFloating.es.js +1 -0
- package/dist/shared/src/containers/DetailsPanel/DetailsPanelFloating/DetailsPanelFloating.es.js.map +1 -1
- package/dist/shared/src/containers/DetailsPanel/DetailsPanelHeader/DetailsPanelHeader.cjs.js +1 -0
- package/dist/shared/src/containers/DetailsPanel/DetailsPanelHeader/DetailsPanelHeader.cjs.js.map +1 -1
- package/dist/shared/src/containers/DetailsPanel/DetailsPanelHeader/DetailsPanelHeader.es.js +1 -0
- package/dist/shared/src/containers/DetailsPanel/DetailsPanelHeader/DetailsPanelHeader.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/Feed.cjs.js +23 -2
- package/dist/shared/src/containers/Feed/Feed.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/Feed.es.js +24 -3
- package/dist/shared/src/containers/Feed/Feed.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/ActivityComment/ActivityComment.cjs.js +18 -0
- package/dist/shared/src/containers/Feed/components/ActivityComment/ActivityComment.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/ActivityComment/ActivityComment.es.js +19 -1
- package/dist/shared/src/containers/Feed/components/ActivityComment/ActivityComment.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/CommentInput/CommentInput.cjs.js +7 -4
- package/dist/shared/src/containers/Feed/components/CommentInput/CommentInput.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/CommentInput/CommentInput.es.js +7 -4
- package/dist/shared/src/containers/Feed/components/CommentInput/CommentInput.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/CommentInput/helpers.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/CommentInput/helpers.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/CommentInput/hooks/useAnnotationsSync.cjs.js +1 -1
- package/dist/shared/src/containers/Feed/components/CommentInput/hooks/useAnnotationsSync.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/CommentInput/hooks/useAnnotationsSync.es.js +1 -1
- package/dist/shared/src/containers/Feed/components/CommentInput/hooks/useAnnotationsSync.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/CommentInput/hooks/useAnnotationsUpload.cjs.js +27 -15
- package/dist/shared/src/containers/Feed/components/CommentInput/hooks/useAnnotationsUpload.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/CommentInput/hooks/useAnnotationsUpload.es.js +27 -15
- package/dist/shared/src/containers/Feed/components/CommentInput/hooks/useAnnotationsUpload.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/FileUploadCard/FileUploadCard.cjs.js +40 -12
- package/dist/shared/src/containers/Feed/components/FileUploadCard/FileUploadCard.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/FileUploadCard/FileUploadCard.es.js +41 -13
- package/dist/shared/src/containers/Feed/components/FileUploadCard/FileUploadCard.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/FileUploadCard/FileUploadCard.styled.cjs.js +33 -19
- package/dist/shared/src/containers/Feed/components/FileUploadCard/FileUploadCard.styled.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/FileUploadCard/FileUploadCard.styled.es.js +33 -19
- package/dist/shared/src/containers/Feed/components/FileUploadCard/FileUploadCard.styled.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/FilesGrid/FilesGrid.cjs.js +14 -12
- package/dist/shared/src/containers/Feed/components/FilesGrid/FilesGrid.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/FilesGrid/FilesGrid.es.js +14 -12
- package/dist/shared/src/containers/Feed/components/FilesGrid/FilesGrid.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/components/Tooltips/EntityTooltip/EntityTooltip.cjs.js +8 -8
- package/dist/shared/src/containers/Feed/components/Tooltips/EntityTooltip/EntityTooltip.es.js +8 -8
- package/dist/shared/src/containers/Feed/helpers/mergeAnnotationAttachments.cjs.js +18 -0
- package/dist/shared/src/containers/Feed/helpers/mergeAnnotationAttachments.cjs.js.map +1 -0
- package/dist/shared/src/containers/Feed/helpers/mergeAnnotationAttachments.es.js +19 -0
- package/dist/shared/src/containers/Feed/helpers/mergeAnnotationAttachments.es.js.map +1 -0
- package/dist/shared/src/containers/Feed/hooks/useCommentMutations.cjs.js +12 -3
- package/dist/shared/src/containers/Feed/hooks/useCommentMutations.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/hooks/useCommentMutations.es.js +12 -3
- package/dist/shared/src/containers/Feed/hooks/useCommentMutations.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/hooks/useTransformActivities.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/hooks/useTransformActivities.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.cjs.js +6 -6
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.es.js +6 -6
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/buildTreeTableColumns.cjs.js +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/buildTreeTableColumns.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/buildTreeTableColumns.es.js +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/buildTreeTableColumns.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/context/ColumnSettingsContext.cjs.js +20 -2
- package/dist/shared/src/containers/ProjectTreeTable/context/ColumnSettingsContext.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/context/ColumnSettingsContext.es.js +20 -2
- package/dist/shared/src/containers/ProjectTreeTable/context/ColumnSettingsContext.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/ThumbnailWidget.cjs.js +2 -6
- package/dist/shared/src/containers/ProjectTreeTable/widgets/ThumbnailWidget.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/ThumbnailWidget.es.js +2 -6
- package/dist/shared/src/containers/ProjectTreeTable/widgets/ThumbnailWidget.es.js.map +1 -1
- package/dist/shared/src/containers/RepresentationsList/RepresentationsList.cjs.js +1 -0
- package/dist/shared/src/containers/RepresentationsList/RepresentationsList.cjs.js.map +1 -1
- package/dist/shared/src/containers/RepresentationsList/RepresentationsList.es.js +1 -0
- package/dist/shared/src/containers/RepresentationsList/RepresentationsList.es.js.map +1 -1
- package/dist/shared/src/context/DetailsPanelContext.cjs.js +4 -0
- package/dist/shared/src/context/DetailsPanelContext.cjs.js.map +1 -1
- package/dist/shared/src/context/DetailsPanelContext.es.js +4 -0
- package/dist/shared/src/context/DetailsPanelContext.es.js.map +1 -1
- package/dist/shared/src/hooks/useActionTriggers.cjs.js +75 -0
- package/dist/shared/src/hooks/useActionTriggers.cjs.js.map +1 -1
- package/dist/shared/src/hooks/useActionTriggers.es.js +75 -0
- package/dist/shared/src/hooks/useActionTriggers.es.js.map +1 -1
- package/dist/types/containers/Actions/Actions.d.ts +2 -1
- package/dist/types/containers/Feed/components/CommentInput/CommentInput.d.ts +1 -1
- package/dist/types/containers/Feed/components/CommentInput/helpers.d.ts +6 -1
- package/dist/types/containers/Feed/components/CommentInput/hooks/useAnnotationsSync.d.ts +1 -1
- package/dist/types/containers/Feed/components/CommentInput/hooks/useAnnotationsUpload.d.ts +5 -1
- package/dist/types/containers/Feed/components/FileUploadCard/FileUploadCard.d.ts +5 -2
- package/dist/types/containers/Feed/components/FileUploadCard/FileUploadCard.styled.d.ts +4 -0
- package/dist/types/containers/Feed/components/FilesGrid/FilesGrid.d.ts +1 -1
- package/dist/types/containers/Feed/helpers/mergeAnnotationAttachments.d.ts +2 -0
- package/dist/types/containers/Feed/hooks/useCommentMutations.d.ts +1 -1
- package/dist/types/containers/Feed/index.d.ts +6 -0
- package/dist/types/context/DetailsPanelContext.d.ts +4 -0
- package/dist/types/hooks/useActionTriggers.d.ts +1 -0
- package/package.json +1 -1
package/dist/shared/src/containers/Feed/components/ActivityComment/ActivityComment.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActivityComment.cjs.js","sources":["../../../../../../../src/containers/Feed/components/ActivityComment/ActivityComment.tsx"],"sourcesContent":["import clsx from 'clsx'\nimport { useMemo } from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport emoji from 'remark-emoji'\nimport remarkGfm from 'remark-gfm'\nimport remarkDirective from 'remark-directive'\nimport remarkDirectiveRehype from 'remark-directive-rehype'\n\nimport CommentInput from '../CommentInput/CommentInput'\nimport Reactions from '../ReactionContainer/Reactions'\nimport { Reaction } from '../ReactionContainer/types'\nimport useReferenceTooltip from '../../hooks/useReferenceTooltip'\nimport FilesGrid, { FilesGridProps } from '../FilesGrid/FilesGrid'\n\nimport { getTextRefs } from '../CommentInput/quillToMarkdown'\nimport * as Styled from './ActivityComment.styled'\nimport CommentWrapper from './CommentWrapper'\nimport { aTag, blockquoteTag, codeTag, inputTag } from './ActivityMarkdownComponents'\nimport { mapGraphQLReactions } from './mappers'\nimport { Icon } from '@ynput/ayon-react-components'\nimport ActivityStatus from '../ActivityStatus/ActivityStatus'\nimport { useFeedContext } from '../../context/FeedContext'\nimport { confirmDelete } from '../../../../util'\nimport ActivityHeader, { ActivityHeaderProps } from '../ActivityHeader/ActivityHeader'\nimport type { Status } from '../../../ProjectTreeTable/types/project'\n\ntype Props = {\n activity: any\n onCheckChange?: Function\n onDelete?: (activityId: string, entityId: string, refs: any) => Promise<void>\n onUpdate?: Function\n projectInfo: any\n editProps?: {\n disabled: boolean\n isLoading: boolean\n }\n projectName: string\n entityType: string\n onReferenceClick?: ActivityHeaderProps['onReferenceClick']\n onFileExpand?: FilesGridProps['onExpand']\n showOrigin?: boolean\n isHighlighted?: boolean\n readOnly?: boolean\n statuses: Status[]\n}\n\nconst ActivityComment = ({\n activity = {},\n onCheckChange,\n onDelete,\n onUpdate,\n projectInfo,\n editProps,\n projectName,\n entityType,\n onReferenceClick,\n onFileExpand,\n showOrigin,\n isHighlighted,\n readOnly,\n statuses = [],\n}: Props) => {\n const { userName, createReaction, deleteReaction } = useFeedContext()\n\n let {\n body,\n authorName,\n authorFullName,\n createdAt,\n referenceType,\n entityId,\n activityId,\n author,\n isOwner,\n files = [],\n origin,\n } = activity\n if (!authorName) authorName = author?.name || ''\n if (!authorFullName) authorFullName = author?.fullName || authorName\n\n const { editingId, setEditingId } = useFeedContext()\n\n const handleEditComment = () => {\n setEditingId(activityId)\n }\n\n const handleEditCancel = () => {\n // close the edit comment\n setEditingId(null)\n }\n\n const handleSave = async (value: any, files: any) => {\n await onUpdate?.(value, files)\n setEditingId(null)\n }\n\n const isEditing = editingId === activityId\n\n const isRef = referenceType !== 'origin' || showOrigin\n\n const handleDelete = async () => {\n const refs = getTextRefs(body)\n\n // if the comment is a reference, (it's origin is not the entity)\n // we need to delete the reference from the origin as well\n // add it to the refs to delete\n if (isRef && origin) {\n refs.push({ id: origin.id, type: origin.type })\n }\n\n // note: body is used to match other refs to delete\n onDelete && (await onDelete(activityId, entityId, refs))\n }\n\n const deleteConfirmation = () => {\n confirmDelete({\n title: 'Delete comment',\n message: 'Are you sure you want to delete this comment?',\n accept: async () => {\n await handleDelete()\n },\n })\n }\n\n const [, setRefTooltip] = useReferenceTooltip()\n\n const mappedReactions = useMemo(\n () => mapGraphQLReactions(activity.reactions, userName),\n [[...(activity.reactions || [])]],\n )\n\n const reactionChangeHandler = (reaction: Reaction) => {\n if (reaction.isActive) {\n createReaction({\n projectName: projectName,\n // @ts-ignore exposed endpoint doesn't need the username, we still need to pass it for the optimistic update\n userName: userName,\n activityId: activityId,\n createReactionModel: {\n reaction: reaction.type,\n },\n })\n } else {\n deleteReaction({\n projectName: projectName,\n // @ts-ignore exposed endpoint doesn't need the username, we still need to pass it for the optimistic update\n userName: userName,\n activityId: activityId,\n reaction: reaction.type,\n })\n }\n }\n\n return (\n <>\n <Styled.Comment\n className={clsx('comment', { isOwner, isEditing, isHighlighted })}\n id={activityId}\n >\n <ActivityHeader\n name={authorName}\n fullName={authorFullName}\n date={createdAt}\n isRef={isRef}\n activity={activity}\n // projectInfo={projectInfo}\n projectName={projectName}\n entityType={entityType}\n onReferenceClick={onReferenceClick}\n onReferenceTooltip={setRefTooltip}\n children={undefined}\n />\n <Styled.Body className={clsx('comment-body', { isEditing })}>\n {!readOnly && (\n <Styled.Tools className={'tools'}>\n {isOwner && onDelete && (\n <Styled.ToolButton\n icon=\"delete\"\n onClick={deleteConfirmation}\n tooltip=\"Delete comment\"\n />\n )}\n {isOwner && handleEditComment && (\n <Styled.ToolButton icon=\"edit_square\" onClick={handleEditComment} />\n )}\n </Styled.Tools>\n )}\n {isEditing ? (\n <CommentInput\n initValue={body}\n initFiles={files}\n isEditing\n onClose={handleEditCancel}\n onSubmit={handleSave}\n isOpen={true}\n {...editProps}\n />\n ) : (\n <>\n <CommentWrapper>\n <ReactMarkdown\n remarkPlugins={[remarkGfm, emoji, remarkDirective, remarkDirectiveRehype]}\n urlTransform={(url) => url}\n components={{\n // a links\n // @ts-ignore\n a: (props) =>\n // @ts-ignore\n aTag(props, {\n entityId,\n projectName,\n projectInfo,\n onReferenceClick,\n onReferenceTooltip: setRefTooltip,\n activityId,\n }),\n // checkbox inputs\n // @ts-ignore\n input: (props) => inputTag(props, { activity, onCheckChange }),\n // code syntax highlighting\n // eslint-disable-next-line\n // @ts-ignore\n code: (props) => codeTag(props),\n // @ts-ignore\n blockquote: (props) => blockquoteTag(props),\n // @ts-ignore\n tip: (props) => (\n <Styled.Tip>\n <Icon icon=\"info\" />\n {props.children}\n </Styled.Tip>\n ),\n // @ts-ignore\n status: (props) => {\n return (\n <ActivityStatus name={props.id} statuses={statuses}>\n {props.children}\n </ActivityStatus>\n )\n },\n }}\n >\n {body}\n </ReactMarkdown>\n </CommentWrapper>\n {/* file uploads */}\n {/* @ts-ignore */}\n <FilesGrid\n files={files}\n isCompact={files.length > 6}\n activityId={activityId}\n projectName={projectName}\n isDownloadable\n onExpand={onFileExpand}\n onRemove={undefined}\n />\n </>\n )}\n\n {!isEditing && (\n <div style={{ marginTop: '16px' }}>\n {mappedReactions && (\n <Reactions\n reactions={mappedReactions}\n changeHandler={reactionChangeHandler}\n readOnly={readOnly}\n />\n )}\n </div>\n )}\n </Styled.Body>\n </Styled.Comment>\n </>\n )\n}\n\nexport default ActivityComment\n"],"names":["useFeedContext","files","getTextRefs","confirmDelete","useMemo","mapGraphQLReactions","jsx","Fragment","jsxs","Styled.Comment","Styled.Body","Styled.Tools","Styled.ToolButton","CommentInput","aTag","inputTag","codeTag","blockquoteTag","Styled.Tip","Icon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ActivityComment.cjs.js","sources":["../../../../../../../src/containers/Feed/components/ActivityComment/ActivityComment.tsx"],"sourcesContent":["import clsx from 'clsx'\nimport { useCallback, useMemo } from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport emoji from 'remark-emoji'\nimport remarkGfm from 'remark-gfm'\nimport remarkDirective from 'remark-directive'\nimport remarkDirectiveRehype from 'remark-directive-rehype'\n\nimport CommentInput from '../CommentInput/CommentInput'\nimport Reactions from '../ReactionContainer/Reactions'\nimport { Reaction } from '../ReactionContainer/types'\nimport useReferenceTooltip from '../../hooks/useReferenceTooltip'\nimport FilesGrid, { FilesGridProps } from '../FilesGrid/FilesGrid'\n\nimport { getTextRefs } from '../CommentInput/quillToMarkdown'\nimport * as Styled from './ActivityComment.styled'\nimport CommentWrapper from './CommentWrapper'\nimport { aTag, blockquoteTag, codeTag, inputTag } from './ActivityMarkdownComponents'\nimport { mapGraphQLReactions } from './mappers'\nimport { Icon } from '@ynput/ayon-react-components'\nimport ActivityStatus from '../ActivityStatus/ActivityStatus'\nimport { useFeedContext } from '../../context/FeedContext'\nimport { confirmDelete } from '../../../../util'\nimport ActivityHeader, { ActivityHeaderProps } from '../ActivityHeader/ActivityHeader'\nimport type { Status } from '../../../ProjectTreeTable/types/project'\nimport { SavedAnnotationMetadata } from '../../index'\nimport { useDetailsPanelContext } from '@shared/context'\n\ntype Props = {\n activity: any\n onCheckChange?: Function\n onDelete?: (activityId: string, entityId: string, refs: any) => Promise<void>\n onUpdate?: Function\n projectInfo: any\n editProps?: {\n disabled: boolean\n isLoading: boolean\n }\n projectName: string\n entityType: string\n onReferenceClick?: ActivityHeaderProps['onReferenceClick']\n onFileExpand?: FilesGridProps['onExpand']\n showOrigin?: boolean\n isHighlighted?: boolean\n readOnly?: boolean\n statuses: Status[]\n}\n\nconst ActivityComment = ({\n activity = {},\n onCheckChange,\n onDelete,\n onUpdate,\n projectInfo,\n editProps,\n projectName,\n entityType,\n onReferenceClick,\n onFileExpand,\n showOrigin,\n isHighlighted,\n readOnly,\n statuses = [],\n}: Props) => {\n const { userName, createReaction, deleteReaction } = useFeedContext()\n\n let {\n body,\n authorName,\n authorFullName,\n createdAt,\n referenceType,\n entityId,\n activityId,\n author,\n isOwner,\n files = [],\n origin,\n } = activity\n if (!authorName) authorName = author?.name || ''\n if (!authorFullName) authorFullName = author?.fullName || authorName\n\n const { editingId, setEditingId } = useFeedContext()\n const { onGoToFrame } = useDetailsPanelContext()\n\n const handleEditComment = () => {\n setEditingId(activityId)\n }\n\n const handleEditCancel = () => {\n // close the edit comment\n setEditingId(null)\n }\n\n const handleSave = async (value: any, files: any) => {\n await onUpdate?.(value, files)\n setEditingId(null)\n }\n\n const isEditing = editingId === activityId\n\n const isRef = referenceType !== 'origin' || showOrigin\n\n const handleDelete = async () => {\n const refs = getTextRefs(body)\n\n // if the comment is a reference, (it's origin is not the entity)\n // we need to delete the reference from the origin as well\n // add it to the refs to delete\n if (isRef && origin) {\n refs.push({ id: origin.id, type: origin.type })\n }\n\n // note: body is used to match other refs to delete\n onDelete && (await onDelete(activityId, entityId, refs))\n }\n\n const deleteConfirmation = () => {\n confirmDelete({\n title: 'Delete comment',\n message: 'Are you sure you want to delete this comment?',\n accept: async () => {\n await handleDelete()\n },\n })\n }\n\n const [, setRefTooltip] = useReferenceTooltip()\n\n const mappedReactions = useMemo(\n () => mapGraphQLReactions(activity.reactions, userName),\n [[...(activity.reactions || [])]],\n )\n\n const reactionChangeHandler = (reaction: Reaction) => {\n if (reaction.isActive) {\n createReaction({\n projectName: projectName,\n // @ts-ignore exposed endpoint doesn't need the username, we still need to pass it for the optimistic update\n userName: userName,\n activityId: activityId,\n createReactionModel: {\n reaction: reaction.type,\n },\n })\n } else {\n deleteReaction({\n projectName: projectName,\n // @ts-ignore exposed endpoint doesn't need the username, we still need to pass it for the optimistic update\n userName: userName,\n activityId: activityId,\n reaction: reaction.type,\n })\n }\n }\n\n const onAnnotationClick = useCallback(\n (file: any) => {\n if (!file.annotation) return\n // annotation frame numbers are 1-based\n onGoToFrame?.((file.annotation as SavedAnnotationMetadata).range[0] - 1)\n },\n [onGoToFrame],\n )\n\n return (\n <>\n <Styled.Comment\n className={clsx('comment', { isOwner, isEditing, isHighlighted })}\n id={activityId}\n >\n <ActivityHeader\n name={authorName}\n fullName={authorFullName}\n date={createdAt}\n isRef={isRef}\n activity={activity}\n // projectInfo={projectInfo}\n projectName={projectName}\n entityType={entityType}\n onReferenceClick={onReferenceClick}\n onReferenceTooltip={setRefTooltip}\n children={undefined}\n />\n <Styled.Body className={clsx('comment-body', { isEditing })}>\n {!readOnly && (\n <Styled.Tools className={'tools'}>\n {isOwner && onDelete && (\n <Styled.ToolButton\n icon=\"delete\"\n onClick={deleteConfirmation}\n tooltip=\"Delete comment\"\n />\n )}\n {isOwner && handleEditComment && (\n <Styled.ToolButton icon=\"edit_square\" onClick={handleEditComment} />\n )}\n </Styled.Tools>\n )}\n {isEditing ? (\n <CommentInput\n initValue={body}\n initFiles={files}\n isEditing\n onClose={handleEditCancel}\n onSubmit={handleSave}\n isOpen={true}\n {...editProps}\n />\n ) : (\n <>\n <CommentWrapper>\n <ReactMarkdown\n remarkPlugins={[remarkGfm, emoji, remarkDirective, remarkDirectiveRehype]}\n urlTransform={(url) => url}\n components={{\n // a links\n // @ts-ignore\n a: (props) =>\n // @ts-ignore\n aTag(props, {\n entityId,\n projectName,\n projectInfo,\n onReferenceClick,\n onReferenceTooltip: setRefTooltip,\n activityId,\n }),\n // checkbox inputs\n // @ts-ignore\n input: (props) => inputTag(props, { activity, onCheckChange }),\n // code syntax highlighting\n // eslint-disable-next-line\n // @ts-ignore\n code: (props) => codeTag(props),\n // @ts-ignore\n blockquote: (props) => blockquoteTag(props),\n // @ts-ignore\n tip: (props) => (\n <Styled.Tip>\n <Icon icon=\"info\" />\n {props.children}\n </Styled.Tip>\n ),\n // @ts-ignore\n status: (props) => {\n return (\n <ActivityStatus name={props.id} statuses={statuses}>\n {props.children}\n </ActivityStatus>\n )\n },\n }}\n >\n {body}\n </ReactMarkdown>\n </CommentWrapper>\n {/* file uploads */}\n {/* @ts-ignore */}\n <FilesGrid\n files={files}\n isCompact={files.length > 6}\n activityId={activityId}\n projectName={projectName}\n isDownloadable\n onExpand={onFileExpand}\n onAnnotationClick={onAnnotationClick}\n onRemove={undefined}\n />\n </>\n )}\n\n {!isEditing && (\n <div style={{ marginTop: '16px' }}>\n {mappedReactions && (\n <Reactions\n reactions={mappedReactions}\n changeHandler={reactionChangeHandler}\n readOnly={readOnly}\n />\n )}\n </div>\n )}\n </Styled.Body>\n </Styled.Comment>\n </>\n )\n}\n\nexport default ActivityComment\n"],"names":["useFeedContext","useDetailsPanelContext","files","getTextRefs","confirmDelete","useMemo","mapGraphQLReactions","useCallback","jsx","Fragment","jsxs","Styled.Comment","Styled.Body","Styled.Tools","Styled.ToolButton","CommentInput","aTag","inputTag","codeTag","blockquoteTag","Styled.Tip","Icon"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { j as jsxRuntimeExports } from "../../../../../../_virtual/jsx-runtime.es.js";
|
|
2
2
|
import clsx from "clsx";
|
|
3
|
-
import { useMemo } from "react";
|
|
3
|
+
import { useMemo, useCallback } from "react";
|
|
4
4
|
import ReactMarkdown from "react-markdown";
|
|
5
5
|
import emoji from "remark-emoji";
|
|
6
6
|
import remarkGfm from "remark-gfm";
|
|
@@ -22,6 +22,15 @@ import { confirmDelete } from "../../../../util/confirmDelete.es.js";
|
|
|
22
22
|
import "react-toastify";
|
|
23
23
|
import "../../../../util/pubsub.es.js";
|
|
24
24
|
import ActivityHeader from "../ActivityHeader/ActivityHeader.es.js";
|
|
25
|
+
import "../../../../context/RemoteModulesContext.es.js";
|
|
26
|
+
import { useDetailsPanelContext } from "../../../../context/DetailsPanelContext.es.js";
|
|
27
|
+
import "../../../../context/ThumbnailUploaderContext.es.js";
|
|
28
|
+
import "../../../../context/SettingsPanelContext.es.js";
|
|
29
|
+
import "../../../../context/pip/PiPProvider.es.js";
|
|
30
|
+
import "react-dom";
|
|
31
|
+
import "../../../../context/pip/PiPWrapper.es.js";
|
|
32
|
+
import "../../../../context/AddonProjectContext.es.js";
|
|
33
|
+
import "../../../../context/AddonContext.es.js";
|
|
25
34
|
const ActivityComment = ({
|
|
26
35
|
activity = {},
|
|
27
36
|
onCheckChange,
|
|
@@ -55,6 +64,7 @@ const ActivityComment = ({
|
|
|
55
64
|
if (!authorName) authorName = (author == null ? void 0 : author.name) || "";
|
|
56
65
|
if (!authorFullName) authorFullName = (author == null ? void 0 : author.fullName) || authorName;
|
|
57
66
|
const { editingId, setEditingId } = useFeedContext();
|
|
67
|
+
const { onGoToFrame } = useDetailsPanelContext();
|
|
58
68
|
const handleEditComment = () => {
|
|
59
69
|
setEditingId(activityId);
|
|
60
70
|
};
|
|
@@ -109,6 +119,13 @@ const ActivityComment = ({
|
|
|
109
119
|
});
|
|
110
120
|
}
|
|
111
121
|
};
|
|
122
|
+
const onAnnotationClick = useCallback(
|
|
123
|
+
(file) => {
|
|
124
|
+
if (!file.annotation) return;
|
|
125
|
+
onGoToFrame == null ? void 0 : onGoToFrame(file.annotation.range[0] - 1);
|
|
126
|
+
},
|
|
127
|
+
[onGoToFrame]
|
|
128
|
+
);
|
|
112
129
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
113
130
|
Comment,
|
|
114
131
|
{
|
|
@@ -203,6 +220,7 @@ const ActivityComment = ({
|
|
|
203
220
|
projectName,
|
|
204
221
|
isDownloadable: true,
|
|
205
222
|
onExpand: onFileExpand,
|
|
223
|
+
onAnnotationClick,
|
|
206
224
|
onRemove: void 0
|
|
207
225
|
}
|
|
208
226
|
)
|
package/dist/shared/src/containers/Feed/components/ActivityComment/ActivityComment.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActivityComment.es.js","sources":["../../../../../../../src/containers/Feed/components/ActivityComment/ActivityComment.tsx"],"sourcesContent":["import clsx from 'clsx'\nimport { useMemo } from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport emoji from 'remark-emoji'\nimport remarkGfm from 'remark-gfm'\nimport remarkDirective from 'remark-directive'\nimport remarkDirectiveRehype from 'remark-directive-rehype'\n\nimport CommentInput from '../CommentInput/CommentInput'\nimport Reactions from '../ReactionContainer/Reactions'\nimport { Reaction } from '../ReactionContainer/types'\nimport useReferenceTooltip from '../../hooks/useReferenceTooltip'\nimport FilesGrid, { FilesGridProps } from '../FilesGrid/FilesGrid'\n\nimport { getTextRefs } from '../CommentInput/quillToMarkdown'\nimport * as Styled from './ActivityComment.styled'\nimport CommentWrapper from './CommentWrapper'\nimport { aTag, blockquoteTag, codeTag, inputTag } from './ActivityMarkdownComponents'\nimport { mapGraphQLReactions } from './mappers'\nimport { Icon } from '@ynput/ayon-react-components'\nimport ActivityStatus from '../ActivityStatus/ActivityStatus'\nimport { useFeedContext } from '../../context/FeedContext'\nimport { confirmDelete } from '../../../../util'\nimport ActivityHeader, { ActivityHeaderProps } from '../ActivityHeader/ActivityHeader'\nimport type { Status } from '../../../ProjectTreeTable/types/project'\n\ntype Props = {\n activity: any\n onCheckChange?: Function\n onDelete?: (activityId: string, entityId: string, refs: any) => Promise<void>\n onUpdate?: Function\n projectInfo: any\n editProps?: {\n disabled: boolean\n isLoading: boolean\n }\n projectName: string\n entityType: string\n onReferenceClick?: ActivityHeaderProps['onReferenceClick']\n onFileExpand?: FilesGridProps['onExpand']\n showOrigin?: boolean\n isHighlighted?: boolean\n readOnly?: boolean\n statuses: Status[]\n}\n\nconst ActivityComment = ({\n activity = {},\n onCheckChange,\n onDelete,\n onUpdate,\n projectInfo,\n editProps,\n projectName,\n entityType,\n onReferenceClick,\n onFileExpand,\n showOrigin,\n isHighlighted,\n readOnly,\n statuses = [],\n}: Props) => {\n const { userName, createReaction, deleteReaction } = useFeedContext()\n\n let {\n body,\n authorName,\n authorFullName,\n createdAt,\n referenceType,\n entityId,\n activityId,\n author,\n isOwner,\n files = [],\n origin,\n } = activity\n if (!authorName) authorName = author?.name || ''\n if (!authorFullName) authorFullName = author?.fullName || authorName\n\n const { editingId, setEditingId } = useFeedContext()\n\n const handleEditComment = () => {\n setEditingId(activityId)\n }\n\n const handleEditCancel = () => {\n // close the edit comment\n setEditingId(null)\n }\n\n const handleSave = async (value: any, files: any) => {\n await onUpdate?.(value, files)\n setEditingId(null)\n }\n\n const isEditing = editingId === activityId\n\n const isRef = referenceType !== 'origin' || showOrigin\n\n const handleDelete = async () => {\n const refs = getTextRefs(body)\n\n // if the comment is a reference, (it's origin is not the entity)\n // we need to delete the reference from the origin as well\n // add it to the refs to delete\n if (isRef && origin) {\n refs.push({ id: origin.id, type: origin.type })\n }\n\n // note: body is used to match other refs to delete\n onDelete && (await onDelete(activityId, entityId, refs))\n }\n\n const deleteConfirmation = () => {\n confirmDelete({\n title: 'Delete comment',\n message: 'Are you sure you want to delete this comment?',\n accept: async () => {\n await handleDelete()\n },\n })\n }\n\n const [, setRefTooltip] = useReferenceTooltip()\n\n const mappedReactions = useMemo(\n () => mapGraphQLReactions(activity.reactions, userName),\n [[...(activity.reactions || [])]],\n )\n\n const reactionChangeHandler = (reaction: Reaction) => {\n if (reaction.isActive) {\n createReaction({\n projectName: projectName,\n // @ts-ignore exposed endpoint doesn't need the username, we still need to pass it for the optimistic update\n userName: userName,\n activityId: activityId,\n createReactionModel: {\n reaction: reaction.type,\n },\n })\n } else {\n deleteReaction({\n projectName: projectName,\n // @ts-ignore exposed endpoint doesn't need the username, we still need to pass it for the optimistic update\n userName: userName,\n activityId: activityId,\n reaction: reaction.type,\n })\n }\n }\n\n return (\n <>\n <Styled.Comment\n className={clsx('comment', { isOwner, isEditing, isHighlighted })}\n id={activityId}\n >\n <ActivityHeader\n name={authorName}\n fullName={authorFullName}\n date={createdAt}\n isRef={isRef}\n activity={activity}\n // projectInfo={projectInfo}\n projectName={projectName}\n entityType={entityType}\n onReferenceClick={onReferenceClick}\n onReferenceTooltip={setRefTooltip}\n children={undefined}\n />\n <Styled.Body className={clsx('comment-body', { isEditing })}>\n {!readOnly && (\n <Styled.Tools className={'tools'}>\n {isOwner && onDelete && (\n <Styled.ToolButton\n icon=\"delete\"\n onClick={deleteConfirmation}\n tooltip=\"Delete comment\"\n />\n )}\n {isOwner && handleEditComment && (\n <Styled.ToolButton icon=\"edit_square\" onClick={handleEditComment} />\n )}\n </Styled.Tools>\n )}\n {isEditing ? (\n <CommentInput\n initValue={body}\n initFiles={files}\n isEditing\n onClose={handleEditCancel}\n onSubmit={handleSave}\n isOpen={true}\n {...editProps}\n />\n ) : (\n <>\n <CommentWrapper>\n <ReactMarkdown\n remarkPlugins={[remarkGfm, emoji, remarkDirective, remarkDirectiveRehype]}\n urlTransform={(url) => url}\n components={{\n // a links\n // @ts-ignore\n a: (props) =>\n // @ts-ignore\n aTag(props, {\n entityId,\n projectName,\n projectInfo,\n onReferenceClick,\n onReferenceTooltip: setRefTooltip,\n activityId,\n }),\n // checkbox inputs\n // @ts-ignore\n input: (props) => inputTag(props, { activity, onCheckChange }),\n // code syntax highlighting\n // eslint-disable-next-line\n // @ts-ignore\n code: (props) => codeTag(props),\n // @ts-ignore\n blockquote: (props) => blockquoteTag(props),\n // @ts-ignore\n tip: (props) => (\n <Styled.Tip>\n <Icon icon=\"info\" />\n {props.children}\n </Styled.Tip>\n ),\n // @ts-ignore\n status: (props) => {\n return (\n <ActivityStatus name={props.id} statuses={statuses}>\n {props.children}\n </ActivityStatus>\n )\n },\n }}\n >\n {body}\n </ReactMarkdown>\n </CommentWrapper>\n {/* file uploads */}\n {/* @ts-ignore */}\n <FilesGrid\n files={files}\n isCompact={files.length > 6}\n activityId={activityId}\n projectName={projectName}\n isDownloadable\n onExpand={onFileExpand}\n onRemove={undefined}\n />\n </>\n )}\n\n {!isEditing && (\n <div style={{ marginTop: '16px' }}>\n {mappedReactions && (\n <Reactions\n reactions={mappedReactions}\n changeHandler={reactionChangeHandler}\n readOnly={readOnly}\n />\n )}\n </div>\n )}\n </Styled.Body>\n </Styled.Comment>\n </>\n )\n}\n\nexport default ActivityComment\n"],"names":["files","jsx","Fragment","jsxs","Styled.Comment","Styled.Body","Styled.Tools","Styled.ToolButton","Styled.Tip"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ActivityComment.es.js","sources":["../../../../../../../src/containers/Feed/components/ActivityComment/ActivityComment.tsx"],"sourcesContent":["import clsx from 'clsx'\nimport { useCallback, useMemo } from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport emoji from 'remark-emoji'\nimport remarkGfm from 'remark-gfm'\nimport remarkDirective from 'remark-directive'\nimport remarkDirectiveRehype from 'remark-directive-rehype'\n\nimport CommentInput from '../CommentInput/CommentInput'\nimport Reactions from '../ReactionContainer/Reactions'\nimport { Reaction } from '../ReactionContainer/types'\nimport useReferenceTooltip from '../../hooks/useReferenceTooltip'\nimport FilesGrid, { FilesGridProps } from '../FilesGrid/FilesGrid'\n\nimport { getTextRefs } from '../CommentInput/quillToMarkdown'\nimport * as Styled from './ActivityComment.styled'\nimport CommentWrapper from './CommentWrapper'\nimport { aTag, blockquoteTag, codeTag, inputTag } from './ActivityMarkdownComponents'\nimport { mapGraphQLReactions } from './mappers'\nimport { Icon } from '@ynput/ayon-react-components'\nimport ActivityStatus from '../ActivityStatus/ActivityStatus'\nimport { useFeedContext } from '../../context/FeedContext'\nimport { confirmDelete } from '../../../../util'\nimport ActivityHeader, { ActivityHeaderProps } from '../ActivityHeader/ActivityHeader'\nimport type { Status } from '../../../ProjectTreeTable/types/project'\nimport { SavedAnnotationMetadata } from '../../index'\nimport { useDetailsPanelContext } from '@shared/context'\n\ntype Props = {\n activity: any\n onCheckChange?: Function\n onDelete?: (activityId: string, entityId: string, refs: any) => Promise<void>\n onUpdate?: Function\n projectInfo: any\n editProps?: {\n disabled: boolean\n isLoading: boolean\n }\n projectName: string\n entityType: string\n onReferenceClick?: ActivityHeaderProps['onReferenceClick']\n onFileExpand?: FilesGridProps['onExpand']\n showOrigin?: boolean\n isHighlighted?: boolean\n readOnly?: boolean\n statuses: Status[]\n}\n\nconst ActivityComment = ({\n activity = {},\n onCheckChange,\n onDelete,\n onUpdate,\n projectInfo,\n editProps,\n projectName,\n entityType,\n onReferenceClick,\n onFileExpand,\n showOrigin,\n isHighlighted,\n readOnly,\n statuses = [],\n}: Props) => {\n const { userName, createReaction, deleteReaction } = useFeedContext()\n\n let {\n body,\n authorName,\n authorFullName,\n createdAt,\n referenceType,\n entityId,\n activityId,\n author,\n isOwner,\n files = [],\n origin,\n } = activity\n if (!authorName) authorName = author?.name || ''\n if (!authorFullName) authorFullName = author?.fullName || authorName\n\n const { editingId, setEditingId } = useFeedContext()\n const { onGoToFrame } = useDetailsPanelContext()\n\n const handleEditComment = () => {\n setEditingId(activityId)\n }\n\n const handleEditCancel = () => {\n // close the edit comment\n setEditingId(null)\n }\n\n const handleSave = async (value: any, files: any) => {\n await onUpdate?.(value, files)\n setEditingId(null)\n }\n\n const isEditing = editingId === activityId\n\n const isRef = referenceType !== 'origin' || showOrigin\n\n const handleDelete = async () => {\n const refs = getTextRefs(body)\n\n // if the comment is a reference, (it's origin is not the entity)\n // we need to delete the reference from the origin as well\n // add it to the refs to delete\n if (isRef && origin) {\n refs.push({ id: origin.id, type: origin.type })\n }\n\n // note: body is used to match other refs to delete\n onDelete && (await onDelete(activityId, entityId, refs))\n }\n\n const deleteConfirmation = () => {\n confirmDelete({\n title: 'Delete comment',\n message: 'Are you sure you want to delete this comment?',\n accept: async () => {\n await handleDelete()\n },\n })\n }\n\n const [, setRefTooltip] = useReferenceTooltip()\n\n const mappedReactions = useMemo(\n () => mapGraphQLReactions(activity.reactions, userName),\n [[...(activity.reactions || [])]],\n )\n\n const reactionChangeHandler = (reaction: Reaction) => {\n if (reaction.isActive) {\n createReaction({\n projectName: projectName,\n // @ts-ignore exposed endpoint doesn't need the username, we still need to pass it for the optimistic update\n userName: userName,\n activityId: activityId,\n createReactionModel: {\n reaction: reaction.type,\n },\n })\n } else {\n deleteReaction({\n projectName: projectName,\n // @ts-ignore exposed endpoint doesn't need the username, we still need to pass it for the optimistic update\n userName: userName,\n activityId: activityId,\n reaction: reaction.type,\n })\n }\n }\n\n const onAnnotationClick = useCallback(\n (file: any) => {\n if (!file.annotation) return\n // annotation frame numbers are 1-based\n onGoToFrame?.((file.annotation as SavedAnnotationMetadata).range[0] - 1)\n },\n [onGoToFrame],\n )\n\n return (\n <>\n <Styled.Comment\n className={clsx('comment', { isOwner, isEditing, isHighlighted })}\n id={activityId}\n >\n <ActivityHeader\n name={authorName}\n fullName={authorFullName}\n date={createdAt}\n isRef={isRef}\n activity={activity}\n // projectInfo={projectInfo}\n projectName={projectName}\n entityType={entityType}\n onReferenceClick={onReferenceClick}\n onReferenceTooltip={setRefTooltip}\n children={undefined}\n />\n <Styled.Body className={clsx('comment-body', { isEditing })}>\n {!readOnly && (\n <Styled.Tools className={'tools'}>\n {isOwner && onDelete && (\n <Styled.ToolButton\n icon=\"delete\"\n onClick={deleteConfirmation}\n tooltip=\"Delete comment\"\n />\n )}\n {isOwner && handleEditComment && (\n <Styled.ToolButton icon=\"edit_square\" onClick={handleEditComment} />\n )}\n </Styled.Tools>\n )}\n {isEditing ? (\n <CommentInput\n initValue={body}\n initFiles={files}\n isEditing\n onClose={handleEditCancel}\n onSubmit={handleSave}\n isOpen={true}\n {...editProps}\n />\n ) : (\n <>\n <CommentWrapper>\n <ReactMarkdown\n remarkPlugins={[remarkGfm, emoji, remarkDirective, remarkDirectiveRehype]}\n urlTransform={(url) => url}\n components={{\n // a links\n // @ts-ignore\n a: (props) =>\n // @ts-ignore\n aTag(props, {\n entityId,\n projectName,\n projectInfo,\n onReferenceClick,\n onReferenceTooltip: setRefTooltip,\n activityId,\n }),\n // checkbox inputs\n // @ts-ignore\n input: (props) => inputTag(props, { activity, onCheckChange }),\n // code syntax highlighting\n // eslint-disable-next-line\n // @ts-ignore\n code: (props) => codeTag(props),\n // @ts-ignore\n blockquote: (props) => blockquoteTag(props),\n // @ts-ignore\n tip: (props) => (\n <Styled.Tip>\n <Icon icon=\"info\" />\n {props.children}\n </Styled.Tip>\n ),\n // @ts-ignore\n status: (props) => {\n return (\n <ActivityStatus name={props.id} statuses={statuses}>\n {props.children}\n </ActivityStatus>\n )\n },\n }}\n >\n {body}\n </ReactMarkdown>\n </CommentWrapper>\n {/* file uploads */}\n {/* @ts-ignore */}\n <FilesGrid\n files={files}\n isCompact={files.length > 6}\n activityId={activityId}\n projectName={projectName}\n isDownloadable\n onExpand={onFileExpand}\n onAnnotationClick={onAnnotationClick}\n onRemove={undefined}\n />\n </>\n )}\n\n {!isEditing && (\n <div style={{ marginTop: '16px' }}>\n {mappedReactions && (\n <Reactions\n reactions={mappedReactions}\n changeHandler={reactionChangeHandler}\n readOnly={readOnly}\n />\n )}\n </div>\n )}\n </Styled.Body>\n </Styled.Comment>\n </>\n )\n}\n\nexport default ActivityComment\n"],"names":["files","jsx","Fragment","jsxs","Styled.Comment","Styled.Body","Styled.Tools","Styled.ToolButton","Styled.Tip"],"mappings":"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"}
|
|
@@ -271,8 +271,8 @@ const CommentInput = ({
|
|
|
271
271
|
setFilesUploading((prev) => prev.filter((uploading) => uploading.name !== file.name));
|
|
272
272
|
return newFile;
|
|
273
273
|
};
|
|
274
|
-
const handleFileRemove = (id, name,
|
|
275
|
-
if (
|
|
274
|
+
const handleFileRemove = (id, name, isUnsavedAnnotation) => {
|
|
275
|
+
if (isUnsavedAnnotation) {
|
|
276
276
|
removeAnnotation == null ? void 0 : removeAnnotation(id);
|
|
277
277
|
} else {
|
|
278
278
|
setFiles((prev) => prev.filter((file) => file.id !== id));
|
|
@@ -313,15 +313,18 @@ const CommentInput = ({
|
|
|
313
313
|
try {
|
|
314
314
|
setIsSubmitting(true);
|
|
315
315
|
let annotationFiles = [];
|
|
316
|
+
let annotationMetadata = [];
|
|
316
317
|
if (annotations.length) {
|
|
317
|
-
|
|
318
|
+
const { files: files2, metadata } = await uploadAnnotations(annotations);
|
|
319
|
+
annotationFiles = files2;
|
|
320
|
+
annotationMetadata = metadata;
|
|
318
321
|
}
|
|
319
322
|
const [markdown] = quillToMarkdown.convertToMarkdown(editorValue);
|
|
320
323
|
const markdownParsed = helpers.parseImages(markdown);
|
|
321
324
|
const uploadedFiles = [...files, ...annotationFiles];
|
|
322
325
|
if ((markdownParsed || uploadedFiles.length) && onSubmit) {
|
|
323
326
|
try {
|
|
324
|
-
await onSubmit(markdownParsed, uploadedFiles);
|
|
327
|
+
await onSubmit(markdownParsed, uploadedFiles, { annotations: annotationMetadata });
|
|
325
328
|
setEditorValue("");
|
|
326
329
|
setFiles([]);
|
|
327
330
|
} catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommentInput.cjs.js","sources":["../../../../../../../src/containers/Feed/components/CommentInput/CommentInput.tsx"],"sourcesContent":["// React and related hooks\nimport React, { FC, useEffect, useMemo, useRef, useState } from 'react'\n\n// Third-party libraries\nimport clsx from 'clsx'\nimport { toast } from 'react-toastify'\nimport ReactQuill, { Quill } from 'react-quill-ayon'\n\n// Components\nimport { Button, Icon, SaveButton } from '@ynput/ayon-react-components'\nimport CommentMentionSelect from '../CommentMentionSelect/CommentMentionSelect'\nimport InputMarkdownConvert from './InputMarkdownConvert'\nimport FilesGrid from '../FilesGrid'\n\n// Styled components\nimport * as Styled from './CommentInput.styled'\n\n// Helpers and utilities\nimport getMentionOptions from '../../mentionHelpers/getMentionOptions'\nimport getMentionUsers from '../../mentionHelpers/getMentionUsers'\nimport getMentionTasks from '../../mentionHelpers/getMentionTasks'\nimport getMentionVersions from '../../mentionHelpers/getMentionVersions'\nimport { convertToMarkdown } from './quillToMarkdown'\nimport { handleFileDrop, parseImages, typeWithDelay } from './helpers'\nimport { getModules, quillFormats } from './modules'\n\n// Hooks\nimport useInitialValue from './hooks/useInitialValue'\nimport useSetCursorEnd from './hooks/useSetCursorEnd'\nimport useMentionLink from './hooks/useMentionLink'\nimport useAnnotationsSync from './hooks/useAnnotationsSync'\n\n// State management\nimport useAnnotationsUpload from './hooks/useAnnotationsUpload'\nimport { useFeedContext } from '../../context/FeedContext'\n\nvar Delta = Quill.import('delta')\n\nconst mentionTypes = ['@', '@@', '@@@']\nexport const mentionTypeOptions = {\n '@@@': {\n id: 'task',\n },\n '@@': {\n id: 'version',\n },\n '@': {\n id: 'user',\n isCircle: true,\n },\n}\n\ninterface CommentInputProps {\n initValue: string | null\n initFiles?: any[]\n onSubmit: (markdown: string, files: any[]) => Promise<void>\n isEditing?: boolean\n disabled?: boolean\n isLoading?: boolean\n isOpen: boolean\n onOpen?: () => void\n onClose?: () => void\n}\n\nconst CommentInput: FC<CommentInputProps> = ({\n initValue,\n initFiles = [],\n onSubmit,\n isEditing,\n disabled,\n isLoading,\n isOpen,\n onOpen,\n onClose,\n}) => {\n const { projectName, entities, projectInfo, scope, currentTab, mentionSuggestionsData } =\n useFeedContext()\n\n const {\n users: mentionUsers,\n versions: mentionVersions,\n tasks: mentionTasks,\n } = mentionSuggestionsData || {}\n\n const [initHeight, setInitHeight] = useState(88)\n const [editorValue, setEditorValue] = useState('')\n // file uploads\n const [files, setFiles] = useState(initFiles)\n const [filesUploading, setFilesUploading] = useState([])\n const [isDropping, setIsDropping] = useState(false)\n const [isSubmitting, setIsSubmitting] = useState(false)\n\n const { annotations, removeAnnotation, goToAnnotation } = useAnnotationsSync({\n entityId: entities[0]?.id,\n filesUploading,\n })\n\n // MENTION STATES\n const [mention, setMention] = useState<null | any>(null)\n const [mentionSelectedIndex, setMentionSelectedIndex] = useState(0)\n // REFS\n const editorRef = useRef<any>(null)\n const markdownRef = useRef<HTMLDivElement>(null)\n\n // if there is an initial value, set it so the editor is prefilled\n useInitialValue({\n markdownRef,\n initValue,\n setEditorValue,\n setInitHeight,\n isOpen: isOpen,\n filter: currentTab,\n })\n\n // When editing, set selection to the end of the editor\n useSetCursorEnd({ initHeight, editorRef, isEditing })\n // create a new quill format for mentions and registers it\n useMentionLink({ projectName })\n\n // focus on editor when opened\n useEffect(() => {\n if (isOpen) {\n editorRef.current?.getEditor()?.enable()\n // block autofocus if opened from an annotation\n if (annotations.length > 0 && files.length === 0) {\n return\n }\n\n editorRef.current?.focus()\n }\n // We don't set annotations or files as useEffect dependencies, because we don't want to focus\n // the input if it's already open but annotations change (e.g. are removed).\n }, [isOpen, editorRef])\n\n mentionTypes.sort((a, b) => b.length - a.length)\n\n const mentionOptions = useMemo(\n () =>\n getMentionOptions(\n mention?.type,\n {\n '@': () => getMentionUsers(mentionUsers),\n '@@': () => getMentionVersions(mentionVersions),\n '@@@': () => getMentionTasks(mentionTasks, projectInfo.taskTypes),\n },\n mention?.search,\n ),\n [mentionTasks, mentionVersions, mentionUsers, mention?.type, mention?.search],\n )\n\n // show first 5 and filter itself out\n const shownMentionOptions = mentionOptions.slice(0, 5)\n\n // triggered when a mention is selected\n const [newSelection, setNewSelection] = useState<null | number>()\n\n useEffect(() => {\n if (newSelection) {\n setNewSelection(null)\n // now we set selection to the end of the mention\n const quill = editorRef.current.getEditor()\n quill.setSelection(newSelection)\n }\n }, [newSelection])\n\n const handleSelectMention = (selectedOption: any) => {\n // get option text\n const quill = editorRef.current.getEditor()\n\n const typePrefix = mention.type // the type of mention: @, @@, @@@\n const search = typePrefix + (mention.search || '') // the full search string: @Tim\n const mentionLabel = typePrefix + selectedOption.label // the label of the mention: @Tim Bailey\n // @ts-expect-error\n const type = mentionTypeOptions[typePrefix] // the type of mention: user, version, task\n const href = `${type?.id}:${selectedOption.id}` // the href of the mention: user:user.123\n\n // get selection delta\n const selection = quill.getSelection(true)\n const selectionIndex = selection?.index || 0\n const startIndex = selectionIndex - search.length // the start index of the search\n\n // first delete the search string\n quill.deleteText(startIndex, search.length)\n\n // insert embed link\n quill.insertText(startIndex, mentionLabel, 'mention', href)\n\n const endIndex = startIndex + mentionLabel.length\n\n // insert a space after the mention\n quill.updateContents(new Delta().retain(endIndex).insert(' '))\n\n // remove single \\n after mention\n quill.updateContents(new Delta().retain(endIndex + 1).delete(1))\n\n // set selection to the end of the mention + 1\n setNewSelection(endIndex + 1)\n\n // reset mention state\n setMention(null)\n setMentionSelectedIndex(0)\n }\n\n const handleSelectChange = (option: any) => {\n handleSelectMention(option)\n }\n\n const handleChange = (content: string, delta: any, _: any, editor: any) => {\n let currentCharacter =\n (delta.ops[0] && delta.ops[0].insert) || (delta.ops[1] && delta.ops[1].insert)\n\n const tabOrEnter = currentCharacter === '\\n' || currentCharacter === '\\t'\n // find the first option\n const selectedOption = mentionOptions[mentionSelectedIndex]\n\n if (mention && tabOrEnter && selectedOption) {\n // get option text\n const retain = (delta.ops[0] && delta.ops[0].retain) || 0\n // prevent default\n\n // @ts-ignore\n handleSelectMention(selectedOption, retain)\n\n return\n }\n\n setEditorValue(content)\n\n const isDelete = delta.ops.length === 2 && !!delta.ops[1].delete\n\n if (!currentCharacter && isDelete) {\n currentCharacter = editor.getText(delta.ops[0].retain - 1, 1)\n }\n\n const isMention = mentionTypes.includes(currentCharacter)\n\n if (isMention) {\n const mentionIndex = delta.ops.findIndex((op: any) => 'insert' in op || 'delete' in op)\n const mention = currentCharacter\n let retain = mentionIndex === 0 ? 0 : delta.ops[mentionIndex - 1].retain\n if (isDelete) retain = retain - 1\n\n // for each mention denotation char, check if it is a mention\n // sort by length of mention denotation char\n let mentionMatch = null\n\n // loop through each mention denotation char, with longest first. First one to match is the one we want\n for (const chars of mentionTypes) {\n let isMatch = true\n // start with the last character\n if (chars.endsWith(mention)) {\n // loop through the chars backwards\n for (let i = chars.length - 1; i >= 0; i--) {\n // skip first character as that's already been checked\n if (i === 0) continue\n const char = chars[i - 1]\n const indexInDelta = retain - (chars.length - i)\n const valueCharAtIndex = editor.getText(indexInDelta, 1)\n if (valueCharAtIndex !== char) {\n isMatch = false\n break\n }\n }\n } else {\n isMatch = false\n }\n\n if (isMatch) {\n // console.log('match!!!', chars)\n mentionMatch = chars\n break\n }\n }\n\n if (mentionMatch) {\n setMention({\n type: mentionMatch,\n retain: retain,\n })\n } else {\n setMention(null)\n setMentionSelectedIndex(0)\n }\n } else {\n // get full string between mention and new delta\n // This is where SEARCH is handled\n if (mention) {\n const retain = delta.ops[0].retain\n // if space is pressed, remove mention\n if (currentCharacter === ' ' || !retain) {\n setMention(null)\n setMentionSelectedIndex(0)\n return\n }\n\n let distanceMentionToRetain = retain - mention.retain\n if (!isDelete) distanceMentionToRetain++\n const mentionFull = editor.getText(mention.retain, distanceMentionToRetain)\n const mentionSearch = mentionFull.replace(mention.type.slice(-1), '')\n // check for space in mentionFull\n if (mentionFull.includes(' ')) {\n setMention(null)\n setMentionSelectedIndex(0)\n } else {\n setMention({\n ...mention,\n search: mentionSearch?.toLowerCase(),\n })\n }\n } else {\n // just deleting any text\n const quill = editorRef.current.getEditor()\n const currentSelection = quill.getSelection(false)\n const currentFormat = quill.getFormat(currentSelection?.index, currentSelection?.length)\n if (currentFormat.mention) {\n // if format is mention, delete the whole mention\n const [lineBlock] = quill.getLine(currentSelection.index - 1) || []\n const ops = lineBlock?.cache?.delta?.ops || []\n // get last op with attributes mention: true\n const lastMentionOp = ops.reverse().find((op: any) => op.attributes?.mention)\n if (lastMentionOp) {\n const mentionLength = lastMentionOp.insert.length\n quill.deleteText(currentSelection.index - mentionLength, mentionLength)\n }\n }\n }\n }\n }\n\n const addTextToEditor = (type: string) => {\n // get editor retain\n const quill = editorRef.current.getEditor()\n\n let retain = quill.getSelection(true)?.index || 0\n\n // get character at retain\n const currentCharacter = quill.getText(retain - 1, 1)\n\n // if the current character is a character, increment retain\n const addSpace = currentCharacter !== ' ' && currentCharacter\n if (addSpace) {\n quill.insertText(retain, ' ')\n retain++\n }\n\n // This is hack AF, but it works\n typeWithDelay(quill, retain, type)\n }\n\n const handleMentionButton = (type: string) => {\n // first check if mention is already open\n if (mention) {\n const { type, retain, search = '' } = mention\n\n const quill = editorRef.current.getEditor()\n const length = type.length + search.length\n const start = retain - type.length + 1\n // delete the mention\n quill.deleteText(start, length)\n }\n\n addTextToEditor(type)\n }\n\n const handleOpenClick = () => {\n if (isOpen || disabled) return\n\n onOpen && onOpen()\n }\n\n const handleClose = () => {\n // get editor value\n const editor = editorRef.current.getEditor()\n const text = editor.getText()\n if (text.length < 2 || isEditing) {\n setEditorValue('')\n }\n\n // always close editor\n onClose && onClose()\n }\n\n const handleFileUploaded = ({ file, data }: any) => {\n const newFile = {\n id: data.id,\n name: file.name,\n mime: file.type,\n size: file.size,\n order: files.length,\n }\n\n setFiles((prev) => [...prev, newFile])\n // remove from uploading\n setFilesUploading((prev) => prev.filter((uploading: any) => uploading.name !== file.name))\n\n return newFile\n }\n\n const handleFileRemove = (id: string, name: string, isAnnotation: boolean) => {\n if (isAnnotation) {\n // remove from annotations (if it's an annotation)\n removeAnnotation?.(id)\n } else {\n // remove file from files\n setFiles((prev) => prev.filter((file) => file.id !== id))\n // remove from uploading\n setFilesUploading((prev) => {\n return prev.filter((file: any) => file.name !== name)\n })\n }\n }\n\n const handleFileProgress = (e: any, file: any) => {\n const progress = Math.round((e.loaded * 100) / e.total)\n if (progress !== 100) {\n const uploadProgress = {\n name: file.name,\n progress,\n type: file.type,\n order: files.length + filesUploading.length,\n }\n\n // @ts-ignore\n setFilesUploading((prev) => {\n // replace or add new progress\n const newProgress = prev.filter((name: any) => name.name !== file.name)\n return [...newProgress, uploadProgress]\n })\n }\n }\n\n // when a file is not dropped onto the comment input\n const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {\n setIsDropping(false)\n // upload file\n handleFileDrop(e, projectName, handleFileProgress, handleFileUploaded)\n }\n\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n e.stopPropagation()\n setIsDropping(true)\n }\n\n const uploadAnnotations = useAnnotationsUpload({\n projectName,\n onSuccess: handleFileUploaded,\n })\n\n const handleSubmit = async () => {\n try {\n setIsSubmitting(true)\n // upload any annotations first\n let annotationFiles = []\n if (annotations.length) {\n annotationFiles = await uploadAnnotations(annotations)\n }\n\n // convert to markdown\n const [markdown] = convertToMarkdown(editorValue)\n\n // remove img query params\n const markdownParsed = parseImages(markdown)\n\n const uploadedFiles = [...files, ...annotationFiles]\n\n if ((markdownParsed || uploadedFiles.length) && onSubmit) {\n try {\n await onSubmit(markdownParsed, uploadedFiles)\n // only clear if onSubmit is successful\n setEditorValue('')\n setFiles([])\n } catch (error) {\n // error is handled in rtk query mutation\n return\n }\n }\n } catch (error) {\n console.error(error)\n toast.error('Something went wrong')\n } finally {\n setIsSubmitting(false)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (mention) {\n // close mention on escape\n if (e.key === 'Escape') {\n setMention(null)\n setMentionSelectedIndex(0)\n return\n }\n\n // add top search of mention\n if (mention && e.key === 'Tab') {\n // we handle this in the onChange\n }\n\n const arrowDirection = e.key === 'ArrowUp' ? -1 : e.key === 'ArrowDown' ? 1 : 0\n\n if (arrowDirection) {\n // navigate through mentions\n e.preventDefault()\n let newIndex = mentionSelectedIndex + arrowDirection\n if (newIndex < 0) newIndex = shownMentionOptions.length - 1\n if (newIndex >= shownMentionOptions.length) newIndex = 0\n setMentionSelectedIndex(newIndex)\n }\n\n if (e.key === 'Enter') {\n // we handle this in the onChange\n }\n }\n\n if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {\n handleSubmit()\n }\n\n if (e.key === 'Escape') {\n handleClose()\n }\n }\n\n let quillMinHeight: number | undefined = isOpen ? initHeight + 41 : 44\n if (isEditing) quillMinHeight = undefined\n\n // QUILL CONFIG\n const modules = useMemo(\n () =>\n getModules({\n imageUploader: {\n projectName,\n onUpload: handleFileUploaded,\n onUploadProgress: handleFileProgress,\n },\n }),\n [projectName, setFiles, setFilesUploading],\n )\n\n const allFiles = [...annotations, ...(files || []), ...filesUploading].sort(\n (a, b) => a.order - b.order,\n )\n const compactGrid = allFiles.length > 6\n\n // disable version mentions for folders\n let mentionsError = null\n if (entities.length && entities[0].entityType === 'folder') {\n if (mention?.type === '@@') {\n mentionsError = 'Version mentions are disabled for folders'\n }\n }\n\n return (\n <>\n <Styled.AutoHeight\n className={clsx('comment-container', { isOpen, isEditing })}\n onDragOver={handleDragOver}\n onDragLeave={() => setIsDropping(false)}\n onDrop={handleDrop}\n onClick={() => setIsDropping(false)}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <Styled.Comment\n className={clsx('block-shortcuts', {\n isOpen,\n isClosed: !isOpen || disabled,\n isEditing,\n isDropping,\n disabled,\n isLoading,\n isSubmitting,\n })}\n onKeyDown={handleKeyDown}\n onClick={handleOpenClick}\n >\n <Styled.Markdown ref={markdownRef}>\n {/* this is purely used to translate the markdown into html for Editor */}\n <InputMarkdownConvert typeOptions={mentionTypeOptions} initValue={initValue} />\n </Styled.Markdown>\n\n {/* file uploads */}\n {isOpen && (\n <FilesGrid\n files={allFiles}\n isCompact={compactGrid}\n onRemove={handleFileRemove}\n style={{ borderBottom: '1px solid var(--md-sys-color-outline-variant)' }}\n projectName={projectName}\n onAnnotationClick={goToAnnotation}\n />\n )}\n {isOpen && !disabled ? (\n <ReactQuill\n theme=\"snow\"\n style={{ minHeight: quillMinHeight, maxHeight: 300 }}\n ref={editorRef}\n value={editorValue}\n onChange={handleChange}\n readOnly={!isOpen}\n placeholder={'Comment or mention with @user, @@version, @@@task...'}\n modules={modules}\n formats={quillFormats}\n />\n ) : (\n <Styled.Placeholder>\n {disabled ? 'Commenting is disabled across multiple projects.' : 'Add a comment...'}\n </Styled.Placeholder>\n )}\n\n <Styled.Footer>\n <Styled.Buttons>\n {/* mention a user */}\n <Button\n icon=\"person\"\n variant=\"text\"\n onClick={() => handleMentionButton('@')}\n data-tooltip={'Mention user'}\n data-shortcut={'@'}\n />\n {/* mention a version */}\n <Button\n icon=\"layers\"\n variant=\"text\"\n onClick={() => handleMentionButton('@@')}\n data-tooltip={'Mention version'}\n data-shortcut={'@@'}\n />\n {/* mention a task */}\n <Button\n icon=\"check_circle\"\n variant=\"text\"\n onClick={() => handleMentionButton('@@@')}\n data-tooltip={'Mention task'}\n data-shortcut={'@@@'}\n />\n </Styled.Buttons>\n <Styled.Buttons>\n {isEditing && (\n <Button variant=\"text\" onClick={handleClose}>\n Cancel\n </Button>\n )}\n <SaveButton\n label={isEditing ? 'Save' : 'Comment'}\n className=\"comment\"\n active={!!editorValue || !!files.length}\n onClick={handleSubmit}\n disabled={isLoading}\n />\n </Styled.Buttons>\n </Styled.Footer>\n\n <Styled.Dropzone className={clsx({ show: isDropping && isOpen })}>\n <Icon icon=\"cloud_upload\" />\n </Styled.Dropzone>\n </Styled.Comment>\n <CommentMentionSelect\n mention={mention}\n options={shownMentionOptions}\n onChange={handleSelectChange}\n types={mentionTypes}\n z\n // @ts-ignore\n config={mentionTypeOptions[mention?.type]}\n noneFound={!shownMentionOptions.length && mention?.search}\n noneFoundAtAll={!shownMentionOptions.length && !mention?.search}\n selectedIndex={mentionSelectedIndex}\n // @ts-ignore\n error={mentionsError}\n />\n </Styled.AutoHeight>\n </>\n )\n}\n\nexport default CommentInput\n"],"names":["Quill","useFeedContext","useState","useAnnotationsSync","useRef","useEffect","_a","useMemo","mention","typeWithDelay","type","handleFileDrop","convertToMarkdown","parseImages","toast","getModules","jsx","Fragment","jsxs","Styled.AutoHeight","Styled.Comment","Styled.Markdown","quillFormats","Styled.Placeholder","Styled.Footer","Styled.Buttons","Button","SaveButton","Styled.Dropzone","Icon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CommentInput.cjs.js","sources":["../../../../../../../src/containers/Feed/components/CommentInput/CommentInput.tsx"],"sourcesContent":["// React and related hooks\nimport React, { FC, useEffect, useMemo, useRef, useState } from 'react'\n\n// Third-party libraries\nimport clsx from 'clsx'\nimport { toast } from 'react-toastify'\nimport ReactQuill, { Quill } from 'react-quill-ayon'\n\n// Components\nimport { Button, Icon, SaveButton } from '@ynput/ayon-react-components'\nimport CommentMentionSelect from '../CommentMentionSelect/CommentMentionSelect'\nimport InputMarkdownConvert from './InputMarkdownConvert'\nimport FilesGrid from '../FilesGrid'\n\n// Styled components\nimport * as Styled from './CommentInput.styled'\n\n// Helpers and utilities\nimport getMentionOptions from '../../mentionHelpers/getMentionOptions'\nimport getMentionUsers from '../../mentionHelpers/getMentionUsers'\nimport getMentionTasks from '../../mentionHelpers/getMentionTasks'\nimport getMentionVersions from '../../mentionHelpers/getMentionVersions'\nimport { convertToMarkdown } from './quillToMarkdown'\nimport { handleFileDrop, parseImages, typeWithDelay } from './helpers'\nimport { getModules, quillFormats } from './modules'\n\n// Hooks\nimport useInitialValue from './hooks/useInitialValue'\nimport useSetCursorEnd from './hooks/useSetCursorEnd'\nimport useMentionLink from './hooks/useMentionLink'\nimport useAnnotationsSync from './hooks/useAnnotationsSync'\n\n// State management\nimport useAnnotationsUpload from './hooks/useAnnotationsUpload'\nimport { useFeedContext } from '../../context/FeedContext'\nimport { SavedAnnotationMetadata } from '../../index'\n\nvar Delta = Quill.import('delta')\n\nconst mentionTypes = ['@', '@@', '@@@']\nexport const mentionTypeOptions = {\n '@@@': {\n id: 'task',\n },\n '@@': {\n id: 'version',\n },\n '@': {\n id: 'user',\n isCircle: true,\n },\n}\n\ninterface CommentInputProps {\n initValue: string | null\n initFiles?: any[]\n onSubmit: (markdown: string, files: any[], data?: any) => Promise<void>\n isEditing?: boolean\n disabled?: boolean\n isLoading?: boolean\n isOpen: boolean\n onOpen?: () => void\n onClose?: () => void\n}\n\nconst CommentInput: FC<CommentInputProps> = ({\n initValue,\n initFiles = [],\n onSubmit,\n isEditing,\n disabled,\n isLoading,\n isOpen,\n onOpen,\n onClose,\n}) => {\n const { projectName, entities, projectInfo, scope, currentTab, mentionSuggestionsData } =\n useFeedContext()\n\n const {\n users: mentionUsers,\n versions: mentionVersions,\n tasks: mentionTasks,\n } = mentionSuggestionsData || {}\n\n const [initHeight, setInitHeight] = useState(88)\n const [editorValue, setEditorValue] = useState('')\n // file uploads\n const [files, setFiles] = useState(initFiles)\n const [filesUploading, setFilesUploading] = useState([])\n const [isDropping, setIsDropping] = useState(false)\n const [isSubmitting, setIsSubmitting] = useState(false)\n\n const { annotations, removeAnnotation, goToAnnotation } = useAnnotationsSync({\n entityId: entities[0]?.id,\n filesUploading,\n })\n\n // MENTION STATES\n const [mention, setMention] = useState<null | any>(null)\n const [mentionSelectedIndex, setMentionSelectedIndex] = useState(0)\n // REFS\n const editorRef = useRef<any>(null)\n const markdownRef = useRef<HTMLDivElement>(null)\n\n // if there is an initial value, set it so the editor is prefilled\n useInitialValue({\n markdownRef,\n initValue,\n setEditorValue,\n setInitHeight,\n isOpen: isOpen,\n filter: currentTab,\n })\n\n // When editing, set selection to the end of the editor\n useSetCursorEnd({ initHeight, editorRef, isEditing })\n // create a new quill format for mentions and registers it\n useMentionLink({ projectName })\n\n // focus on editor when opened\n useEffect(() => {\n if (isOpen) {\n editorRef.current?.getEditor()?.enable()\n // block autofocus if opened from an annotation\n if (annotations.length > 0 && files.length === 0) {\n return\n }\n\n editorRef.current?.focus()\n }\n // We don't set annotations or files as useEffect dependencies, because we don't want to focus\n // the input if it's already open but annotations change (e.g. are removed).\n }, [isOpen, editorRef])\n\n mentionTypes.sort((a, b) => b.length - a.length)\n\n const mentionOptions = useMemo(\n () =>\n getMentionOptions(\n mention?.type,\n {\n '@': () => getMentionUsers(mentionUsers),\n '@@': () => getMentionVersions(mentionVersions),\n '@@@': () => getMentionTasks(mentionTasks, projectInfo.taskTypes),\n },\n mention?.search,\n ),\n [mentionTasks, mentionVersions, mentionUsers, mention?.type, mention?.search],\n )\n\n // show first 5 and filter itself out\n const shownMentionOptions = mentionOptions.slice(0, 5)\n\n // triggered when a mention is selected\n const [newSelection, setNewSelection] = useState<null | number>()\n\n useEffect(() => {\n if (newSelection) {\n setNewSelection(null)\n // now we set selection to the end of the mention\n const quill = editorRef.current.getEditor()\n quill.setSelection(newSelection)\n }\n }, [newSelection])\n\n const handleSelectMention = (selectedOption: any) => {\n // get option text\n const quill = editorRef.current.getEditor()\n\n const typePrefix = mention.type // the type of mention: @, @@, @@@\n const search = typePrefix + (mention.search || '') // the full search string: @Tim\n const mentionLabel = typePrefix + selectedOption.label // the label of the mention: @Tim Bailey\n // @ts-expect-error\n const type = mentionTypeOptions[typePrefix] // the type of mention: user, version, task\n const href = `${type?.id}:${selectedOption.id}` // the href of the mention: user:user.123\n\n // get selection delta\n const selection = quill.getSelection(true)\n const selectionIndex = selection?.index || 0\n const startIndex = selectionIndex - search.length // the start index of the search\n\n // first delete the search string\n quill.deleteText(startIndex, search.length)\n\n // insert embed link\n quill.insertText(startIndex, mentionLabel, 'mention', href)\n\n const endIndex = startIndex + mentionLabel.length\n\n // insert a space after the mention\n quill.updateContents(new Delta().retain(endIndex).insert(' '))\n\n // remove single \\n after mention\n quill.updateContents(new Delta().retain(endIndex + 1).delete(1))\n\n // set selection to the end of the mention + 1\n setNewSelection(endIndex + 1)\n\n // reset mention state\n setMention(null)\n setMentionSelectedIndex(0)\n }\n\n const handleSelectChange = (option: any) => {\n handleSelectMention(option)\n }\n\n const handleChange = (content: string, delta: any, _: any, editor: any) => {\n let currentCharacter =\n (delta.ops[0] && delta.ops[0].insert) || (delta.ops[1] && delta.ops[1].insert)\n\n const tabOrEnter = currentCharacter === '\\n' || currentCharacter === '\\t'\n // find the first option\n const selectedOption = mentionOptions[mentionSelectedIndex]\n\n if (mention && tabOrEnter && selectedOption) {\n // get option text\n const retain = (delta.ops[0] && delta.ops[0].retain) || 0\n // prevent default\n\n // @ts-ignore\n handleSelectMention(selectedOption, retain)\n\n return\n }\n\n setEditorValue(content)\n\n const isDelete = delta.ops.length === 2 && !!delta.ops[1].delete\n\n if (!currentCharacter && isDelete) {\n currentCharacter = editor.getText(delta.ops[0].retain - 1, 1)\n }\n\n const isMention = mentionTypes.includes(currentCharacter)\n\n if (isMention) {\n const mentionIndex = delta.ops.findIndex((op: any) => 'insert' in op || 'delete' in op)\n const mention = currentCharacter\n let retain = mentionIndex === 0 ? 0 : delta.ops[mentionIndex - 1].retain\n if (isDelete) retain = retain - 1\n\n // for each mention denotation char, check if it is a mention\n // sort by length of mention denotation char\n let mentionMatch = null\n\n // loop through each mention denotation char, with longest first. First one to match is the one we want\n for (const chars of mentionTypes) {\n let isMatch = true\n // start with the last character\n if (chars.endsWith(mention)) {\n // loop through the chars backwards\n for (let i = chars.length - 1; i >= 0; i--) {\n // skip first character as that's already been checked\n if (i === 0) continue\n const char = chars[i - 1]\n const indexInDelta = retain - (chars.length - i)\n const valueCharAtIndex = editor.getText(indexInDelta, 1)\n if (valueCharAtIndex !== char) {\n isMatch = false\n break\n }\n }\n } else {\n isMatch = false\n }\n\n if (isMatch) {\n // console.log('match!!!', chars)\n mentionMatch = chars\n break\n }\n }\n\n if (mentionMatch) {\n setMention({\n type: mentionMatch,\n retain: retain,\n })\n } else {\n setMention(null)\n setMentionSelectedIndex(0)\n }\n } else {\n // get full string between mention and new delta\n // This is where SEARCH is handled\n if (mention) {\n const retain = delta.ops[0].retain\n // if space is pressed, remove mention\n if (currentCharacter === ' ' || !retain) {\n setMention(null)\n setMentionSelectedIndex(0)\n return\n }\n\n let distanceMentionToRetain = retain - mention.retain\n if (!isDelete) distanceMentionToRetain++\n const mentionFull = editor.getText(mention.retain, distanceMentionToRetain)\n const mentionSearch = mentionFull.replace(mention.type.slice(-1), '')\n // check for space in mentionFull\n if (mentionFull.includes(' ')) {\n setMention(null)\n setMentionSelectedIndex(0)\n } else {\n setMention({\n ...mention,\n search: mentionSearch?.toLowerCase(),\n })\n }\n } else {\n // just deleting any text\n const quill = editorRef.current.getEditor()\n const currentSelection = quill.getSelection(false)\n const currentFormat = quill.getFormat(currentSelection?.index, currentSelection?.length)\n if (currentFormat.mention) {\n // if format is mention, delete the whole mention\n const [lineBlock] = quill.getLine(currentSelection.index - 1) || []\n const ops = lineBlock?.cache?.delta?.ops || []\n // get last op with attributes mention: true\n const lastMentionOp = ops.reverse().find((op: any) => op.attributes?.mention)\n if (lastMentionOp) {\n const mentionLength = lastMentionOp.insert.length\n quill.deleteText(currentSelection.index - mentionLength, mentionLength)\n }\n }\n }\n }\n }\n\n const addTextToEditor = (type: string) => {\n // get editor retain\n const quill = editorRef.current.getEditor()\n\n let retain = quill.getSelection(true)?.index || 0\n\n // get character at retain\n const currentCharacter = quill.getText(retain - 1, 1)\n\n // if the current character is a character, increment retain\n const addSpace = currentCharacter !== ' ' && currentCharacter\n if (addSpace) {\n quill.insertText(retain, ' ')\n retain++\n }\n\n // This is hack AF, but it works\n typeWithDelay(quill, retain, type)\n }\n\n const handleMentionButton = (type: string) => {\n // first check if mention is already open\n if (mention) {\n const { type, retain, search = '' } = mention\n\n const quill = editorRef.current.getEditor()\n const length = type.length + search.length\n const start = retain - type.length + 1\n // delete the mention\n quill.deleteText(start, length)\n }\n\n addTextToEditor(type)\n }\n\n const handleOpenClick = () => {\n if (isOpen || disabled) return\n\n onOpen && onOpen()\n }\n\n const handleClose = () => {\n // get editor value\n const editor = editorRef.current.getEditor()\n const text = editor.getText()\n if (text.length < 2 || isEditing) {\n setEditorValue('')\n }\n\n // always close editor\n onClose && onClose()\n }\n\n const handleFileUploaded = ({ file, data }: any) => {\n const newFile = {\n id: data.id,\n name: file.name,\n mime: file.type,\n size: file.size,\n order: files.length,\n }\n\n setFiles((prev) => [...prev, newFile])\n // remove from uploading\n setFilesUploading((prev) => prev.filter((uploading: any) => uploading.name !== file.name))\n\n return newFile\n }\n\n const handleFileRemove = (id: string, name: string, isUnsavedAnnotation: boolean) => {\n if (isUnsavedAnnotation) {\n // remove from annotations (if it's an unsaved annotation)\n removeAnnotation?.(id)\n } else {\n // remove file from files\n setFiles((prev) => prev.filter((file) => file.id !== id))\n // remove from uploading\n setFilesUploading((prev) => {\n return prev.filter((file: any) => file.name !== name)\n })\n }\n }\n\n const handleFileProgress = (e: any, file: any) => {\n const progress = Math.round((e.loaded * 100) / e.total)\n if (progress !== 100) {\n const uploadProgress = {\n name: file.name,\n progress,\n type: file.type,\n order: files.length + filesUploading.length,\n }\n\n // @ts-ignore\n setFilesUploading((prev) => {\n // replace or add new progress\n const newProgress = prev.filter((name: any) => name.name !== file.name)\n return [...newProgress, uploadProgress]\n })\n }\n }\n\n // when a file is not dropped onto the comment input\n const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {\n setIsDropping(false)\n // upload file\n handleFileDrop(e, projectName, handleFileProgress, handleFileUploaded)\n }\n\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n e.stopPropagation()\n setIsDropping(true)\n }\n\n const uploadAnnotations = useAnnotationsUpload({\n projectName,\n onSuccess: handleFileUploaded,\n })\n\n const handleSubmit = async () => {\n try {\n setIsSubmitting(true)\n // upload any annotations first\n let annotationFiles = []\n let annotationMetadata: SavedAnnotationMetadata[] = []\n\n if (annotations.length) {\n const { files, metadata } = await uploadAnnotations(annotations)\n annotationFiles = files\n annotationMetadata = metadata\n }\n\n // convert to markdown\n const [markdown] = convertToMarkdown(editorValue)\n\n // remove img query params\n const markdownParsed = parseImages(markdown)\n\n const uploadedFiles = [...files, ...annotationFiles]\n\n if ((markdownParsed || uploadedFiles.length) && onSubmit) {\n try {\n await onSubmit(markdownParsed, uploadedFiles, { annotations: annotationMetadata })\n // only clear if onSubmit is successful\n setEditorValue('')\n setFiles([])\n } catch (error) {\n // error is handled in rtk query mutation\n return\n }\n }\n } catch (error) {\n console.error(error)\n toast.error('Something went wrong')\n } finally {\n setIsSubmitting(false)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (mention) {\n // close mention on escape\n if (e.key === 'Escape') {\n setMention(null)\n setMentionSelectedIndex(0)\n return\n }\n\n // add top search of mention\n if (mention && e.key === 'Tab') {\n // we handle this in the onChange\n }\n\n const arrowDirection = e.key === 'ArrowUp' ? -1 : e.key === 'ArrowDown' ? 1 : 0\n\n if (arrowDirection) {\n // navigate through mentions\n e.preventDefault()\n let newIndex = mentionSelectedIndex + arrowDirection\n if (newIndex < 0) newIndex = shownMentionOptions.length - 1\n if (newIndex >= shownMentionOptions.length) newIndex = 0\n setMentionSelectedIndex(newIndex)\n }\n\n if (e.key === 'Enter') {\n // we handle this in the onChange\n }\n }\n\n if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {\n handleSubmit()\n }\n\n if (e.key === 'Escape') {\n handleClose()\n }\n }\n\n let quillMinHeight: number | undefined = isOpen ? initHeight + 41 : 44\n if (isEditing) quillMinHeight = undefined\n\n // QUILL CONFIG\n const modules = useMemo(\n () =>\n getModules({\n imageUploader: {\n projectName,\n onUpload: handleFileUploaded,\n onUploadProgress: handleFileProgress,\n },\n }),\n [projectName, setFiles, setFilesUploading],\n )\n\n const allFiles = [...annotations, ...(files || []), ...filesUploading].sort(\n (a, b) => a.order - b.order,\n )\n const compactGrid = allFiles.length > 6\n\n // disable version mentions for folders\n let mentionsError = null\n if (entities.length && entities[0].entityType === 'folder') {\n if (mention?.type === '@@') {\n mentionsError = 'Version mentions are disabled for folders'\n }\n }\n\n return (\n <>\n <Styled.AutoHeight\n className={clsx('comment-container', { isOpen, isEditing })}\n onDragOver={handleDragOver}\n onDragLeave={() => setIsDropping(false)}\n onDrop={handleDrop}\n onClick={() => setIsDropping(false)}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <Styled.Comment\n className={clsx('block-shortcuts', {\n isOpen,\n isClosed: !isOpen || disabled,\n isEditing,\n isDropping,\n disabled,\n isLoading,\n isSubmitting,\n })}\n onKeyDown={handleKeyDown}\n onClick={handleOpenClick}\n >\n <Styled.Markdown ref={markdownRef}>\n {/* this is purely used to translate the markdown into html for Editor */}\n <InputMarkdownConvert typeOptions={mentionTypeOptions} initValue={initValue} />\n </Styled.Markdown>\n\n {/* file uploads */}\n {isOpen && (\n <FilesGrid\n files={allFiles}\n isCompact={compactGrid}\n onRemove={handleFileRemove}\n style={{ borderBottom: '1px solid var(--md-sys-color-outline-variant)' }}\n projectName={projectName}\n onAnnotationClick={goToAnnotation}\n />\n )}\n {isOpen && !disabled ? (\n <ReactQuill\n theme=\"snow\"\n style={{ minHeight: quillMinHeight, maxHeight: 300 }}\n ref={editorRef}\n value={editorValue}\n onChange={handleChange}\n readOnly={!isOpen}\n placeholder={'Comment or mention with @user, @@version, @@@task...'}\n modules={modules}\n formats={quillFormats}\n />\n ) : (\n <Styled.Placeholder>\n {disabled ? 'Commenting is disabled across multiple projects.' : 'Add a comment...'}\n </Styled.Placeholder>\n )}\n\n <Styled.Footer>\n <Styled.Buttons>\n {/* mention a user */}\n <Button\n icon=\"person\"\n variant=\"text\"\n onClick={() => handleMentionButton('@')}\n data-tooltip={'Mention user'}\n data-shortcut={'@'}\n />\n {/* mention a version */}\n <Button\n icon=\"layers\"\n variant=\"text\"\n onClick={() => handleMentionButton('@@')}\n data-tooltip={'Mention version'}\n data-shortcut={'@@'}\n />\n {/* mention a task */}\n <Button\n icon=\"check_circle\"\n variant=\"text\"\n onClick={() => handleMentionButton('@@@')}\n data-tooltip={'Mention task'}\n data-shortcut={'@@@'}\n />\n </Styled.Buttons>\n <Styled.Buttons>\n {isEditing && (\n <Button variant=\"text\" onClick={handleClose}>\n Cancel\n </Button>\n )}\n <SaveButton\n label={isEditing ? 'Save' : 'Comment'}\n className=\"comment\"\n active={!!editorValue || !!files.length}\n onClick={handleSubmit}\n disabled={isLoading}\n />\n </Styled.Buttons>\n </Styled.Footer>\n\n <Styled.Dropzone className={clsx({ show: isDropping && isOpen })}>\n <Icon icon=\"cloud_upload\" />\n </Styled.Dropzone>\n </Styled.Comment>\n <CommentMentionSelect\n mention={mention}\n options={shownMentionOptions}\n onChange={handleSelectChange}\n types={mentionTypes}\n z\n // @ts-ignore\n config={mentionTypeOptions[mention?.type]}\n noneFound={!shownMentionOptions.length && mention?.search}\n noneFoundAtAll={!shownMentionOptions.length && !mention?.search}\n selectedIndex={mentionSelectedIndex}\n // @ts-ignore\n error={mentionsError}\n />\n </Styled.AutoHeight>\n </>\n )\n}\n\nexport default CommentInput\n"],"names":["Quill","useFeedContext","useState","useAnnotationsSync","useRef","useEffect","_a","useMemo","mention","typeWithDelay","type","handleFileDrop","files","convertToMarkdown","parseImages","toast","getModules","jsx","Fragment","jsxs","Styled.AutoHeight","Styled.Comment","Styled.Markdown","quillFormats","Styled.Placeholder","Styled.Footer","Styled.Buttons","Button","SaveButton","Styled.Dropzone","Icon"],"mappings":"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"}
|
|
@@ -269,8 +269,8 @@ const CommentInput = ({
|
|
|
269
269
|
setFilesUploading((prev) => prev.filter((uploading) => uploading.name !== file.name));
|
|
270
270
|
return newFile;
|
|
271
271
|
};
|
|
272
|
-
const handleFileRemove = (id, name,
|
|
273
|
-
if (
|
|
272
|
+
const handleFileRemove = (id, name, isUnsavedAnnotation) => {
|
|
273
|
+
if (isUnsavedAnnotation) {
|
|
274
274
|
removeAnnotation == null ? void 0 : removeAnnotation(id);
|
|
275
275
|
} else {
|
|
276
276
|
setFiles((prev) => prev.filter((file) => file.id !== id));
|
|
@@ -311,15 +311,18 @@ const CommentInput = ({
|
|
|
311
311
|
try {
|
|
312
312
|
setIsSubmitting(true);
|
|
313
313
|
let annotationFiles = [];
|
|
314
|
+
let annotationMetadata = [];
|
|
314
315
|
if (annotations.length) {
|
|
315
|
-
|
|
316
|
+
const { files: files2, metadata } = await uploadAnnotations(annotations);
|
|
317
|
+
annotationFiles = files2;
|
|
318
|
+
annotationMetadata = metadata;
|
|
316
319
|
}
|
|
317
320
|
const [markdown] = convertToMarkdown(editorValue);
|
|
318
321
|
const markdownParsed = parseImages(markdown);
|
|
319
322
|
const uploadedFiles = [...files, ...annotationFiles];
|
|
320
323
|
if ((markdownParsed || uploadedFiles.length) && onSubmit) {
|
|
321
324
|
try {
|
|
322
|
-
await onSubmit(markdownParsed, uploadedFiles);
|
|
325
|
+
await onSubmit(markdownParsed, uploadedFiles, { annotations: annotationMetadata });
|
|
323
326
|
setEditorValue("");
|
|
324
327
|
setFiles([]);
|
|
325
328
|
} catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommentInput.es.js","sources":["../../../../../../../src/containers/Feed/components/CommentInput/CommentInput.tsx"],"sourcesContent":["// React and related hooks\nimport React, { FC, useEffect, useMemo, useRef, useState } from 'react'\n\n// Third-party libraries\nimport clsx from 'clsx'\nimport { toast } from 'react-toastify'\nimport ReactQuill, { Quill } from 'react-quill-ayon'\n\n// Components\nimport { Button, Icon, SaveButton } from '@ynput/ayon-react-components'\nimport CommentMentionSelect from '../CommentMentionSelect/CommentMentionSelect'\nimport InputMarkdownConvert from './InputMarkdownConvert'\nimport FilesGrid from '../FilesGrid'\n\n// Styled components\nimport * as Styled from './CommentInput.styled'\n\n// Helpers and utilities\nimport getMentionOptions from '../../mentionHelpers/getMentionOptions'\nimport getMentionUsers from '../../mentionHelpers/getMentionUsers'\nimport getMentionTasks from '../../mentionHelpers/getMentionTasks'\nimport getMentionVersions from '../../mentionHelpers/getMentionVersions'\nimport { convertToMarkdown } from './quillToMarkdown'\nimport { handleFileDrop, parseImages, typeWithDelay } from './helpers'\nimport { getModules, quillFormats } from './modules'\n\n// Hooks\nimport useInitialValue from './hooks/useInitialValue'\nimport useSetCursorEnd from './hooks/useSetCursorEnd'\nimport useMentionLink from './hooks/useMentionLink'\nimport useAnnotationsSync from './hooks/useAnnotationsSync'\n\n// State management\nimport useAnnotationsUpload from './hooks/useAnnotationsUpload'\nimport { useFeedContext } from '../../context/FeedContext'\n\nvar Delta = Quill.import('delta')\n\nconst mentionTypes = ['@', '@@', '@@@']\nexport const mentionTypeOptions = {\n '@@@': {\n id: 'task',\n },\n '@@': {\n id: 'version',\n },\n '@': {\n id: 'user',\n isCircle: true,\n },\n}\n\ninterface CommentInputProps {\n initValue: string | null\n initFiles?: any[]\n onSubmit: (markdown: string, files: any[]) => Promise<void>\n isEditing?: boolean\n disabled?: boolean\n isLoading?: boolean\n isOpen: boolean\n onOpen?: () => void\n onClose?: () => void\n}\n\nconst CommentInput: FC<CommentInputProps> = ({\n initValue,\n initFiles = [],\n onSubmit,\n isEditing,\n disabled,\n isLoading,\n isOpen,\n onOpen,\n onClose,\n}) => {\n const { projectName, entities, projectInfo, scope, currentTab, mentionSuggestionsData } =\n useFeedContext()\n\n const {\n users: mentionUsers,\n versions: mentionVersions,\n tasks: mentionTasks,\n } = mentionSuggestionsData || {}\n\n const [initHeight, setInitHeight] = useState(88)\n const [editorValue, setEditorValue] = useState('')\n // file uploads\n const [files, setFiles] = useState(initFiles)\n const [filesUploading, setFilesUploading] = useState([])\n const [isDropping, setIsDropping] = useState(false)\n const [isSubmitting, setIsSubmitting] = useState(false)\n\n const { annotations, removeAnnotation, goToAnnotation } = useAnnotationsSync({\n entityId: entities[0]?.id,\n filesUploading,\n })\n\n // MENTION STATES\n const [mention, setMention] = useState<null | any>(null)\n const [mentionSelectedIndex, setMentionSelectedIndex] = useState(0)\n // REFS\n const editorRef = useRef<any>(null)\n const markdownRef = useRef<HTMLDivElement>(null)\n\n // if there is an initial value, set it so the editor is prefilled\n useInitialValue({\n markdownRef,\n initValue,\n setEditorValue,\n setInitHeight,\n isOpen: isOpen,\n filter: currentTab,\n })\n\n // When editing, set selection to the end of the editor\n useSetCursorEnd({ initHeight, editorRef, isEditing })\n // create a new quill format for mentions and registers it\n useMentionLink({ projectName })\n\n // focus on editor when opened\n useEffect(() => {\n if (isOpen) {\n editorRef.current?.getEditor()?.enable()\n // block autofocus if opened from an annotation\n if (annotations.length > 0 && files.length === 0) {\n return\n }\n\n editorRef.current?.focus()\n }\n // We don't set annotations or files as useEffect dependencies, because we don't want to focus\n // the input if it's already open but annotations change (e.g. are removed).\n }, [isOpen, editorRef])\n\n mentionTypes.sort((a, b) => b.length - a.length)\n\n const mentionOptions = useMemo(\n () =>\n getMentionOptions(\n mention?.type,\n {\n '@': () => getMentionUsers(mentionUsers),\n '@@': () => getMentionVersions(mentionVersions),\n '@@@': () => getMentionTasks(mentionTasks, projectInfo.taskTypes),\n },\n mention?.search,\n ),\n [mentionTasks, mentionVersions, mentionUsers, mention?.type, mention?.search],\n )\n\n // show first 5 and filter itself out\n const shownMentionOptions = mentionOptions.slice(0, 5)\n\n // triggered when a mention is selected\n const [newSelection, setNewSelection] = useState<null | number>()\n\n useEffect(() => {\n if (newSelection) {\n setNewSelection(null)\n // now we set selection to the end of the mention\n const quill = editorRef.current.getEditor()\n quill.setSelection(newSelection)\n }\n }, [newSelection])\n\n const handleSelectMention = (selectedOption: any) => {\n // get option text\n const quill = editorRef.current.getEditor()\n\n const typePrefix = mention.type // the type of mention: @, @@, @@@\n const search = typePrefix + (mention.search || '') // the full search string: @Tim\n const mentionLabel = typePrefix + selectedOption.label // the label of the mention: @Tim Bailey\n // @ts-expect-error\n const type = mentionTypeOptions[typePrefix] // the type of mention: user, version, task\n const href = `${type?.id}:${selectedOption.id}` // the href of the mention: user:user.123\n\n // get selection delta\n const selection = quill.getSelection(true)\n const selectionIndex = selection?.index || 0\n const startIndex = selectionIndex - search.length // the start index of the search\n\n // first delete the search string\n quill.deleteText(startIndex, search.length)\n\n // insert embed link\n quill.insertText(startIndex, mentionLabel, 'mention', href)\n\n const endIndex = startIndex + mentionLabel.length\n\n // insert a space after the mention\n quill.updateContents(new Delta().retain(endIndex).insert(' '))\n\n // remove single \\n after mention\n quill.updateContents(new Delta().retain(endIndex + 1).delete(1))\n\n // set selection to the end of the mention + 1\n setNewSelection(endIndex + 1)\n\n // reset mention state\n setMention(null)\n setMentionSelectedIndex(0)\n }\n\n const handleSelectChange = (option: any) => {\n handleSelectMention(option)\n }\n\n const handleChange = (content: string, delta: any, _: any, editor: any) => {\n let currentCharacter =\n (delta.ops[0] && delta.ops[0].insert) || (delta.ops[1] && delta.ops[1].insert)\n\n const tabOrEnter = currentCharacter === '\\n' || currentCharacter === '\\t'\n // find the first option\n const selectedOption = mentionOptions[mentionSelectedIndex]\n\n if (mention && tabOrEnter && selectedOption) {\n // get option text\n const retain = (delta.ops[0] && delta.ops[0].retain) || 0\n // prevent default\n\n // @ts-ignore\n handleSelectMention(selectedOption, retain)\n\n return\n }\n\n setEditorValue(content)\n\n const isDelete = delta.ops.length === 2 && !!delta.ops[1].delete\n\n if (!currentCharacter && isDelete) {\n currentCharacter = editor.getText(delta.ops[0].retain - 1, 1)\n }\n\n const isMention = mentionTypes.includes(currentCharacter)\n\n if (isMention) {\n const mentionIndex = delta.ops.findIndex((op: any) => 'insert' in op || 'delete' in op)\n const mention = currentCharacter\n let retain = mentionIndex === 0 ? 0 : delta.ops[mentionIndex - 1].retain\n if (isDelete) retain = retain - 1\n\n // for each mention denotation char, check if it is a mention\n // sort by length of mention denotation char\n let mentionMatch = null\n\n // loop through each mention denotation char, with longest first. First one to match is the one we want\n for (const chars of mentionTypes) {\n let isMatch = true\n // start with the last character\n if (chars.endsWith(mention)) {\n // loop through the chars backwards\n for (let i = chars.length - 1; i >= 0; i--) {\n // skip first character as that's already been checked\n if (i === 0) continue\n const char = chars[i - 1]\n const indexInDelta = retain - (chars.length - i)\n const valueCharAtIndex = editor.getText(indexInDelta, 1)\n if (valueCharAtIndex !== char) {\n isMatch = false\n break\n }\n }\n } else {\n isMatch = false\n }\n\n if (isMatch) {\n // console.log('match!!!', chars)\n mentionMatch = chars\n break\n }\n }\n\n if (mentionMatch) {\n setMention({\n type: mentionMatch,\n retain: retain,\n })\n } else {\n setMention(null)\n setMentionSelectedIndex(0)\n }\n } else {\n // get full string between mention and new delta\n // This is where SEARCH is handled\n if (mention) {\n const retain = delta.ops[0].retain\n // if space is pressed, remove mention\n if (currentCharacter === ' ' || !retain) {\n setMention(null)\n setMentionSelectedIndex(0)\n return\n }\n\n let distanceMentionToRetain = retain - mention.retain\n if (!isDelete) distanceMentionToRetain++\n const mentionFull = editor.getText(mention.retain, distanceMentionToRetain)\n const mentionSearch = mentionFull.replace(mention.type.slice(-1), '')\n // check for space in mentionFull\n if (mentionFull.includes(' ')) {\n setMention(null)\n setMentionSelectedIndex(0)\n } else {\n setMention({\n ...mention,\n search: mentionSearch?.toLowerCase(),\n })\n }\n } else {\n // just deleting any text\n const quill = editorRef.current.getEditor()\n const currentSelection = quill.getSelection(false)\n const currentFormat = quill.getFormat(currentSelection?.index, currentSelection?.length)\n if (currentFormat.mention) {\n // if format is mention, delete the whole mention\n const [lineBlock] = quill.getLine(currentSelection.index - 1) || []\n const ops = lineBlock?.cache?.delta?.ops || []\n // get last op with attributes mention: true\n const lastMentionOp = ops.reverse().find((op: any) => op.attributes?.mention)\n if (lastMentionOp) {\n const mentionLength = lastMentionOp.insert.length\n quill.deleteText(currentSelection.index - mentionLength, mentionLength)\n }\n }\n }\n }\n }\n\n const addTextToEditor = (type: string) => {\n // get editor retain\n const quill = editorRef.current.getEditor()\n\n let retain = quill.getSelection(true)?.index || 0\n\n // get character at retain\n const currentCharacter = quill.getText(retain - 1, 1)\n\n // if the current character is a character, increment retain\n const addSpace = currentCharacter !== ' ' && currentCharacter\n if (addSpace) {\n quill.insertText(retain, ' ')\n retain++\n }\n\n // This is hack AF, but it works\n typeWithDelay(quill, retain, type)\n }\n\n const handleMentionButton = (type: string) => {\n // first check if mention is already open\n if (mention) {\n const { type, retain, search = '' } = mention\n\n const quill = editorRef.current.getEditor()\n const length = type.length + search.length\n const start = retain - type.length + 1\n // delete the mention\n quill.deleteText(start, length)\n }\n\n addTextToEditor(type)\n }\n\n const handleOpenClick = () => {\n if (isOpen || disabled) return\n\n onOpen && onOpen()\n }\n\n const handleClose = () => {\n // get editor value\n const editor = editorRef.current.getEditor()\n const text = editor.getText()\n if (text.length < 2 || isEditing) {\n setEditorValue('')\n }\n\n // always close editor\n onClose && onClose()\n }\n\n const handleFileUploaded = ({ file, data }: any) => {\n const newFile = {\n id: data.id,\n name: file.name,\n mime: file.type,\n size: file.size,\n order: files.length,\n }\n\n setFiles((prev) => [...prev, newFile])\n // remove from uploading\n setFilesUploading((prev) => prev.filter((uploading: any) => uploading.name !== file.name))\n\n return newFile\n }\n\n const handleFileRemove = (id: string, name: string, isAnnotation: boolean) => {\n if (isAnnotation) {\n // remove from annotations (if it's an annotation)\n removeAnnotation?.(id)\n } else {\n // remove file from files\n setFiles((prev) => prev.filter((file) => file.id !== id))\n // remove from uploading\n setFilesUploading((prev) => {\n return prev.filter((file: any) => file.name !== name)\n })\n }\n }\n\n const handleFileProgress = (e: any, file: any) => {\n const progress = Math.round((e.loaded * 100) / e.total)\n if (progress !== 100) {\n const uploadProgress = {\n name: file.name,\n progress,\n type: file.type,\n order: files.length + filesUploading.length,\n }\n\n // @ts-ignore\n setFilesUploading((prev) => {\n // replace or add new progress\n const newProgress = prev.filter((name: any) => name.name !== file.name)\n return [...newProgress, uploadProgress]\n })\n }\n }\n\n // when a file is not dropped onto the comment input\n const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {\n setIsDropping(false)\n // upload file\n handleFileDrop(e, projectName, handleFileProgress, handleFileUploaded)\n }\n\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n e.stopPropagation()\n setIsDropping(true)\n }\n\n const uploadAnnotations = useAnnotationsUpload({\n projectName,\n onSuccess: handleFileUploaded,\n })\n\n const handleSubmit = async () => {\n try {\n setIsSubmitting(true)\n // upload any annotations first\n let annotationFiles = []\n if (annotations.length) {\n annotationFiles = await uploadAnnotations(annotations)\n }\n\n // convert to markdown\n const [markdown] = convertToMarkdown(editorValue)\n\n // remove img query params\n const markdownParsed = parseImages(markdown)\n\n const uploadedFiles = [...files, ...annotationFiles]\n\n if ((markdownParsed || uploadedFiles.length) && onSubmit) {\n try {\n await onSubmit(markdownParsed, uploadedFiles)\n // only clear if onSubmit is successful\n setEditorValue('')\n setFiles([])\n } catch (error) {\n // error is handled in rtk query mutation\n return\n }\n }\n } catch (error) {\n console.error(error)\n toast.error('Something went wrong')\n } finally {\n setIsSubmitting(false)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (mention) {\n // close mention on escape\n if (e.key === 'Escape') {\n setMention(null)\n setMentionSelectedIndex(0)\n return\n }\n\n // add top search of mention\n if (mention && e.key === 'Tab') {\n // we handle this in the onChange\n }\n\n const arrowDirection = e.key === 'ArrowUp' ? -1 : e.key === 'ArrowDown' ? 1 : 0\n\n if (arrowDirection) {\n // navigate through mentions\n e.preventDefault()\n let newIndex = mentionSelectedIndex + arrowDirection\n if (newIndex < 0) newIndex = shownMentionOptions.length - 1\n if (newIndex >= shownMentionOptions.length) newIndex = 0\n setMentionSelectedIndex(newIndex)\n }\n\n if (e.key === 'Enter') {\n // we handle this in the onChange\n }\n }\n\n if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {\n handleSubmit()\n }\n\n if (e.key === 'Escape') {\n handleClose()\n }\n }\n\n let quillMinHeight: number | undefined = isOpen ? initHeight + 41 : 44\n if (isEditing) quillMinHeight = undefined\n\n // QUILL CONFIG\n const modules = useMemo(\n () =>\n getModules({\n imageUploader: {\n projectName,\n onUpload: handleFileUploaded,\n onUploadProgress: handleFileProgress,\n },\n }),\n [projectName, setFiles, setFilesUploading],\n )\n\n const allFiles = [...annotations, ...(files || []), ...filesUploading].sort(\n (a, b) => a.order - b.order,\n )\n const compactGrid = allFiles.length > 6\n\n // disable version mentions for folders\n let mentionsError = null\n if (entities.length && entities[0].entityType === 'folder') {\n if (mention?.type === '@@') {\n mentionsError = 'Version mentions are disabled for folders'\n }\n }\n\n return (\n <>\n <Styled.AutoHeight\n className={clsx('comment-container', { isOpen, isEditing })}\n onDragOver={handleDragOver}\n onDragLeave={() => setIsDropping(false)}\n onDrop={handleDrop}\n onClick={() => setIsDropping(false)}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <Styled.Comment\n className={clsx('block-shortcuts', {\n isOpen,\n isClosed: !isOpen || disabled,\n isEditing,\n isDropping,\n disabled,\n isLoading,\n isSubmitting,\n })}\n onKeyDown={handleKeyDown}\n onClick={handleOpenClick}\n >\n <Styled.Markdown ref={markdownRef}>\n {/* this is purely used to translate the markdown into html for Editor */}\n <InputMarkdownConvert typeOptions={mentionTypeOptions} initValue={initValue} />\n </Styled.Markdown>\n\n {/* file uploads */}\n {isOpen && (\n <FilesGrid\n files={allFiles}\n isCompact={compactGrid}\n onRemove={handleFileRemove}\n style={{ borderBottom: '1px solid var(--md-sys-color-outline-variant)' }}\n projectName={projectName}\n onAnnotationClick={goToAnnotation}\n />\n )}\n {isOpen && !disabled ? (\n <ReactQuill\n theme=\"snow\"\n style={{ minHeight: quillMinHeight, maxHeight: 300 }}\n ref={editorRef}\n value={editorValue}\n onChange={handleChange}\n readOnly={!isOpen}\n placeholder={'Comment or mention with @user, @@version, @@@task...'}\n modules={modules}\n formats={quillFormats}\n />\n ) : (\n <Styled.Placeholder>\n {disabled ? 'Commenting is disabled across multiple projects.' : 'Add a comment...'}\n </Styled.Placeholder>\n )}\n\n <Styled.Footer>\n <Styled.Buttons>\n {/* mention a user */}\n <Button\n icon=\"person\"\n variant=\"text\"\n onClick={() => handleMentionButton('@')}\n data-tooltip={'Mention user'}\n data-shortcut={'@'}\n />\n {/* mention a version */}\n <Button\n icon=\"layers\"\n variant=\"text\"\n onClick={() => handleMentionButton('@@')}\n data-tooltip={'Mention version'}\n data-shortcut={'@@'}\n />\n {/* mention a task */}\n <Button\n icon=\"check_circle\"\n variant=\"text\"\n onClick={() => handleMentionButton('@@@')}\n data-tooltip={'Mention task'}\n data-shortcut={'@@@'}\n />\n </Styled.Buttons>\n <Styled.Buttons>\n {isEditing && (\n <Button variant=\"text\" onClick={handleClose}>\n Cancel\n </Button>\n )}\n <SaveButton\n label={isEditing ? 'Save' : 'Comment'}\n className=\"comment\"\n active={!!editorValue || !!files.length}\n onClick={handleSubmit}\n disabled={isLoading}\n />\n </Styled.Buttons>\n </Styled.Footer>\n\n <Styled.Dropzone className={clsx({ show: isDropping && isOpen })}>\n <Icon icon=\"cloud_upload\" />\n </Styled.Dropzone>\n </Styled.Comment>\n <CommentMentionSelect\n mention={mention}\n options={shownMentionOptions}\n onChange={handleSelectChange}\n types={mentionTypes}\n z\n // @ts-ignore\n config={mentionTypeOptions[mention?.type]}\n noneFound={!shownMentionOptions.length && mention?.search}\n noneFoundAtAll={!shownMentionOptions.length && !mention?.search}\n selectedIndex={mentionSelectedIndex}\n // @ts-ignore\n error={mentionsError}\n />\n </Styled.AutoHeight>\n </>\n )\n}\n\nexport default CommentInput\n"],"names":["_a","mention","type","jsx","Fragment","jsxs","Styled.AutoHeight","Styled.Comment","Styled.Markdown","Styled.Placeholder","Styled.Footer","Styled.Buttons","Styled.Dropzone"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CommentInput.es.js","sources":["../../../../../../../src/containers/Feed/components/CommentInput/CommentInput.tsx"],"sourcesContent":["// React and related hooks\nimport React, { FC, useEffect, useMemo, useRef, useState } from 'react'\n\n// Third-party libraries\nimport clsx from 'clsx'\nimport { toast } from 'react-toastify'\nimport ReactQuill, { Quill } from 'react-quill-ayon'\n\n// Components\nimport { Button, Icon, SaveButton } from '@ynput/ayon-react-components'\nimport CommentMentionSelect from '../CommentMentionSelect/CommentMentionSelect'\nimport InputMarkdownConvert from './InputMarkdownConvert'\nimport FilesGrid from '../FilesGrid'\n\n// Styled components\nimport * as Styled from './CommentInput.styled'\n\n// Helpers and utilities\nimport getMentionOptions from '../../mentionHelpers/getMentionOptions'\nimport getMentionUsers from '../../mentionHelpers/getMentionUsers'\nimport getMentionTasks from '../../mentionHelpers/getMentionTasks'\nimport getMentionVersions from '../../mentionHelpers/getMentionVersions'\nimport { convertToMarkdown } from './quillToMarkdown'\nimport { handleFileDrop, parseImages, typeWithDelay } from './helpers'\nimport { getModules, quillFormats } from './modules'\n\n// Hooks\nimport useInitialValue from './hooks/useInitialValue'\nimport useSetCursorEnd from './hooks/useSetCursorEnd'\nimport useMentionLink from './hooks/useMentionLink'\nimport useAnnotationsSync from './hooks/useAnnotationsSync'\n\n// State management\nimport useAnnotationsUpload from './hooks/useAnnotationsUpload'\nimport { useFeedContext } from '../../context/FeedContext'\nimport { SavedAnnotationMetadata } from '../../index'\n\nvar Delta = Quill.import('delta')\n\nconst mentionTypes = ['@', '@@', '@@@']\nexport const mentionTypeOptions = {\n '@@@': {\n id: 'task',\n },\n '@@': {\n id: 'version',\n },\n '@': {\n id: 'user',\n isCircle: true,\n },\n}\n\ninterface CommentInputProps {\n initValue: string | null\n initFiles?: any[]\n onSubmit: (markdown: string, files: any[], data?: any) => Promise<void>\n isEditing?: boolean\n disabled?: boolean\n isLoading?: boolean\n isOpen: boolean\n onOpen?: () => void\n onClose?: () => void\n}\n\nconst CommentInput: FC<CommentInputProps> = ({\n initValue,\n initFiles = [],\n onSubmit,\n isEditing,\n disabled,\n isLoading,\n isOpen,\n onOpen,\n onClose,\n}) => {\n const { projectName, entities, projectInfo, scope, currentTab, mentionSuggestionsData } =\n useFeedContext()\n\n const {\n users: mentionUsers,\n versions: mentionVersions,\n tasks: mentionTasks,\n } = mentionSuggestionsData || {}\n\n const [initHeight, setInitHeight] = useState(88)\n const [editorValue, setEditorValue] = useState('')\n // file uploads\n const [files, setFiles] = useState(initFiles)\n const [filesUploading, setFilesUploading] = useState([])\n const [isDropping, setIsDropping] = useState(false)\n const [isSubmitting, setIsSubmitting] = useState(false)\n\n const { annotations, removeAnnotation, goToAnnotation } = useAnnotationsSync({\n entityId: entities[0]?.id,\n filesUploading,\n })\n\n // MENTION STATES\n const [mention, setMention] = useState<null | any>(null)\n const [mentionSelectedIndex, setMentionSelectedIndex] = useState(0)\n // REFS\n const editorRef = useRef<any>(null)\n const markdownRef = useRef<HTMLDivElement>(null)\n\n // if there is an initial value, set it so the editor is prefilled\n useInitialValue({\n markdownRef,\n initValue,\n setEditorValue,\n setInitHeight,\n isOpen: isOpen,\n filter: currentTab,\n })\n\n // When editing, set selection to the end of the editor\n useSetCursorEnd({ initHeight, editorRef, isEditing })\n // create a new quill format for mentions and registers it\n useMentionLink({ projectName })\n\n // focus on editor when opened\n useEffect(() => {\n if (isOpen) {\n editorRef.current?.getEditor()?.enable()\n // block autofocus if opened from an annotation\n if (annotations.length > 0 && files.length === 0) {\n return\n }\n\n editorRef.current?.focus()\n }\n // We don't set annotations or files as useEffect dependencies, because we don't want to focus\n // the input if it's already open but annotations change (e.g. are removed).\n }, [isOpen, editorRef])\n\n mentionTypes.sort((a, b) => b.length - a.length)\n\n const mentionOptions = useMemo(\n () =>\n getMentionOptions(\n mention?.type,\n {\n '@': () => getMentionUsers(mentionUsers),\n '@@': () => getMentionVersions(mentionVersions),\n '@@@': () => getMentionTasks(mentionTasks, projectInfo.taskTypes),\n },\n mention?.search,\n ),\n [mentionTasks, mentionVersions, mentionUsers, mention?.type, mention?.search],\n )\n\n // show first 5 and filter itself out\n const shownMentionOptions = mentionOptions.slice(0, 5)\n\n // triggered when a mention is selected\n const [newSelection, setNewSelection] = useState<null | number>()\n\n useEffect(() => {\n if (newSelection) {\n setNewSelection(null)\n // now we set selection to the end of the mention\n const quill = editorRef.current.getEditor()\n quill.setSelection(newSelection)\n }\n }, [newSelection])\n\n const handleSelectMention = (selectedOption: any) => {\n // get option text\n const quill = editorRef.current.getEditor()\n\n const typePrefix = mention.type // the type of mention: @, @@, @@@\n const search = typePrefix + (mention.search || '') // the full search string: @Tim\n const mentionLabel = typePrefix + selectedOption.label // the label of the mention: @Tim Bailey\n // @ts-expect-error\n const type = mentionTypeOptions[typePrefix] // the type of mention: user, version, task\n const href = `${type?.id}:${selectedOption.id}` // the href of the mention: user:user.123\n\n // get selection delta\n const selection = quill.getSelection(true)\n const selectionIndex = selection?.index || 0\n const startIndex = selectionIndex - search.length // the start index of the search\n\n // first delete the search string\n quill.deleteText(startIndex, search.length)\n\n // insert embed link\n quill.insertText(startIndex, mentionLabel, 'mention', href)\n\n const endIndex = startIndex + mentionLabel.length\n\n // insert a space after the mention\n quill.updateContents(new Delta().retain(endIndex).insert(' '))\n\n // remove single \\n after mention\n quill.updateContents(new Delta().retain(endIndex + 1).delete(1))\n\n // set selection to the end of the mention + 1\n setNewSelection(endIndex + 1)\n\n // reset mention state\n setMention(null)\n setMentionSelectedIndex(0)\n }\n\n const handleSelectChange = (option: any) => {\n handleSelectMention(option)\n }\n\n const handleChange = (content: string, delta: any, _: any, editor: any) => {\n let currentCharacter =\n (delta.ops[0] && delta.ops[0].insert) || (delta.ops[1] && delta.ops[1].insert)\n\n const tabOrEnter = currentCharacter === '\\n' || currentCharacter === '\\t'\n // find the first option\n const selectedOption = mentionOptions[mentionSelectedIndex]\n\n if (mention && tabOrEnter && selectedOption) {\n // get option text\n const retain = (delta.ops[0] && delta.ops[0].retain) || 0\n // prevent default\n\n // @ts-ignore\n handleSelectMention(selectedOption, retain)\n\n return\n }\n\n setEditorValue(content)\n\n const isDelete = delta.ops.length === 2 && !!delta.ops[1].delete\n\n if (!currentCharacter && isDelete) {\n currentCharacter = editor.getText(delta.ops[0].retain - 1, 1)\n }\n\n const isMention = mentionTypes.includes(currentCharacter)\n\n if (isMention) {\n const mentionIndex = delta.ops.findIndex((op: any) => 'insert' in op || 'delete' in op)\n const mention = currentCharacter\n let retain = mentionIndex === 0 ? 0 : delta.ops[mentionIndex - 1].retain\n if (isDelete) retain = retain - 1\n\n // for each mention denotation char, check if it is a mention\n // sort by length of mention denotation char\n let mentionMatch = null\n\n // loop through each mention denotation char, with longest first. First one to match is the one we want\n for (const chars of mentionTypes) {\n let isMatch = true\n // start with the last character\n if (chars.endsWith(mention)) {\n // loop through the chars backwards\n for (let i = chars.length - 1; i >= 0; i--) {\n // skip first character as that's already been checked\n if (i === 0) continue\n const char = chars[i - 1]\n const indexInDelta = retain - (chars.length - i)\n const valueCharAtIndex = editor.getText(indexInDelta, 1)\n if (valueCharAtIndex !== char) {\n isMatch = false\n break\n }\n }\n } else {\n isMatch = false\n }\n\n if (isMatch) {\n // console.log('match!!!', chars)\n mentionMatch = chars\n break\n }\n }\n\n if (mentionMatch) {\n setMention({\n type: mentionMatch,\n retain: retain,\n })\n } else {\n setMention(null)\n setMentionSelectedIndex(0)\n }\n } else {\n // get full string between mention and new delta\n // This is where SEARCH is handled\n if (mention) {\n const retain = delta.ops[0].retain\n // if space is pressed, remove mention\n if (currentCharacter === ' ' || !retain) {\n setMention(null)\n setMentionSelectedIndex(0)\n return\n }\n\n let distanceMentionToRetain = retain - mention.retain\n if (!isDelete) distanceMentionToRetain++\n const mentionFull = editor.getText(mention.retain, distanceMentionToRetain)\n const mentionSearch = mentionFull.replace(mention.type.slice(-1), '')\n // check for space in mentionFull\n if (mentionFull.includes(' ')) {\n setMention(null)\n setMentionSelectedIndex(0)\n } else {\n setMention({\n ...mention,\n search: mentionSearch?.toLowerCase(),\n })\n }\n } else {\n // just deleting any text\n const quill = editorRef.current.getEditor()\n const currentSelection = quill.getSelection(false)\n const currentFormat = quill.getFormat(currentSelection?.index, currentSelection?.length)\n if (currentFormat.mention) {\n // if format is mention, delete the whole mention\n const [lineBlock] = quill.getLine(currentSelection.index - 1) || []\n const ops = lineBlock?.cache?.delta?.ops || []\n // get last op with attributes mention: true\n const lastMentionOp = ops.reverse().find((op: any) => op.attributes?.mention)\n if (lastMentionOp) {\n const mentionLength = lastMentionOp.insert.length\n quill.deleteText(currentSelection.index - mentionLength, mentionLength)\n }\n }\n }\n }\n }\n\n const addTextToEditor = (type: string) => {\n // get editor retain\n const quill = editorRef.current.getEditor()\n\n let retain = quill.getSelection(true)?.index || 0\n\n // get character at retain\n const currentCharacter = quill.getText(retain - 1, 1)\n\n // if the current character is a character, increment retain\n const addSpace = currentCharacter !== ' ' && currentCharacter\n if (addSpace) {\n quill.insertText(retain, ' ')\n retain++\n }\n\n // This is hack AF, but it works\n typeWithDelay(quill, retain, type)\n }\n\n const handleMentionButton = (type: string) => {\n // first check if mention is already open\n if (mention) {\n const { type, retain, search = '' } = mention\n\n const quill = editorRef.current.getEditor()\n const length = type.length + search.length\n const start = retain - type.length + 1\n // delete the mention\n quill.deleteText(start, length)\n }\n\n addTextToEditor(type)\n }\n\n const handleOpenClick = () => {\n if (isOpen || disabled) return\n\n onOpen && onOpen()\n }\n\n const handleClose = () => {\n // get editor value\n const editor = editorRef.current.getEditor()\n const text = editor.getText()\n if (text.length < 2 || isEditing) {\n setEditorValue('')\n }\n\n // always close editor\n onClose && onClose()\n }\n\n const handleFileUploaded = ({ file, data }: any) => {\n const newFile = {\n id: data.id,\n name: file.name,\n mime: file.type,\n size: file.size,\n order: files.length,\n }\n\n setFiles((prev) => [...prev, newFile])\n // remove from uploading\n setFilesUploading((prev) => prev.filter((uploading: any) => uploading.name !== file.name))\n\n return newFile\n }\n\n const handleFileRemove = (id: string, name: string, isUnsavedAnnotation: boolean) => {\n if (isUnsavedAnnotation) {\n // remove from annotations (if it's an unsaved annotation)\n removeAnnotation?.(id)\n } else {\n // remove file from files\n setFiles((prev) => prev.filter((file) => file.id !== id))\n // remove from uploading\n setFilesUploading((prev) => {\n return prev.filter((file: any) => file.name !== name)\n })\n }\n }\n\n const handleFileProgress = (e: any, file: any) => {\n const progress = Math.round((e.loaded * 100) / e.total)\n if (progress !== 100) {\n const uploadProgress = {\n name: file.name,\n progress,\n type: file.type,\n order: files.length + filesUploading.length,\n }\n\n // @ts-ignore\n setFilesUploading((prev) => {\n // replace or add new progress\n const newProgress = prev.filter((name: any) => name.name !== file.name)\n return [...newProgress, uploadProgress]\n })\n }\n }\n\n // when a file is not dropped onto the comment input\n const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {\n setIsDropping(false)\n // upload file\n handleFileDrop(e, projectName, handleFileProgress, handleFileUploaded)\n }\n\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n e.stopPropagation()\n setIsDropping(true)\n }\n\n const uploadAnnotations = useAnnotationsUpload({\n projectName,\n onSuccess: handleFileUploaded,\n })\n\n const handleSubmit = async () => {\n try {\n setIsSubmitting(true)\n // upload any annotations first\n let annotationFiles = []\n let annotationMetadata: SavedAnnotationMetadata[] = []\n\n if (annotations.length) {\n const { files, metadata } = await uploadAnnotations(annotations)\n annotationFiles = files\n annotationMetadata = metadata\n }\n\n // convert to markdown\n const [markdown] = convertToMarkdown(editorValue)\n\n // remove img query params\n const markdownParsed = parseImages(markdown)\n\n const uploadedFiles = [...files, ...annotationFiles]\n\n if ((markdownParsed || uploadedFiles.length) && onSubmit) {\n try {\n await onSubmit(markdownParsed, uploadedFiles, { annotations: annotationMetadata })\n // only clear if onSubmit is successful\n setEditorValue('')\n setFiles([])\n } catch (error) {\n // error is handled in rtk query mutation\n return\n }\n }\n } catch (error) {\n console.error(error)\n toast.error('Something went wrong')\n } finally {\n setIsSubmitting(false)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (mention) {\n // close mention on escape\n if (e.key === 'Escape') {\n setMention(null)\n setMentionSelectedIndex(0)\n return\n }\n\n // add top search of mention\n if (mention && e.key === 'Tab') {\n // we handle this in the onChange\n }\n\n const arrowDirection = e.key === 'ArrowUp' ? -1 : e.key === 'ArrowDown' ? 1 : 0\n\n if (arrowDirection) {\n // navigate through mentions\n e.preventDefault()\n let newIndex = mentionSelectedIndex + arrowDirection\n if (newIndex < 0) newIndex = shownMentionOptions.length - 1\n if (newIndex >= shownMentionOptions.length) newIndex = 0\n setMentionSelectedIndex(newIndex)\n }\n\n if (e.key === 'Enter') {\n // we handle this in the onChange\n }\n }\n\n if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {\n handleSubmit()\n }\n\n if (e.key === 'Escape') {\n handleClose()\n }\n }\n\n let quillMinHeight: number | undefined = isOpen ? initHeight + 41 : 44\n if (isEditing) quillMinHeight = undefined\n\n // QUILL CONFIG\n const modules = useMemo(\n () =>\n getModules({\n imageUploader: {\n projectName,\n onUpload: handleFileUploaded,\n onUploadProgress: handleFileProgress,\n },\n }),\n [projectName, setFiles, setFilesUploading],\n )\n\n const allFiles = [...annotations, ...(files || []), ...filesUploading].sort(\n (a, b) => a.order - b.order,\n )\n const compactGrid = allFiles.length > 6\n\n // disable version mentions for folders\n let mentionsError = null\n if (entities.length && entities[0].entityType === 'folder') {\n if (mention?.type === '@@') {\n mentionsError = 'Version mentions are disabled for folders'\n }\n }\n\n return (\n <>\n <Styled.AutoHeight\n className={clsx('comment-container', { isOpen, isEditing })}\n onDragOver={handleDragOver}\n onDragLeave={() => setIsDropping(false)}\n onDrop={handleDrop}\n onClick={() => setIsDropping(false)}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <Styled.Comment\n className={clsx('block-shortcuts', {\n isOpen,\n isClosed: !isOpen || disabled,\n isEditing,\n isDropping,\n disabled,\n isLoading,\n isSubmitting,\n })}\n onKeyDown={handleKeyDown}\n onClick={handleOpenClick}\n >\n <Styled.Markdown ref={markdownRef}>\n {/* this is purely used to translate the markdown into html for Editor */}\n <InputMarkdownConvert typeOptions={mentionTypeOptions} initValue={initValue} />\n </Styled.Markdown>\n\n {/* file uploads */}\n {isOpen && (\n <FilesGrid\n files={allFiles}\n isCompact={compactGrid}\n onRemove={handleFileRemove}\n style={{ borderBottom: '1px solid var(--md-sys-color-outline-variant)' }}\n projectName={projectName}\n onAnnotationClick={goToAnnotation}\n />\n )}\n {isOpen && !disabled ? (\n <ReactQuill\n theme=\"snow\"\n style={{ minHeight: quillMinHeight, maxHeight: 300 }}\n ref={editorRef}\n value={editorValue}\n onChange={handleChange}\n readOnly={!isOpen}\n placeholder={'Comment or mention with @user, @@version, @@@task...'}\n modules={modules}\n formats={quillFormats}\n />\n ) : (\n <Styled.Placeholder>\n {disabled ? 'Commenting is disabled across multiple projects.' : 'Add a comment...'}\n </Styled.Placeholder>\n )}\n\n <Styled.Footer>\n <Styled.Buttons>\n {/* mention a user */}\n <Button\n icon=\"person\"\n variant=\"text\"\n onClick={() => handleMentionButton('@')}\n data-tooltip={'Mention user'}\n data-shortcut={'@'}\n />\n {/* mention a version */}\n <Button\n icon=\"layers\"\n variant=\"text\"\n onClick={() => handleMentionButton('@@')}\n data-tooltip={'Mention version'}\n data-shortcut={'@@'}\n />\n {/* mention a task */}\n <Button\n icon=\"check_circle\"\n variant=\"text\"\n onClick={() => handleMentionButton('@@@')}\n data-tooltip={'Mention task'}\n data-shortcut={'@@@'}\n />\n </Styled.Buttons>\n <Styled.Buttons>\n {isEditing && (\n <Button variant=\"text\" onClick={handleClose}>\n Cancel\n </Button>\n )}\n <SaveButton\n label={isEditing ? 'Save' : 'Comment'}\n className=\"comment\"\n active={!!editorValue || !!files.length}\n onClick={handleSubmit}\n disabled={isLoading}\n />\n </Styled.Buttons>\n </Styled.Footer>\n\n <Styled.Dropzone className={clsx({ show: isDropping && isOpen })}>\n <Icon icon=\"cloud_upload\" />\n </Styled.Dropzone>\n </Styled.Comment>\n <CommentMentionSelect\n mention={mention}\n options={shownMentionOptions}\n onChange={handleSelectChange}\n types={mentionTypes}\n z\n // @ts-ignore\n config={mentionTypeOptions[mention?.type]}\n noneFound={!shownMentionOptions.length && mention?.search}\n noneFoundAtAll={!shownMentionOptions.length && !mention?.search}\n selectedIndex={mentionSelectedIndex}\n // @ts-ignore\n error={mentionsError}\n />\n </Styled.AutoHeight>\n </>\n )\n}\n\nexport default CommentInput\n"],"names":["_a","mention","type","files","jsx","Fragment","jsxs","Styled.AutoHeight","Styled.Comment","Styled.Markdown","Styled.Placeholder","Styled.Footer","Styled.Buttons","Styled.Dropzone"],"mappings":"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"}
|