From a3033203af926b73f8b72f45028248c22e30315e Mon Sep 17 00:00:00 2001 From: Palanikannan1437 <73993394+Palanikannan1437@users.noreply.github.com> Date: Wed, 21 Feb 2024 18:26:49 +0530 Subject: [PATCH] mentions loading state part done --- .../core/src/types/mention-suggestion.ts | 6 + .../editor/core/src/ui/extensions/index.tsx | 148 +++++++++--------- .../editor/core/src/ui/mentions/custom.tsx | 17 +- .../editor/core/src/ui/mentions/index.tsx | 112 ++++++++++++- .../core/src/ui/mentions/mention-list.tsx | 2 + .../src/ui/mentions/mention-node-view.tsx | 6 +- .../editor/core/src/ui/mentions/suggestion.ts | 133 +++++++++------- .../editor/document-editor/src/ui/index.tsx | 16 +- .../document-editor/src/ui/readonly/index.tsx | 4 + .../comments/comment-create.tsx | 1 - web/hooks/store/use-mention.ts | 57 +++++-- .../projects/[projectId]/pages/[pageId].tsx | 21 ++- web/store/mention.store.ts | 5 +- yarn.lock | 18 ++- 14 files changed, 375 insertions(+), 171 deletions(-) diff --git a/packages/editor/core/src/types/mention-suggestion.ts b/packages/editor/core/src/types/mention-suggestion.ts index dcaa3148d..9e0b11137 100644 --- a/packages/editor/core/src/types/mention-suggestion.ts +++ b/packages/editor/core/src/types/mention-suggestion.ts @@ -1,3 +1,4 @@ +import { Editor, Range } from "@tiptap/react"; export type IMentionSuggestion = { id: string; type: string; @@ -7,4 +8,9 @@ export type IMentionSuggestion = { redirect_uri: string; }; +export type CommandProps = { + editor: Editor; + range: Range; +}; + export type IMentionHighlight = string; diff --git a/packages/editor/core/src/ui/extensions/index.tsx b/packages/editor/core/src/ui/extensions/index.tsx index 5bfba3b0f..e413aa9c1 100644 --- a/packages/editor/core/src/ui/extensions/index.tsx +++ b/packages/editor/core/src/ui/extensions/index.tsx @@ -35,79 +35,81 @@ export const CoreEditorExtensions = ( deleteFile: DeleteImage, restoreFile: RestoreImage, cancelUploadImage?: () => any -) => [ - StarterKit.configure({ - bulletList: { - HTMLAttributes: { - class: "list-disc list-outside leading-3 -mt-2", +) => { + return [ + StarterKit.configure({ + bulletList: { + HTMLAttributes: { + class: "list-disc list-outside leading-3 -mt-2", + }, }, - }, - orderedList: { - HTMLAttributes: { - class: "list-decimal list-outside leading-3 -mt-2", + orderedList: { + HTMLAttributes: { + class: "list-decimal list-outside leading-3 -mt-2", + }, }, - }, - listItem: { - HTMLAttributes: { - class: "leading-normal -mb-2", + listItem: { + HTMLAttributes: { + class: "leading-normal -mb-2", + }, }, - }, - code: false, - codeBlock: false, - horizontalRule: { - HTMLAttributes: { class: "mt-4 mb-4" }, - }, - blockquote: false, - dropcursor: { - color: "rgba(var(--color-text-100))", - width: 2, - }, - }), - CustomQuoteExtension.configure({ - HTMLAttributes: { className: "border-l-4 border-custom-border-300" }, - }), - CustomKeymap, - ListKeymap, - CustomLinkExtension.configure({ - openOnClick: true, - autolink: true, - linkOnPaste: true, - protocols: ["http", "https"], - validate: (url: string) => isValidHttpUrl(url), - HTMLAttributes: { - class: - "text-custom-primary-300 underline underline-offset-[3px] hover:text-custom-primary-500 transition-colors cursor-pointer", - }, - }), - ImageExtension(deleteFile, restoreFile, cancelUploadImage).configure({ - HTMLAttributes: { - class: "rounded-lg border border-custom-border-300", - }, - }), - TiptapUnderline, - TextStyle, - Color, - TaskList.configure({ - HTMLAttributes: { - class: "not-prose pl-2", - }, - }), - TaskItem.configure({ - HTMLAttributes: { - class: "flex items-start my-4", - }, - nested: true, - }), - CustomCodeBlockExtension, - CustomCodeInlineExtension, - Markdown.configure({ - html: true, - transformCopiedText: true, - transformPastedText: true, - }), - Table, - TableHeader, - TableCell, - TableRow, - Mentions(mentionConfig.mentionSuggestions, mentionConfig.mentionHighlights, false), -]; + code: false, + codeBlock: false, + horizontalRule: { + HTMLAttributes: { class: "mt-4 mb-4" }, + }, + blockquote: false, + dropcursor: { + color: "rgba(var(--color-text-100))", + width: 2, + }, + }), + CustomQuoteExtension.configure({ + HTMLAttributes: { className: "border-l-4 border-custom-border-300" }, + }), + CustomKeymap, + ListKeymap, + CustomLinkExtension.configure({ + openOnClick: true, + autolink: true, + linkOnPaste: true, + protocols: ["http", "https"], + validate: (url: string) => isValidHttpUrl(url), + HTMLAttributes: { + class: + "text-custom-primary-300 underline underline-offset-[3px] hover:text-custom-primary-500 transition-colors cursor-pointer", + }, + }), + ImageExtension(deleteFile, restoreFile, cancelUploadImage).configure({ + HTMLAttributes: { + class: "rounded-lg border border-custom-border-300", + }, + }), + TiptapUnderline, + TextStyle, + Color, + TaskList.configure({ + HTMLAttributes: { + class: "not-prose pl-2", + }, + }), + TaskItem.configure({ + HTMLAttributes: { + class: "flex items-start my-4", + }, + nested: true, + }), + CustomCodeBlockExtension, + CustomCodeInlineExtension, + Markdown.configure({ + html: true, + transformCopiedText: true, + transformPastedText: true, + }), + Table, + TableHeader, + TableCell, + TableRow, + Mentions(mentionConfig.mentionSuggestions, mentionConfig.mentionHighlights, false), + ]; +}; diff --git a/packages/editor/core/src/ui/mentions/custom.tsx b/packages/editor/core/src/ui/mentions/custom.tsx index e723ca0d7..d41b06420 100644 --- a/packages/editor/core/src/ui/mentions/custom.tsx +++ b/packages/editor/core/src/ui/mentions/custom.tsx @@ -32,6 +32,12 @@ export const CustomMention = Mention.extend({ redirect_uri: { default: "/", }, + entity_identifier: { + default: null, + }, + entity_name: { + default: null, + }, }; }, @@ -43,17 +49,6 @@ export const CustomMention = Mention.extend({ return [ { tag: "mention-component", - getAttrs: (node: string | HTMLElement) => { - if (typeof node === "string") { - return null; - } - return { - id: node.getAttribute("data-mention-id") || "", - target: node.getAttribute("data-mention-target") || "", - label: node.innerText.slice(1) || "", - redirect_uri: node.getAttribute("redirect_uri"), - }; - }, }, ]; }, diff --git a/packages/editor/core/src/ui/mentions/index.tsx b/packages/editor/core/src/ui/mentions/index.tsx index f6d3e5b1f..15637e516 100644 --- a/packages/editor/core/src/ui/mentions/index.tsx +++ b/packages/editor/core/src/ui/mentions/index.tsx @@ -1,15 +1,115 @@ -// @ts-nocheck - -import { Suggestion } from "src/ui/mentions/suggestion"; import { CustomMention } from "src/ui/mentions/custom"; -import { IMentionHighlight } from "src/types/mention-suggestion"; +import { IMentionHighlight, IMentionSuggestion } from "src/types/mention-suggestion"; +import { ReactRenderer } from "@tiptap/react"; +import { Editor } from "@tiptap/core"; +import tippy from "tippy.js"; -export const Mentions = (mentionSuggestions: IMentionSuggestion[], mentionHighlights: IMentionHighlight[], readonly) => +import { v4 as uuidv4 } from "uuid"; +import { MentionList } from "src/ui/mentions/mention-list"; + +export const getSuggestionItems = + (getSuggestions: () => Promise) => + async ({ query }: { query: string }) => { + console.log("yaa"); + const suggestions = await getSuggestions(); + const mappedSuggestions: IMentionSuggestion[] = suggestions.map((suggestion): IMentionSuggestion => { + const transactionId = uuidv4(); + return { + ...suggestion, + id: transactionId, + }; + }); + const filteredSuggestions = mappedSuggestions + .filter((suggestion) => suggestion.title.toLowerCase().startsWith(query.toLowerCase())) + .slice(0, 5); + + console.log("yoo", filteredSuggestions); + return filteredSuggestions; + }; + +export const Mentions = ( + mentionSuggestions: () => Promise, + mentionHighlights: IMentionHighlight[], + readonly: boolean +) => CustomMention.configure({ HTMLAttributes: { class: "mention", }, readonly: readonly, mentionHighlights: mentionHighlights, - suggestion: Suggestion(mentionSuggestions), + suggestion: { + items: ({ query }) => { + const suggestions = mentionSuggestions(); + const mappedSuggestions: IMentionSuggestion[] = suggestions.map((suggestion): IMentionSuggestion => { + const transactionId = uuidv4(); + return { + ...suggestion, + id: transactionId, + }; + }); + const filteredSuggestions = mappedSuggestions + .filter((suggestion) => suggestion.title.toLowerCase().startsWith(query.toLowerCase())) + .slice(0, 5); + + console.log("yoo", filteredSuggestions); + return filteredSuggestions; + }, + // @ts-ignore + render: () => { + let reactRenderer: ReactRenderer | null = null; + let popup: any | null = null; + + return { + onStart: (props: { editor: Editor; clientRect: DOMRect }) => { + props.editor.storage.mentionsOpen = true; + reactRenderer = new ReactRenderer(MentionList, { + props, + editor: props.editor, + }); + // @ts-ignore + popup = tippy("body", { + getReferenceClientRect: props.clientRect, + appendTo: () => document.querySelector("#editor-container"), + content: reactRenderer.element, + showOnCreate: true, + interactive: true, + trigger: "manual", + placement: "bottom-start", + }); + }, + + onUpdate: (props: { editor: Editor; clientRect: DOMRect }) => { + reactRenderer?.updateProps(props); + + popup && + popup[0].setProps({ + getReferenceClientRect: props.clientRect, + }); + }, + onKeyDown: (props: { event: KeyboardEvent }) => { + if (props.event.key === "Escape") { + popup?.[0].hide(); + + return true; + } + + const navigationKeys = ["ArrowUp", "ArrowDown", "Enter"]; + + if (navigationKeys.includes(props.event.key)) { + // @ts-ignore + reactRenderer?.ref?.onKeyDown(props); + event?.stopPropagation(); + return true; + } + return false; + }, + onExit: (props: { editor: Editor; event: KeyboardEvent }) => { + props.editor.storage.mentionsOpen = false; + popup?.[0].destroy(); + reactRenderer?.destroy(); + }, + }; + }, + }, }); diff --git a/packages/editor/core/src/ui/mentions/mention-list.tsx b/packages/editor/core/src/ui/mentions/mention-list.tsx index afbf10970..b7ec14ecc 100644 --- a/packages/editor/core/src/ui/mentions/mention-list.tsx +++ b/packages/editor/core/src/ui/mentions/mention-list.tsx @@ -19,6 +19,8 @@ export const MentionList = forwardRef((props: MentionListProps, ref) => { props.command({ id: item.id, label: item.title, + entity_identifier: item.entity_identifier, + entity_name: item.entity_name, target: "users", redirect_uri: item.redirect_uri, }); diff --git a/packages/editor/core/src/ui/mentions/mention-node-view.tsx b/packages/editor/core/src/ui/mentions/mention-node-view.tsx index 1c3755f6c..b58ad4eb2 100644 --- a/packages/editor/core/src/ui/mentions/mention-node-view.tsx +++ b/packages/editor/core/src/ui/mentions/mention-node-view.tsx @@ -20,13 +20,13 @@ export const MentionNodeView = (props) => { @{props.node.attrs.label} diff --git a/packages/editor/core/src/ui/mentions/suggestion.ts b/packages/editor/core/src/ui/mentions/suggestion.ts index 40e75a1e3..5b66a7433 100644 --- a/packages/editor/core/src/ui/mentions/suggestion.ts +++ b/packages/editor/core/src/ui/mentions/suggestion.ts @@ -2,65 +2,80 @@ import { ReactRenderer } from "@tiptap/react"; import { Editor } from "@tiptap/core"; import tippy from "tippy.js"; -import { MentionList } from "src/ui/mentions/mention-list"; +import { v4 as uuidv4 } from "uuid"; import { IMentionSuggestion } from "src/types/mention-suggestion"; +import { MentionList } from "src/ui/mentions/mention-list"; -export const Suggestion = (suggestions: IMentionSuggestion[]) => ({ - items: ({ query }: { query: string }) => - suggestions.filter((suggestion) => suggestion.title.toLowerCase().startsWith(query.toLowerCase())).slice(0, 5), - render: () => { - let reactRenderer: ReactRenderer | null = null; - let popup: any | null = null; +export const getSuggestionItems = (suggestions: IMentionSuggestion[]) => { + return ({ query }: { query: string }) => { + const mappedSuggestions: IMentionSuggestion[] = suggestions.map((suggestion): IMentionSuggestion => { + const transactionId = uuidv4(); + return { + ...suggestion, + id: transactionId, + }; + }); + return mappedSuggestions + .filter((suggestion) => suggestion.title.toLowerCase().startsWith(query.toLowerCase())) + .slice(0, 5); + }; +}; - return { - onStart: (props: { editor: Editor; clientRect: DOMRect }) => { - props.editor.storage.mentionsOpen = true; - reactRenderer = new ReactRenderer(MentionList, { - props, - editor: props.editor, - }); - // @ts-ignore - popup = tippy("body", { - getReferenceClientRect: props.clientRect, - appendTo: () => document.querySelector("#editor-container"), - content: reactRenderer.element, - showOnCreate: true, - interactive: true, - trigger: "manual", - placement: "bottom-start", - }); - }, - - onUpdate: (props: { editor: Editor; clientRect: DOMRect }) => { - reactRenderer?.updateProps(props); - - popup && - popup[0].setProps({ - getReferenceClientRect: props.clientRect, - }); - }, - onKeyDown: (props: { event: KeyboardEvent }) => { - if (props.event.key === "Escape") { - popup?.[0].hide(); - - return true; - } - - const navigationKeys = ["ArrowUp", "ArrowDown", "Enter"]; - - if (navigationKeys.includes(props.event.key)) { - // @ts-ignore - reactRenderer?.ref?.onKeyDown(props); - event?.stopPropagation(); - return true; - } - return false; - }, - onExit: (props: { editor: Editor; event: KeyboardEvent }) => { - props.editor.storage.mentionsOpen = false; - popup?.[0].destroy(); - reactRenderer?.destroy(); - }, - }; - }, -}); +// export const Suggestion = (suggestions: IMentionSuggestion[]) => ({ +// items: getSuggestionItems(suggestions), +// render: () => { +// let reactRenderer: ReactRenderer | null = null; +// let popup: any | null = null; +// +// return { +// onStart: (props: { editor: Editor; clientRect: DOMRect }) => { +// props.editor.storage.mentionsOpen = true; +// reactRenderer = new ReactRenderer(MentionList, { +// props, +// editor: props.editor, +// }); +// // @ts-ignore +// popup = tippy("body", { +// getReferenceClientRect: props.clientRect, +// appendTo: () => document.querySelector("#editor-container"), +// content: reactRenderer.element, +// showOnCreate: true, +// interactive: true, +// trigger: "manual", +// placement: "bottom-start", +// }); +// }, +// +// onUpdate: (props: { editor: Editor; clientRect: DOMRect }) => { +// reactRenderer?.updateProps(props); +// +// popup && +// popup[0].setProps({ +// getReferenceClientRect: props.clientRect, +// }); +// }, +// onKeyDown: (props: { event: KeyboardEvent }) => { +// if (props.event.key === "Escape") { +// popup?.[0].hide(); +// +// return true; +// } +// +// const navigationKeys = ["ArrowUp", "ArrowDown", "Enter"]; +// +// if (navigationKeys.includes(props.event.key)) { +// // @ts-ignore +// reactRenderer?.ref?.onKeyDown(props); +// event?.stopPropagation(); +// return true; +// } +// return false; +// }, +// onExit: (props: { editor: Editor; event: KeyboardEvent }) => { +// props.editor.storage.mentionsOpen = false; +// popup?.[0].destroy(); +// reactRenderer?.destroy(); +// }, +// }; +// }, +// }); diff --git a/packages/editor/document-editor/src/ui/index.tsx b/packages/editor/document-editor/src/ui/index.tsx index 2491e04c7..c8fc8b1d9 100644 --- a/packages/editor/document-editor/src/ui/index.tsx +++ b/packages/editor/document-editor/src/ui/index.tsx @@ -1,6 +1,13 @@ "use client"; import React, { useState } from "react"; -import { UploadImage, DeleteImage, RestoreImage, getEditorClassNames, useEditor } from "@plane/editor-core"; +import { + UploadImage, + DeleteImage, + RestoreImage, + getEditorClassNames, + useEditor, + IMentionSuggestion, +} from "@plane/editor-core"; import { DocumentEditorExtensions } from "src/ui/extensions"; import { IDuplicationConfig, IPageArchiveConfig, IPageLockConfig } from "src/types/menu-actions"; import { EditorHeader } from "src/ui/components/editor-header"; @@ -43,6 +50,9 @@ interface IDocumentEditor { debouncedUpdatesEnabled?: boolean; isSubmitting: "submitting" | "submitted" | "saved"; + mentionHighlights?: string[]; + mentionSuggestions?: IMentionSuggestion[]; + // embed configuration duplicationConfig?: IDuplicationConfig; pageLockConfig?: IPageLockConfig; @@ -66,6 +76,8 @@ const DocumentEditor = ({ editorContentCustomClassNames, value, uploadFile, + mentionHighlights, + mentionSuggestions, deleteFile, restoreFile, isSubmitting, @@ -109,6 +121,8 @@ const DocumentEditor = ({ cancelUploadImage, rerenderOnPropsChange, forwardedRef, + mentionSuggestions, + mentionHighlights, extensions: DocumentEditorExtensions(uploadFile, setHideDragHandleFunction, setIsSubmitting), }); diff --git a/packages/editor/document-editor/src/ui/readonly/index.tsx b/packages/editor/document-editor/src/ui/readonly/index.tsx index 7c49ffa83..58a9ec70a 100644 --- a/packages/editor/document-editor/src/ui/readonly/index.tsx +++ b/packages/editor/document-editor/src/ui/readonly/index.tsx @@ -22,6 +22,8 @@ interface IDocumentReadOnlyEditor { documentDetails: DocumentDetails; pageLockConfig?: IPageLockConfig; pageArchiveConfig?: IPageArchiveConfig; + mentionHighlights?: string[]; + pageDuplicationConfig?: IDuplicationConfig; onActionCompleteHandler: (action: { title: string; @@ -44,6 +46,7 @@ const DocumentReadOnlyEditor = ({ borderOnFocus, customClassName, value, + mentionHighlights, documentDetails, forwardedRef, pageDuplicationConfig, @@ -58,6 +61,7 @@ const DocumentReadOnlyEditor = ({ const editor = useReadOnlyEditor({ value, + mentionHighlights, forwardedRef, rerenderOnPropsChange, extensions: [IssueWidgetPlaceholder()], diff --git a/web/components/issues/issue-detail/issue-activity/comments/comment-create.tsx b/web/components/issues/issue-detail/issue-activity/comments/comment-create.tsx index bb79c9817..bf5b15266 100644 --- a/web/components/issues/issue-detail/issue-activity/comments/comment-create.tsx +++ b/web/components/issues/issue-detail/issue-activity/comments/comment-create.tsx @@ -81,7 +81,6 @@ export const IssueCommentCreate: FC = (props) => { render={({ field: { value, onChange } }) => ( { - console.log("yo"); handleSubmit(onSubmit)(e); }} cancelUploadImage={fileService.cancelUpload} diff --git a/web/hooks/store/use-mention.ts b/web/hooks/store/use-mention.ts index bf688053c..270a7764e 100644 --- a/web/hooks/store/use-mention.ts +++ b/web/hooks/store/use-mention.ts @@ -1,11 +1,50 @@ -import { useContext } from "react"; -// mobx store -import { StoreContext } from "contexts/store-context"; -// types -import { IMentionStore } from "store/mention.store"; +import useSWR from "swr"; -export const useMention = (): IMentionStore => { - const context = useContext(StoreContext); - if (context === undefined) throw new Error("useMention must be used within StoreProvider"); - return context.mention; +import { ProjectMemberService } from "services/project"; +import { IProjectMember } from "@plane/types"; +import { UserService } from "services/user.service"; +import { useRef, useEffect } from "react"; + +export const useMention = ({ workspaceSlug, projectId }: { workspaceSlug: string; projectId: string }) => { + const userService = new UserService(); + const projectMemberService = new ProjectMemberService(); + + const { data: projectMembers } = useSWR(["projectMembers", workspaceSlug, projectId], async () => { + const members = await projectMemberService.fetchProjectMembers(workspaceSlug, projectId); + const detailedMembers = await Promise.all( + members.map(async (member) => projectMemberService.getProjectMember(workspaceSlug, projectId, member.id)) + ); + return detailedMembers; + }); + + const projectMembersRef = useRef(); + + useEffect(() => { + if (projectMembers) { + projectMembersRef.current = projectMembers; + } + }, [projectMembers]); + + const { data: user } = useSWR("currentUser", async () => userService.currentUser()); + + const mentionHighlights = user ? [user.id] : []; + + const getMentionSuggestions = () => () => { + const mentionSuggestions = + projectMembersRef.current?.map((memberDetails) => ({ + entity_name: "user_mention", + entity_identifier: `${memberDetails?.member?.id}`, + type: "User", + title: `${memberDetails?.member?.display_name}`, + subtitle: memberDetails?.member?.email ?? "", + avatar: `${memberDetails?.member?.avatar}`, + redirect_uri: `/${workspaceSlug}/profile/${memberDetails?.member?.id}`, + })) || []; + + return mentionSuggestions; + }; + return { + getMentionSuggestions, + mentionHighlights, + }; }; diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx index 93a814d57..50a952d4b 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx @@ -6,7 +6,7 @@ import { ReactElement, useEffect, useRef, useState } from "react"; import { Controller, useForm } from "react-hook-form"; // hooks -import { useApplication, usePage, useUser, useWorkspace } from "hooks/store"; +import { useApplication, useMention, usePage, useUser, useWorkspace } from "hooks/store"; import useReloadConfirmations from "hooks/use-reload-confirmation"; import useToast from "hooks/use-toast"; // services @@ -29,6 +29,8 @@ import { NextPageWithLayout } from "lib/types"; import { EUserProjectRoles } from "constants/project"; import { useProjectPages } from "hooks/store/use-project-specific-pages"; import { IssuePeekOverview } from "components/issues"; +import { ProjectMemberService } from "services/project"; +import { UserService } from "services/user.service"; // services const fileService = new FileService(); @@ -84,8 +86,22 @@ const PageDetailsPage: NextPageWithLayout = observer(() => { : null ); + const projectMemberService = new ProjectMemberService(); + + const { data: projectMembers } = useSWR(["projectMembers", workspaceSlug, projectId], async () => { + const members = await projectMemberService.fetchProjectMembers(workspaceSlug, projectId); + const detailedMembers = await Promise.all( + members.map(async (member) => projectMemberService.getProjectMember(workspaceSlug, projectId, member.id)) + ); + console.log("ye toh chal", detailedMembers); + return detailedMembers; + }); + const pageStore = usePage(pageId as string); + // store hooks + const { getMentionSuggestions, mentionHighlights, mentionSuggestions } = useMention({ workspaceSlug, projectId }); + const { setShowAlert } = useReloadConfirmations(pageStore?.isSubmitting === "submitting"); useEffect( @@ -273,6 +289,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => { last_updated_at: updated_at, last_updated_by: updated_by, }} + mentionHighlights={mentionHighlights} pageLockConfig={userCanLock && !archived_at ? { action: unlockPage, is_locked: is_locked } : undefined} pageDuplicationConfig={userCanDuplicate && !archived_at ? { action: duplicate_page } : undefined} pageArchiveConfig={ @@ -300,6 +317,8 @@ const PageDetailsPage: NextPageWithLayout = observer(() => { last_updated_at: updated_at, last_updated_by: updated_by, }} + mentionSuggestions={getMentionSuggestions(projectMembers)} + mentionHighlights={mentionHighlights} uploadFile={fileService.getUploadFileFunction(workspaceSlug as string)} deleteFile={fileService.getDeleteImageFunction(workspaceId)} restoreFile={fileService.getRestoreImageFunction(workspaceId)} diff --git a/web/store/mention.store.ts b/web/store/mention.store.ts index 872efeb41..48553b2cc 100644 --- a/web/store/mention.store.ts +++ b/web/store/mention.store.ts @@ -33,9 +33,12 @@ export class MentionStore implements IMentionStore { const suggestions = (projectMemberIds ?? [])?.map((memberId) => { const memberDetails = this.rootStore.memberRoot.project.getProjectMemberDetails(memberId); + // __AUTO_GENERATED_PRINT_VAR_START__ + console.log("MentionStore#mentionSuggestions#(anon) memberDetails are: %s", memberDetails?.member.id); // __AUTO_GENERATED_PRINT_VAR_END__ return { - id: `${memberDetails?.member?.id}`, + entity_name: "user_mention", + entity_identifier: `${memberDetails?.member?.id}`, type: "User", title: `${memberDetails?.member?.display_name}`, subtitle: memberDetails?.member?.email ?? "", diff --git a/yarn.lock b/yarn.lock index 291c710bd..c5151b14f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5012,7 +5012,7 @@ fault@^2.0.0: dependencies: format "^0.2.0" -fflate@^0.4.1: +fflate@^0.4.8: version "0.4.8" resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae" integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA== @@ -7171,12 +7171,18 @@ postcss@^8.4.21, postcss@^8.4.23, postcss@^8.4.29: picocolors "^1.0.0" source-map-js "^1.0.2" -posthog-js@^1.88.4: - version "1.96.1" - resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.96.1.tgz#4f9719a24e4e14037b0e72d430194d7cdb576447" - integrity sha512-kv1vQqYMt2BV3YHS+wxsbGuP+tz+M3y1AzNhz8TfkpY1HT8W/ONT0i0eQpeRr9Y+d4x/fZ6M4cXG5GMvi9lRCA== +posthog-js@^1.105.0: + version "1.108.3" + resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.108.3.tgz#774353d7ad594b68e6f5e6cce0fe8b583562f455" + integrity sha512-Vi9lX/MhovsKIEdj2aJ5ioku9U/eMGY8/DzKf4EpyrElxPPdabAdCDRUa81eAqxC6npkOpkHskawUPLg20le4Q== dependencies: - fflate "^0.4.1" + fflate "^0.4.8" + preact "^10.19.3" + +preact@^10.19.3: + version "10.19.6" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.19.6.tgz#66007b67aad4d11899f583df1b0116d94a89b8f5" + integrity sha512-gympg+T2Z1fG1unB8NH29yHJwnEaCH37Z32diPDku316OTnRPeMbiRV9kTrfZpocXjdfnWuFUl/Mj4BHaf6gnw== prebuild-install@^7.1.1: version "7.1.1"